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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With