3

This is a purely hypothetical situation. When answering a question yesterday I came across a problem which I hadn't encountered before. The question itself was pretty flawed in that you simply wouldn't do what it was trying to achieve, but this problem may pop up in other situations. I wasn't able to give a working answer that didn't involve changing the markup, and I'd like to know if it's at all possible without changing the markup.

Take this example:

<p><strong>Lorem</strong> ipsum dolor <strong>sit</strong> amet...</p>

To style the first strong element you'd simply use p > strong:first-child or something similar. That's great and works well, but what if the first strong was optional and it was only the first strong that would require styling?

<p>Lorem ipsum dolor <strong>sit</strong> amet...</p>

Is it possible to ensure that only the very first strong tag here would be styled without using classes, identifiers or anything that could differentiate the two strong tags through the markup?

Here's a JSFiddle of the above.

Note: from the initial answers the question may have been a little misleading. The paragraph doesn't have to be the first on the page, so p:first-child isn't a solution. The first paragraph may not have this leading strong element - alternatively the second paragraph could also have this leading strong element.

Edit: I've updated the JSFiddle example to give a little more clarity of what should and shouldn't be styled.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
James Donnelly
  • 126,410
  • 34
  • 208
  • 218

7 Answers7

2

Unfortunately, it's not possible.

The problem is that CSS selects only element nodes, and text nodes are not element nodes. So, as far as CSS is concerned, <p>blah <b>blah</b> blah <b>blah</b> blah</p> might as well be <p><b></b><b></b></p>.

In other words, your strong tag is the first element inside its parent regardless of whether there's text in front of it, even though it's not the first node when there's text in front.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
1

Perhaps, this is what you are trying to do:

p:first-child > strong:first-child
loxxy
  • 12,990
  • 2
  • 25
  • 56
  • No, in this the paragraph is assumed to be anywhere on the page. It's not necessarily the first paragraph, and the first paragraph may or may not have this leading `strong` element. – James Donnelly Mar 18 '13 at 09:17
  • Yes, but the first `strong` tag would be entirely optional. Here's an updated example: http://jsfiddle.net/RNpsG/9/ – James Donnelly Mar 18 '13 at 09:25
1

How about using * for any container, which has strong as its first element should be in different color:

* > strong:first-child { color:#f30; }

Or like this:

 * > p > strong:first-child { color:#f30; }
Khurram Ishaque
  • 778
  • 1
  • 9
  • 26
1

EDIT - as pointed out in the comments, this solution falls apart pretty quickly. There isn't a CSS-only way to achieve this that I can see.

I've come up with a pure CSS solution. Here's the CSS (based on your amended example):

p > strong { color:blue; }
p > strong:first-child { color:red; }
p > strong:nth-last-child(-n+1) { color:blue; }

Which renders:

nth-last-child example

This makes use of the :nth-last-child selector, which is supported in all good browsers (and IE9+). That selector:

…matches an element that has an+b-1 siblings after it in the document tree, for a given positive or zero value for n, and has a parent element

The order of those selectors is important because the specificity is the same for each, so we need to be over-riding the previous targeted strong's with each subsequent selector.

CherryFlavourPez
  • 7,529
  • 5
  • 45
  • 47
  • Ah, this is almost a solution! Unfortunately it doesn't work when you have multiple `strong` elements which aren't at the beginning: http://jsfiddle.net/Jzqha/4/ – James Donnelly Mar 18 '13 at 09:59
  • No, it is a node problem, for the selectors `

    .........

    ` will always be considered as same as `

    `
    – Valky Mar 18 '13 at 10:06
  • Exactly... CSS is unable to distinguish between `` and ` foo `, there's really no way around it. It's possible that some kind of `:first-line` positioning hack could sort of work, but it doesn't seem worth pursuing. – Dagg Nabbit Mar 18 '13 at 10:08
1

I have tried a lot more but I could not find any method that your need would be fulfilled, but anyway I have added a trick for your fiddle. See this fiddle just add <span></span> inside to your first <strong> element and define your css... is this Ok for you?

Edit Or you could define a blank strong inside your div <strong></strong> to make this first element.

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
-1

I think this is what you are looking for...

p strong:first-child { ... }
Ian Wood
  • 6,515
  • 5
  • 34
  • 73
  • That's not what he's after. In fact, that code is given in the question. I believe he's trying to target the `strong` *only if* it is the very first element (i.e. in the exact position in the DOM that has been outlined). – CherryFlavourPez Mar 18 '13 at 09:15
  • perhaps I misread the question - he asked 'Is it possible to ensure that only the very first strong tag here would be styled without using classes' – Ian Wood Mar 18 '13 at 09:20
-1

Look at this it might solve your problem: http://jsfiddle.net/RNpsG/1/

body > p:first-child > strong:first-child { color:#f30; }
kleinohad
  • 5,800
  • 2
  • 26
  • 34