I have a DOM element (#installations) with a number of children, only one of them has a class .selected. I need to select this class and the first 3 of the rest (:not(.selected)) and show them - the goal is to have only 4 elements shown, regardless of which element has the class .selected.
The problem is, in the expression:
#installations > *:not(.selected):nth-of-type(-n+3), .selected
:nth-of-type() disregards the :not() selector and just selects the first 3 children of #installation. For example, if I have this HTML:
<div id="installations">
<div id="one"/>
<div id="two"/>
<div id="three" class="selected"/>
<div id="four"/>
<div id="five"/>
</div>
I will only have one, two, three selected and not the first four. The logical implication is that :nth-of-type() will have only (one, two, four, five) to select from, since :not() already excluded the selected one, thus selecting (one, two, four), and then the other part of the selector , .selected
will add the selected element.
If .selected is not in the first four elements, let's say it's the sixth, we will have the first three + sixth elements selected.
To clarify: selecting .selected plus 3 adjacent elements is also fine. However, I this is also difficult in case .selected is in the last 3 (if we select the next 3 adjacent elements)
As a general rule, if you want to select an interval of a selector regardless of the type of element it is, use nth-child . However, if you want to select a specific type only and apply an interval selection from there, use nth-of-type .
The :nth-child selector allows you to select one or more elements based on their source order, according to a formula. It is defined in the CSS Selectors Level 3 spec as a “structural pseudo-class”, meaning it is used to style content based on its relationship with parent and sibling elements.
There cannot be a way to select :nth-of-type() of a class, because :nth-of-type() only selects the nth child of its type.
formula (an + b) In addition to the value n being able to be any number, you can also use a formula. nth-child(3n) would affect every third child element. nth-child(3n+1) would apply to every third element starting from the first one.
As mentioned in my comment, pseudo-classes are not processed sequentially; they are all evaluated together on each and every one of your elements. See this answer for details.
After a bit of tinkering around, given your HTML and the conditions by which to select elements, I came up with the following, long list of selectors:
/* The first three children will always be selected at minimum */
#installations > div:nth-child(-n+3),
/* Select .selected if it's not among the first three children */
#installations > div.selected,
/* If .selected is among the first three children, select the fourth */
#installations > div.selected:nth-child(-n+3) ~ div:nth-child(4)
For this to work, one simple assumption has to be made: the selected
class will only appear on one element at a time.
You'll need to combine all three selectors in the same rule in order to match the four elements you're looking for. Notice the commas in my code.
Interactive jsFiddle demo (for testing the selector with the class in different child elements)
For what it's worth, it's easier if you can fall back to JavaScript. As an example, if you use jQuery, its :lt()
selector makes things a little simpler:
// Apply styles using this selector instead: #installations > div.with-jquery
$('#installations')
.children('div.selected, div:not(.selected):lt(3)')
.addClass('with-jquery');
Interactive jsFiddle demo (ignore the JS code in this demo, it's only there to make it interactive)
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