General CSS Selector Specification
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 paragraphs 1 and 3 to have the same style, and the third paragraph matches a more specific selector h1 ~ p
because it h1
is a closer cousin than h2
. However, in my testing, the result is that paragraphs 2 and 3 are styled the same way.
Two questions:
Does the css selector spec define this behavior somewhere? The css spec in the General sibling selector seems open to interpretation here.
How can I achieve the intended result with the same method as points 1 and 3? I cannot add classes or any attributes to the html, I can only manipulate the css.
source to share
Both selectors have the same specificity, which causes the precedence to h2 ~ p
be defined after, therefore cascading over h1 ~ p
. How close a sibling is does not matter.
For the behavior you want, you can use the adjacent sibling selector +
.
If you change h1 ~ p
after you see it accepts the foreword
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>
source to share
Musa seems correct that you cannot solve this in the general case using CSS alone.
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 on the number of interlaces, this could work as well and could be expanded to more partitions:
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/
However, neither approach is particularly scalable.
source to share
What a difficult question! If you have access to add some jQuery it might be helpful to use move methods . The following works, but you will need to fit your specific needs, so another way might be better.
$( "h1" )
.nextUntil( "h2" )
.css( "color", "red" );
$( "h2" )
.nextUntil("h1")
.css( "color", "green" );
source to share
your code has the css of the tag h1
on the first line, so it will look for the tag p
that is the sibling with the tag h1
and will apply red to the whole tag p
. on the very next line, two tags will be found p
, which below the first h1 tag and those two
p` tag will be applied by the second css. This is the protrusion problem you have. Now the solution to your problem is css3 adjacent sibling selector
Have a look at this fiddle: http://jsfiddle.net/4ks7j938/9/
source to share