Reputation: 9363
I have a nested list like this :
<ul class="tree">
<li><div>Animals</div>
<ul>
<li><div>Birds</div>
<ul>
<li class="last"><div>Eagle</div></li>
</ul>
</li>
<li><div>Mammals</div>
<ul>
<li><div>Elephant</div></li>
<li class="last"><div>Cats</div>
<ul>
<li><div>Lion</div></li>
<li class="last"><div>Tiger</div></li>
</ul>
</li>
</ul>
</li>
<li class="last"><div>Reptiles</div>
<ul>
<li><div>Snake</li>
<li class="last"><div>Turtle</div></li>
</ul>
</li>
</ul>
</li>
</ul>
I'd like to style this so each level is indented, but I also wish to have each entire line highlighted when hovered. When I put a hover on DIV
, the highlighting only starts from the left-position of the containing UL
:
ul.tree, ul.tree ul {
list-style-type: none;
}
ul.tree li div:hover {
background-color: red;
}
Is there some way to achieve the effect I want, without defining multiple rules for li li
, li li li
, etc. ?
There could be an infinite number of levels of nesting, so I find it quite ugly to define all these different rules.
Or is there a way to calculate the level of nesting dynamically (in CSS?), so I could remove the padding of UL
and instead put the right amount of padding inside each DIV
?
UPDATE:
added a fiddle that shows what I want: http://jsfiddle.net/za3db/
You can see it's only indented on the second level, because I did not define the rule for the third, or fourth...
Upvotes: 3
Views: 2123
Reputation: 1244
I know this answer is a tad late, however I was working on a tree recently and had the exact same thought and found a solution by studying the way several products tackle it. The below snippet illustrates a possible solution by placing a fill div
for each item in the tree which has a large negative margin which allows it to cover the whole line. It's a very simple CSS
only solution.
Hopefully it will help you and others who come across this question + answer.
.fill {
display: none;
margin-left: -10000px;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
z-index: -1;
}
.title {
position: relative;
}
.title:hover .fill {
display: block;
background-color: #eee;
}
<ul class="tree">
<li>
<div class="title">
<div class="fill"></div>
Animals
</div>
<ul>
<li>
<div class="title">
<div class="fill"></div>
Birds
</div>
<ul>
<li class="last">
<div class="title">
<div class="fill"></div>
Eagle
</div>
</li>
</ul>
</li>
<li>
<div class="title">
<div class="fill"></div>
Mammals
</div>
<ul>
<li>
<div class="title">
<div class="fill"></div>
Elephant
</div>
</li>
<li class="last">
<div class="title">
<div class="fill"></div>
Cats
</div>
<ul>
<li>
<div class="title">
<div class="fill"></div>
Lion
</div>
</li>
<li class="last">
<div class="title">
<div class="fill"></div>
Tiger
</div>
</li>
</ul>
</li>
</ul>
</li>
<li class="last">
<div class="title">
<div class="fill"></div>
Reptiles
</div>
<ul>
<li>
<div class="title">
<div class="fill"></div>
Snake
</div>
</li>
<li class="last">
<div class="title">
<div class="fill"></div>
Turtle
</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Upvotes: 1
Reputation: 5148
This kinda does was you want: http://jsfiddle.net/za3db/4/
It is placing an absolute positioned (left:0; right:0
) pseudo-element under (z-index:-1
) each of your div
s. But this construct has 2 downsides:
1.3em
= line-height)So the best solution might still be javascript or just writing down all those li li
, li li li
, ... rules.
Edit: I played a little more with it and came up with a new version using hidden floated counter()
-pseudo-elements for the indent: http://jsfiddle.net/za3db/5/.
Upvotes: 0
Reputation: 1226
I haven't been able to do it with CSS, but it can be done with a little bit of javascript (jQuery).
$(".tree div").each(function()
{
var padding = $(this).parents("ol, ul").length * 20 + "px";
$(this).css("padding-left", padding);
});
Upvotes: 0