10

I have an element that has a child and another element with the same child, but there is also a text node:

<p><strong>This should be heading</strong></p>
...
<p>There is a sentence that has <strong>strong text</strong> inside it.</p>

I do not have the ability to modify the DOM structure in any way, including no JavaScript. All I can do is edit CSS, but I want to style the inline strong differently than the strong that is the only child.

I thought this might work:

p strong:only-child
{
    color: red;
}

However, both items turn red.

Is there a way to target child nodes that don't have text node siblings, using only CSS?

I don't think it can be done, but I figured I'd ask in case there is some sort of clever work-around.

jeffjenx
  • 17,041
  • 6
  • 57
  • 99
  • 3
    This cannot be done with a selector. That said, which `strong` do you want to turn red? Both `strong` elements are inline, it just happens that one of them is surrounded by non-whitespace text. – BoltClock Aug 01 '13 at 13:03
  • I updated my example code, as whitespace is not a factor. The goal is to make the faux heading (strong without text around it) red and the strong inside the sentence remains black. – jeffjenx Aug 01 '13 at 13:05
  • I think this is not possible with css since in both cases you have a p with a strong inside. If you can't change the html I think you need some javascript. – Mir Aug 01 '13 at 13:08
  • inline text is not considered as nodes by themselves. Therefore this is not possible. You can however, style the tags according to where they fit in the WHOLE document (in relation to each other, etc) – ProfileTwist Aug 01 '13 at 13:42
  • 1
    I found only one way to distinguish these cases in pure CSS — to check whether `p:first-letter` is inside `p strong` or not. But it seems that this approach can be used only to style the background: http://jsfiddle.net/SjBAx/ – Ilya Streltsyn Aug 01 '13 at 13:53
  • One issue with that solution (Ilya's) is that the ``s become inline blocks, which means they can't split across lines. For line-break purposes, the entire `` becomes a single word. – Peeja Apr 07 '14 at 17:28

2 Answers2

4

As per my understanding I think it should be like

p:first-child
{
    color: red;
}

JSFiddle

Praveen
  • 55,303
  • 33
  • 133
  • 164
  • Great idea. Unfortunately, this simplified example excludes other `p` elements that would prevent this from working in my real-world case. I may, however, have to do something similar to this with an `nth-child()` somehow. – jeffjenx Aug 01 '13 at 13:08
  • 3
    This assumes `p:first-child` will always be one that contains the faux heading. Not sure it holds water, especially in the context of "elements with only an element child vs elements with both text and element children". – BoltClock Aug 01 '13 at 13:08
  • Hopefully it it's _always_ the first child ;p – thgaskell Aug 01 '13 at 13:08
0

The following code cannot work properly.

p strong:only-child{
    color: red;
}

when you have code like that:

<p><strong>This should be heading</strong></p>
...
<p>There is a sentence that has <strong>strong text</strong> inside it.</p>

In each case, the 'strong' element is the only child element of its parent - 'p'. Therefore, both 'strong' elements here would be matched. That's why both your items turned red.

To change the color only of the first paragraph, you can write (as somebody had mentioned before):

p:first-child{
    color:red;
  }

or its equivalent, which is:

p:nth-child(1){
}

The best-case scenario, which I know doesn't apply here, would be to change the html code by adding 'class="red"' like in these examples:

Version 1:

HTML

<p><strong class="red">This should be a heading</strong></p>
<p>This is a sentence with <strong>strong text</strong> in it.</p>

CSS

.red{
  color:red;
}

Version 2:

<p class="red"><strong>This should be a heading</strong></p>
<p>This is a sentence with <strong>strong text</strong> in it.</p>

CSS

.red{
  color:red;
}
Jacek Lampart
  • 1,741
  • 13
  • 25
Codewife_101
  • 357
  • 1
  • 4
  • 19
  • Aren't you taking a five year old question and duplicating, in part, the highest voted answer? In addition, you are including version 2 which is specifically not allowed in the question. – Rob Jan 14 '18 at 04:22
  • Not really, I added additional content. I clarified why the first approach didn't work properly by explaining the usage of ':only-child' selector. Besides, I added the simple HTML and CSS code for people who will be thinking how to rewrite this code in a better way instead of using 'strong' element twice. – Codewife_101 Jan 14 '18 at 04:51