2

I am trying to select every first paragraph element that follows a header element (e.g. h2). However, due to wrapping in divs, I end up selecting several "first" paragraph elements. Is it possible to select only the paragraph element that follows with CSS combinators? My HTML is like this:

<div>
  <h2>Header</h2>
</div>
<div>
  <div>
    <p>Here goes my first paragraph. This is what I need to select.</p>
    <p>Here goes my second paragraph</p>
    <p>Here goes my third paragraph</p>
  </div>
</div>
<div>
  <div>
    <p>Here goes my fourth paragraph and I don't want to select this one.</p>
  </div>
</div>

This CSS ends up selecting the first as well as what I intended to be fourth paragraph:

p:first-of-type{
  text-indent: 0;
}

So I tried with CSS like this:

div * h2 + div * p:first-of-type{
  text-indent: 0;
}

But it doesn't work. So is it even possible to combine the descendant selector with the general sibling selector like that?

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
chagelskjaer
  • 21
  • 1
  • 4
  • 3
    No you cannot, once you get in one level of the dom you cannot come out and select the sibling one... – Mr. Alien Aug 13 '15 at 13:18
  • @r00k that won't help him either... text may be dynamic, `nth` selectors are static in nature... – Mr. Alien Aug 13 '15 at 13:20
  • `div:nth-child(2) p:first-of-type` ? – j08691 Aug 13 '15 at 13:21
  • See my answer to [this related question](http://stackoverflow.com/questions/28708741/how-do-i-select-an-element-based-on-the-state-of-another-element-in-the-page-wit) for the theory of how combinators work. – BoltClock Aug 13 '15 at 13:21
  • @j08691: div:nth-child(2) says nothing about the presence or position of the h2 or any other heading element. – BoltClock Aug 13 '15 at 13:22
  • @j08691 nope, what if the content is looped with random occurrences of `h2`? he wants to select first paragraph followed by a `div` element having `h2` – Mr. Alien Aug 13 '15 at 13:22
  • @BoltClock - ah yeah I forgot about that condition. – j08691 Aug 13 '15 at 13:23
  • @Paulie_D: You can. I've been doubtful of how effective it is at being a canonical question for this sort of thing though, and I'm not if my answer is too long-winded (though it is by necessity) :( – BoltClock Aug 13 '15 at 13:25
  • @BoltClock It's a tough one...I've had similar thoughts. I think on balance I'll leave it as is and let Quentin's answer stand. Seems to be on point. – Paulie_D Aug 13 '15 at 13:28
  • 1
    @Paulie_D: [This other answer of mine](http://stackoverflow.com/questions/29757133/css-selector-for-adjacency/29765647#29765647) seems to answer this question fully. All we need is a better title for that question. – BoltClock Aug 13 '15 at 13:33
  • @BoltClock Indeed...Mjolnir swinging :) – Paulie_D Aug 13 '15 at 13:34

3 Answers3

3
div * h2 + div * p:first-of-type

That means:

A p which is the first p in its container and which is a descendant of any element which, in turn, is a descendant of a div, which is a sibling of an h2 which is (etc etc).

In your HTML, the div is not a sibling of the h2.

Your problem is that you first need to select the div which is the parent of the h2 and then chain the rest of your selector from there. This isn't possible because CSS doesn't have a parent selector.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
  • Now i see you have quoted the selector from the question... I thought this was an idea for a working selector and was confused for 5 minutes there ... – Nico O Aug 13 '15 at 13:38
1

You cannot select a childelement from another childelement when they are not siblings or conncted by a hirachy.

You can use this selector, it will select the paragraph you want, but only if your HTML structure stays like you defined it:

div:nth-of-type(2) > div > p:first-child

The best solution would be to give you elements classes and ids. It is best practice to use as less rules as possible in CSS. Rules make the page slower...

DavidVollmers
  • 620
  • 4
  • 15
1

Can you edit the html? A couple more selectors could fix this.

<div class="mainContainer"> <!-- new div -->
<div>
  <h2>Header</h2>
</div>
<div>
  <div>
    <p>Here goes my first paragraph. This is what I need to select.</p>
    <p>Here goes my second paragraph</p>
    <p>Here goes my third paragraph</p>
  </div>
</div>
<div>
  <div>
    <p>Here goes my fourth paragraph and I don't want to select this one.</p>
  </div>
</div>
</div> <!-- new div -->

Then with something like:

.mainContainer div:nth-of-type(2) p:first-child { /* css here */ }

You should be able to style just the first paragraph this way, by targeting the first paragraph inside the 2nd "sub" div.

Brad Adams
  • 1,816
  • 3
  • 24
  • 33