7

I Am trying to draw a vertical tree like structure with HTML and CSS. I have done it to some extent.

Fiddle

<!--
We will create a family tree using just CSS(3)
The markup will be simple nested lists
-->
<div class="tree">
    <ul>
        <li>
            <a href="#">Parent</a>
            <ul>
                <li><a href="#">Child</a>
                    <ul>
                        <li><a href="#">Grand Child</a></li>
                    </ul>
                </li>
                <li>
                    <a href="#">Child</a>
                    <ul>
                        <li><a href="#">Grand Child</a></li>
                        <li><a href="#">Grand Child</a>
                            <ul>
                                <li><a href="#">Great Grand Child</a></li>
                                <li><a href="#">Great Grand Child</a></li>
                            </ul>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>

In my case, a node can have maximum 2 childs, not more than that. I have got it working for the first child node. In case of second child, am not getting the vertical line to 100%(till its parent node).

I have tried doing some tweaks but none of them worked. What could I change to my CSS, so it will get all the nodes connected and looks like a tree?

Is it possible to do with CSS itself? or is it possible to by adding some javascript?

1 Answer 1

2

If you have a limited set of possibilities and not looking for something very dynamic, one thing you could do is add classes with different top and height for your :after pseudo element and apply classes in your html to you li elements depending on what each need. Something like that for example:

.tree li::after{
    content: '';
    position: absolute; top: 0;

    width: 3%; height: 50px;
    right: auto; left: -2.5%;

    border-bottom: 1px solid #ccc;
    border-left: 1px solid #ccc;
    border-radius: 0 0 0 5px;
    -webkit-border-radius: 0 0 0 5px;
    -moz-border-radius: 0 0 0 5px;
}
.tree li.two-step::after{
    top: -100px;
    height: 150px;
}

.tree li.three-step::after{
    top: -180px;
    height: 230px;
}

https://jsfiddle.net/g2ue3wL5/1/

EDIT:

Handling :after pseudo-elements dynamically isn't so easy (at least not for me...). There's not really a way to handle them directly, you have to go through their actual element, and even then you need to work with CSS. So a dynamic solution with :after wouldn't be the best approach I think.

But you could replace them with span, and work with jQuery. This gives you a relatively small and easy solution. First, add a span to each a element:

<li><a href="#">Child</a> <span></span>    
<li><a href="#">Grand Child</a><span></span>

Then, in your CSS replace :after with > span:

.tree li > span {
    content:'';
    position: absolute;
    top: 0;
    width: 3%;
    height: 50px;
    right: auto;
    left: -2.5%;
    border-bottom: 1px solid #ccc;
    border-left: 1px solid #ccc;
    border-radius: 0 0 0 5px;
    -webkit-border-radius: 0 0 0 5px;
    -moz-border-radius: 0 0 0 5px;
}

And you go through each of these span and make some calculations to set height and top depending on the parent:

$('.tree li > span').each(function () {
    var thisNewTop = $(this).closest('ul').offset().top - $(this).offset().top; 
    var thisNewHeight = $(this).offset().top - $(this).closest('ul').offset().top + 50;

    $(this).css({
        top: thisNewTop,
        height: thisNewHeight
    });
});

https://jsfiddle.net/g2ue3wL5/3/

The equivalent solution in plain javascript would be much longer, I think it's the kind of situation where jQuery can save a lot of time.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks Julien. The problem here is the depth of each node can be any number. I can't define two-step, three-step kind of classes, as there can be 99-step or n-step. So, is there any possibility to define these pseudo classes functionality dynamically?
From what I know, working dynamically with pseudo classes isn't so easy. I'd go with jQuery if you want something more flexible. See edit.
I hv tried with the jquery you have given. When I add/remove a node in list dynamically. The lines are not coming in appropriate height, even after redrawing the lines. jsfiddle.net/qvnw6510/10 (In jsfiddle, the function is not getting invoked when I add node. You can check the code in your machine.) I have tried debugging it, but couldn't resolve it. I find the calculation of height is not working as expected.
the calculations are fine, it's just that since they take into account height of the elements and this height takes into account the change to top that was made in the first drawLine, it's not working the second time. Simply resetting top to 0 allows to add dynamically. jsfiddle.net/qvnw6510/12
That did the trick Julien. Thanks. I have tried resetting the css before posting, may be I was doing something else wrong that time! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.