Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS General Sibling Selector Specificity

For a document:

<h1>Section 1</h1>
<p>I came after a h1 and should be red.</p>
<p>I came after a h1 and should be red.</p>

<h2>Section 2</h2>
<p>I came after a h2 and should be green.</p>
<p>I came after a h2 and should be green.</p>

<h1>Section 3</h1>
<p>I should be the same color as the section one text?</p>
<p>I should be the same color as the section one text?</p>

I tried to style it:

h1 ~ p {
    color: red;
}

h2 ~ p {
    color: green;
} 

http://jsfiddle.net/4ks7j938/7/

I expected that paragraphs 1 and 3 would have the same style, with the third paragraph matching against the more specific h1 ~ p selector because a h1 is a closer sibling than a h2. However, in my testing, the result is that paragraphs 2 and 3 are styled the same.

Two questions:

Does the css selector spec actually specify this behavior somewhere? The css spec on the General sibling selector seems open to interpretation here.

How can I achieve the intended result of having paragraphs 1 and 3 styled the same way? I cannot add classes or any attributes to the html, I can only control the css.

like image 675
Matt Bierner Avatar asked Mar 18 '23 16:03

Matt Bierner


2 Answers

Both selectors have the same specificity, what causes h2 ~ p to take precedence is that it is defined after, therefore cascading over h1 ~ p. How close the sibling are is of no consequence.
For the behavior you want you can use the adjacent sibling selector +.

If you change the h1 ~ p after you will see it takes precidience

h2 ~ p {
    color: green;
}

h1 ~ p {
    color: red;
}
<h1>Section 1</h1>
<p>I came after a h1 and should be red.</p>
    
<h2>Section 2</h2>
<p>I came after a h2 and should be green.</p>

<h1>Section 3</h1>
<p>I should be the same color as the section one text?</p>
like image 136
Musa Avatar answered Mar 31 '23 23:03

Musa


Musa seems to be correct that you can't solve this in the general case using only CSS.

But here's one solution for three sections:

h1 ~ p,
h1 ~ h1 ~ p {
    color: red;
}

h2 ~ p {
    color: green;
}

http://jsfiddle.net/4ks7j938/12/

Or, depending of the number of interleavings, this may also work and could possibly be extended to more sections:

h1 ~ p,
h1 ~ h2 ~ h1 ~ p,
h1 ~ h2 ~ h1 ~ h2 ~ h1 ~ p
/* add more as needed */ {
    color: red;
}

h2 ~ p,
h2 ~ h1 ~ h2 ~ p,
h2 ~ h1 ~ h2 ~ h1 ~ h2  ~ p
/* add more as needed */ {
    color: green;
}

http://jsfiddle.net/4ks7j938/15/

Neither approach is particularly scalable however.

like image 25
Matt Bierner Avatar answered Apr 01 '23 00:04

Matt Bierner