0

According to the definition of adjacent sibling selector the following code should work. However it does not. I don't seem to find any mistake.

<!DOCTYPE html>
<html>
<head>
<style>

#p2+h4{
    color:red;
}

</style>
</head>

<body>
    <p>
        <p id="p2">This is the sibling of the selected para</p>
        <p>
            <h4>this should not be colored</h4>
        </p>
        <h4>this should be colored</h4>
    </p>    
</body>
</html>
Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
raiyan106
  • 85
  • 1
  • 6
  • 7
    You can't nest paragraphs tags. You also can't have heading tags in paragraph tags. – j08691 Jul 21 '14 at 13:59
  • 3
    "According to the definition of adjacent sibling selector" You seem to have misunderstood the definition, then. – BoltClock Jul 21 '14 at 17:23

5 Answers5

7

H4 is not immediately preceded by the #p2. You should use a more loose sibling selector ~ (general sibling combinator):

#p2 ~ h4

Specification

  • E + F an F element immediately preceded by an E element
  • E ~ F an F element preceded by an E element

Important

But as many others have suggested in comments (and invalidly in answers) your HTML isn't valid. You can't just nest elements that shouldn't be nested. Browsers will reformat it conforming to the specification. Paragraph element can only contain phrasing content.

Elements belonging to phrasing category are <abbr>, <audio>, <b>, <bdo>, <br>, <button>, <canvas>, <cite>, <code>, <command>, <datalist>, <dfn>, <em>, <embed>, <i>, <iframe>, <img>, <input>, <kbd>, <keygen>, <label>, <mark>, <math>, <meter>, <noscript>, <object>, <output>, <progress>, <q>, <ruby>, <samp>, <script>, <select>, <small>, <span>, <strong>, <sub>, <sup>, <svg>, <textarea>, <time>, <var>, <video>, <wbr> and plain text (not only consisting of white spaces characters).

A few other elements belong to this category, but only if a specific condition is fulfilled:

  • <a>, if it contains only phrasing content
  • <area>, if it is a descendant of a element
  • <del>, if it contains only phrasing content
  • <ins>, if it contains only phrasing content
  • <link>, if the itemprop attribute is present
  • <map>, if it contains only phrasing content
  • <meta>, if the itemprop attribute is present

Based on reformatted HTML by the browsers, both headings will get colored as they both become siblings to the #p2 paragraph and are both preceded by the same paragraph.

Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
  • thanks and btw i am new at this. How will I know which elements or tags can be nested and which can't? – raiyan106 Jul 21 '14 at 14:15
  • @raiyan106: I've edited my answer to include the link and excerpt from the specification. Always consult the spec when in doubt. But the quick way of seeing invalid HTML is when it doesn't display correctly and brwser's developer tools show a different DOM tree than you've written (as in this case). – Robert Koritnik Jul 21 '14 at 14:17
  • 1
    "more loose" and "adjacent" contradict each other - you probably meant "sibling" and not "adjacent". – BoltClock Jul 21 '14 at 17:21
1

Your html is invalid. p element permitted content is phrasing content. Additional css adjacent sibling selector selects following the rule:

Adjacent sibling selectors have the following syntax: E1 + E2, where E2 is the subject of the selector. The selector matches if E1 and E2 share the same parent in the document tree and E1 immediately precedes E2, ignoring non-element nodes (such as text nodes and comments).

in your example element with id #p2 is not immediately precedes h4. You can fix your html and use general sibling selector:

#p2 ~ h4 {
  color: red;
}
<div>
  <p id="p2">This is the sibling of the selected para</p>
  <div>
    <h4>this should not be colored</h4>
  </div>
  <h4>this should be colored</h4>
</div>

This will work because general sibling selector selects according to the following rule:

The following-sibling combinator is made of the "tilde" (U+007E, ~) character that separates two sequences of simple selectors. The elements represented by the two sequences share the same parent in the document tree and the element represented by the first sequence precedes (not necessarily immediately) the element represented by the second one.

here element with id #p2 shares the same parent with second element h4 in html but not with the first.

Take a look also Difference between the selectors div + p (plus) and div ~ p (tilde)

References:

Adjacent sibling selectors

Following-sibling combinator

Community
  • 1
  • 1
Alex Char
  • 32,879
  • 9
  • 49
  • 70
  • 2
    Explain the downvote please. – Alex Char Jul 21 '14 at 14:02
  • 2
    This colors both `h4`s which does not match what the OP intended. I have no idea why the OP accepted your answer. It couldn't have solved their problem - unless, of course, they mistated their problem in the first place, which is why I have chosen to downvote the question instead of your answer (the downvote on your answer is not mine, but I can see why someone else might have downvoted it). – BoltClock Jul 22 '14 at 06:09
  • @BoltClock It could in this case because browsers auto-un-nest p tags, so it seemed to work as desired in this specific case – Zach Saucier Mar 29 '17 at 11:42
  • @Zach Saucier: I'm closing the question since the asker never bothered to follow up. – BoltClock Mar 29 '17 at 12:29
0

Because p2 isn't adjacent to any h4s

This would work

<p>stuff</p>
<h4>stuff</h4>

But this wouldn't

<p>stuff</p>
<anyothertag>
    <h4>stuff</h4>
</anyothertag>
Luke
  • 3,985
  • 1
  • 20
  • 35
0

Your HTML is invalid. <p> elements cannot contain other <p> elements, nor heading elements. If you inspect the code in the page, the browser corrects for it and generates it as:

<p></p>
<p id="p2">This is the sibling of the selected para</p>
<p></p>
<h4>this should not be colored</h4>
<p></p>
<h4>this should be colored</h4>
<p></p>

Which is why your CSS fails since #p2+h4 looks for an <h4> as the immediate sibling of an element with the ID of p2. You can use either #p2~h4 or #p2+p+h4 to select the heading. Note however that #p2~h4 would also select the second heading.

j08691
  • 204,283
  • 31
  • 260
  • 272
0

This won't work as browser don't accept nested p tags anyway. Replacing all your p tags with divs would make it work, but that doesn't do it either because you are looking for any elements with the id p2 and is followed immediately by an element of the type h4. Only if you enter something as general as p + h4 you will only address every h4 preceded by a p element. Here's how to make it all work:

<!DOCTYPE html>
<html>
<head>
<style>
#p2 + div + h4{
    color:red;
}
</style>
</head>
<body>
    <div>
        <div id="p2">This is the sibling of the selected para</div>
        <div>
            <h4>this should not be colored</h4>
        </div>
        <h4>this should be colored</h4>
    </div>    
</body>
</html>
somethinghere
  • 16,311
  • 2
  • 28
  • 42