CSS Sibling Selectors (Select All Siblings)

CSS sibling selectors (select all siblings)

You can select all the following siblings using ~ instead of +:

.open ~ h2

If you need to select all h2 elements that aren't .open whether they precede or follow .open, there is no sibling combinator for that. You'll need to use :not() instead:

h2:not(.open)

Optionally with a child combinator if you need to limit the selection to div parents:

div > h2:not(.open)

Is there such a thing as an all inclusive sibling CSS selector?

There is no sibling combinator that looks backward or around, only the adjacent and general sibling combinators that look forward.

The best you can do is determine a way to limit selection only to these p elements with the same parent, and then select the p children that are :not(.green_guys). If the parent element has an ID of #parent, for example, you can use this selector:

#parent > p:not(.green_guys) {
/* selects all <p> children of #parent that are not .green_guys */
}

However the above will still match your p elements even if none of them have the class. It is currently not possible to select the siblings of an element only given the existence of said element (which is the purpose of a sibling combinator — to establish a relationship between two sibling elements).


Selectors 4's :has() will hopefully rectify this without the need for a preceding-sibling combinator, resulting in the following solution:

p:has(~ .green_guys), .green_guys ~ p {
/* selects all <p> elements that are siblings of .green_guys */
}

This will not match anything if none of the children of the parent element have the class.

Select all siblings if one of them has a specific class

Use jQuery to get the siblings and then apply the red class to them.

$( "li.item.red" ).siblings().addClass("red");
.red {

background-color: red;

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul>

<li class="item red">list item</li>

<li class="item">list item</li>

<li class="item">list item</li>

<li class="item">list item</li>

<ul>

<ul>

<li class="item">list item</li>

<li class="item">list item</li>

<li class="item red">list item</li>

<li class="item">list item</li>

<ul>

CSS select all previous siblings for a star rating

// obtain all spans from DOM
const spans = document.querySelectorAll('span');
// set a variable at global scope as indicator
let flag = false;

// add event listener to each span
spans.forEach((sp, j)=>{
sp.addEventListener('click', ()=>{
// if clicked, then not dismissing the background colour after mouse leave
flag = true;
// reassign all spans back to original grey
spans.forEach(dsp=>{
dsp.style.backgroundColor = '#eee';
});
// assign bg to red of the spans from 0 to clicked index
Array.from(new Array(j+1), (x, i) => i).forEach(ind=>{
spans[ind].style.backgroundColor = 'red';
});
});
// redo if mouse enters
sp.addEventListener('mouseenter', ()=>{
flag = false;
});
// if any span is hovered
sp.addEventListener('mouseover', ()=>{
// reassign all spans back to original grey
spans.forEach(dsp=>{
dsp.style.backgroundColor = '#eee';
});
// assign bg to red of the spans from 0 to clicked index
Array.from(new Array(j+1), (x, i) => i).forEach(ind=>{
spans[ind].style.backgroundColor = 'red';
});
});
// in moseleave, only save the background colour if click happened
sp.addEventListener('mouseleave', ()=>{
if(!flag){
spans.forEach(dsp=>{
dsp.style.backgroundColor = '#eee';
});
}
});
});
span {
display:inline-block;
width: 32px;
height: 32px;
background-color:#eee;
}

span:hover {
background-color:red;
opacity: 0.8;
cursor: pointer;
}
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>

Css Selector - Select all siblings until a certain sibling

OK, you can use nextUntil. But, since you want that for a conditional. You should find a way to get a boolean from this.

For example adding to it, .hasClass()

Is there a previous sibling selector?

No, there is no "previous sibling" selector.

On a related note, ~ is for general successor sibling (meaning the element comes after this one, but not necessarily immediately after) and is a CSS3 selector. + is for next sibling and is CSS2.1.

See Adjacent sibling combinator from Selectors Level 3 and 5.7 Adjacent sibling selectors from Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification.

Select any sibling in CSS

The CSS sibling selectors ~ and + only select siblings after a particular element. So those won't be useful if you want to select also the preceding siblings.

But one thing you can do is the following combination of CSS rules:

.container>* {
color: red;
}
.xxx {
color: initial;
}
<div class="container">
<p>Some Text some Text</p>
<div>Some Text some Text</div>
<p>Some Text some Text</p>
<p>Some Text some Text</p>
<p class="xxx">This one has the class mentioned in the text</p>
<p>Some Text some Text</p>
<span>Some Text some Text</span>
</div>

Pure CSS: Select elements that have n or more siblings

It's possible by a technique, which is described well at Lea Verou's Blog CSS Secrets: Styling Elements based on sibling count.

It's based on the follwing observation:

If you know that the first element is also the third last element, you also know that there are three siblings altogether.

All you have to do now is to select this first and 3rd last element plus all its following siblings.

tbody > tr:first-child:nth-last-child(3),
tbody > tr:first-child:nth-last-child(3) ~ tr {}

I enhanced this a little bit, to be more dynamic and made a SCSS mixin in this codepen

The mixin is as follows:

// SCSS
@mixin yuboo-childcount($count, $element, $element-selective: null, $rest: false) {
$el: $element;
$els: $element;
@if $element-selective {
$els: $element-selective;
}
$co: $count;
@if $rest {
$co: n + #{$count};
}

@if $count == 1 {
& > #{$els}:first-child:nth-last-of-type(#{$co}) {
@content;
}
} @else {
& > #{$els}:first-child:nth-last-of-type(#{$co}),
& > #{$el}:first-child:nth-last-of-type(#{$co}) ~ #{$els} {
@content;
}
}
}

If I include it like this:

tbody {
@include yuboo-childcount('3', tr) {
/* my rules */
}
}

it yields:

tbody > tr:first-child:nth-last-of-type(3), 
tbody > tr:first-child:nth-last-of-type(3) ~ tr {
/* my rules */
}

Your example

tr:min-siblings(3) {
color: blue;
}

which I interpret as saying: color should be set to blue for every tr inside a tbody, when there are 3 or more trs in that tbody, would be solved as follows:

tbody {
@include yuboo-childcount('n+3', tr) {
color: blue;
}
}

becoming this CSS

tbody > tr:first-child:nth-last-of-type(n+3), 
tbody > tr:first-child:nth-last-of-type(n+3) ~ tr {
color: blue;
}

Check this example

tr {

color: red;

background-color: pink;

}

tbody > tr:first-child:nth-last-of-type(n+3),

tbody > tr:first-child:nth-last-of-type(n+3) ~ tr {

color: blue;

background-color: lightblue;

}

td {

background-color: inherit;

border: 1px solid gold;

padding: 10px;

}

table {

border: 1px solid gold;

padding: 0;

margin: 10px;

border-collapse: collapse;

}
<table>

<tr><td>1</td></tr>

</table>

<table>

<tr><td>1</td></tr>

<tr><td>2</td></tr>

</table>

<table>

<tr><td>1</td></tr>

<tr><td>2</td></tr>

<tr><td>3</td></tr>

</table>

<table>

<tr><td>1</td></tr>

<tr><td>2</td></tr>

<tr><td>3</td></tr>

<tr><td>4</td></tr>

</table>

<table>

<tr><td>1</td></tr>

<tr><td>2</td></tr>

<tr><td>3</td></tr>

<tr><td>4</td></tr>

<tr><td>5</td></tr>

</table>

<table>

<tr><td>1</td></tr>

<tr><td>2</td></tr>

<tr><td>3</td></tr>

<tr><td>4</td></tr>

<tr><td>5</td></tr>

<tr><td>6</td></tr>

</table>

Is there an ALL siblings selector?

No, there is no such sibling selector in Selectors 3.

Although you can select elements that aren't being hovered using the :not() pseudo-class, as a:not(:hover), you can't select all of them relatively to some other a that is currently being hovered or only while it is being hovered.

Selecting multiple adjacent siblings (and their children)

Why not use adjacent selector to achieve that?

#magic:hover + #sibling1 + #sibling2 span {
color: red;
}

Demo (Hover the first element and see the color changes for the 3rd element)

And if you want to change the styles of all the element followed by #magic, than use

#magic:hover + #sibling1 span,
#magic:hover + #sibling1 + #sibling2 span {
/* Styles goes here */
}

Demo 2



Related Topics



Leave a reply



Submit