CSS only approach
First child does not work that way. You can read more about it in BoltClock's answer here. It selects the first-child
of the parent (that also matches any additional conditions) and cannot select the first element among the children which match the provided condition.
Instead what you could do is first apply the required properties on all li:not(.hidden)
elements and then override it with default settings for li:not(.hidden) ~ li:not(.hidden)
. The second selector means that any .hidden
element which is a sibling of another (meaning it is not the first) would get the default setting whereas the first would get the modified setting (red color in the snippet).
The general sibling selector should be used as the adjacent sibling selector (+
) may not help you completely because as you can see in the below snippet, it would only select all other elements as long as there is no other .hidden
in between.
ul > li:not(.hidden) {
color: red;
}
ul#one > li:not(.hidden) ~ li:not(.hidden) {
color: black;
}
ul#two > li:not(.hidden) + li:not(.hidden) { /* wont help if any other hidden elements in between */
color: black;
}
<ul id='one'>
<li class="hidden">First hidden</li>
<li class="hidden">Second hidden</li>
<li>First not hidden</li>
<li>Second not hidden</li>
<li class="hidden">Third hidden</li>
<li>Third not hidden</li>
</ul>
<ul id='two'>
<li class="hidden">First hidden</li>
<li class="hidden">Second hidden</li>
<li>First not hidden</li>
<li>Second not hidden</li>
<li class="hidden">Third hidden</li>
<li>Third not hidden</li>
</ul>
Using JavaScript/jQuery
I know you have asked for pure CSS selectors but as can been seen from both existing answers, it is not possible to achieve this without doing the override for adjacent siblings. If you want a straight-forward way of handling things then you could look at using JS or jQuery. Below are a couple of sample snippet:
jQuery:
$(document).ready(function() {
$('ul').each(function() {
$(this).children('li:not(.hidden):first').css('color', 'red');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id='one'>
<li class="hidden">First hidden</li>
<li class="hidden">Second hidden</li>
<li>First not hidden</li>
<li>Second not hidden</li>
<li class="hidden">Third hidden</li>
<li>Third not hidden</li>
</ul>
<ul id='two'>
<li>First not hidden</li>
<li class="hidden">First hidden</li>
<li class="hidden">Second hidden</li>
<li>Second not hidden</li>
<li>Third not hidden</li>
<li class="hidden">Third hidden</li>
<li>Fourth not hidden</li>
</ul>
<ul id='two'>
<li class="hidden">First hidden</li>
<li>First not hidden</li>
<li class="hidden">Second hidden</li>
<li>Second not hidden</li>
<li>Third not hidden</li>
<li class="hidden">Third hidden</li>
<li>Fourth not hidden</li>
</ul>
JavaScript:
$(document).ready(function() {
var ulEls = document.querySelectorAll('ul');
for (var i = 0; i < ulEls.length; i++) {
ulEls[i].querySelector('li:not(.hidden)').setAttribute('style', 'color: red');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id='one'>
<li class="hidden">First hidden</li>
<li class="hidden">Second hidden</li>
<li>First not hidden</li>
<li>Second not hidden</li>
<li class="hidden">Third hidden</li>
<li>Third not hidden</li>
</ul>
<ul id='two'>
<li>First not hidden</li>
<li class="hidden">First hidden</li>
<li class="hidden">Second hidden</li>
<li>Second not hidden</li>
<li>Third not hidden</li>
<li class="hidden">Third hidden</li>
<li>Fourth not hidden</li>
</ul>
<ul id='two'>
<li class="hidden">First hidden</li>
<li>First not hidden</li>
<li class="hidden">Second hidden</li>
<li>Second not hidden</li>
<li>Third not hidden</li>
<li class="hidden">Third hidden</li>
<li>Fourth not hidden</li>
</ul>
Note I have used .each()
function or loops in the above snippets because I wanted to illustrate how it covers multiple cases but you may not need them depending on your usage.