1

Here are two examples based on this HTML.

<a href="#">
    <div class="foo">
        hello
        <span class="bar">world</span>
    </div>
</a>

In the first one, I make the link not underline on hover, then make a sub-portion of the link underline, and that works fine:

a {
    text-decoration:none;
}
a:hover {
    text-decoration: none;
}
a:hover .bar {
    text-decoration: underline;
}

http://jsfiddle.net/3qPyX/1/

In the second, I now reverse the selectors so that the second word should be un-underlined. However, now something strange happens. The entire link remains underlined even though the selectors seem like they should remove underline from the second word. <-- (this is the question. why does this happen?)

a {
    text-decoration:none;
}
a:hover {
    text-decoration: underline;
}
a:hover .bar {
    text-decoration: none;
}

http://jsfiddle.net/EAmwt/

Can someone explain what's going wrong in the second example? Inspecting with Chrome shows the span.bar has a computed style of text-decoration:none.

Update: a few answers explaining how to get around the problem, which is great except that's not really my question. What I want to know is why is this behavior different than, say, bold? For instance, if I try the 2nd example with bold, I get the expected results: http://jsfiddle.net/3qPyX/4/

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Robert Martin
  • 16,759
  • 15
  • 61
  • 87

3 Answers3

11

Explanation:

The problem is that some properties (like text-decoration) get drawn to the whole parent inline element, whereas others - like font styling (that get inherited) - get overriden by the children properties.

Just for illustration: simmilarly, if you set a background color to a parent element it will paint the background of the parent ... and you would have to set another color to a child to lay it over (default - transparent - will still show the parent style through), but if you set font-weight at a child it will apply to the text inside the child element and override the parent settings.

You can find more detailed stuff on the text-decoration property in the CSS Level 2 and Level 3 Specifications.


A simple solution

withot changing the markup, you could just display .bar as inline-block.

Like so:

a {
    text-decoration:none;
}
a:hover {
    text-decoration: underline;
}
a:hover .bar {
    display:inline-block;
}

And the inline-block breaks out of the inline/text styling of the parent anchor element =) And you can then style it independently:

DEMO

Martin Turjak
  • 20,896
  • 5
  • 56
  • 76
  • I think "breaks the styling" is the key to understanding why this happens, but I still don't really get it, since I imagine underline to be something applied directly to the text, like bold in my example. What's the difference? – Robert Martin May 17 '13 at 14:09
  • 1
    the font- styling properties work the way you expect, but text-decoration is not one of them ... and gets rendered to the whole element it is applied to, a sI explain in beggining of my answer. [READ MORE HERE](https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration#Notes) – Martin Turjak May 17 '13 at 14:19
  • I hope this answers your actual question ... and the solution suggested I merely add as it overcomes the problems with some intrinsic properties of the `text-decoration` selector ;-) It would make it a bit harder to answer if you also want to know *why* they decided to implement the selector in this specific manner. – Martin Turjak May 17 '13 at 15:33
  • 1
    @RobertMartin see Changes to CSS2.1 spec: http://www.w3.org/TR/CSS21/changes.html#q475 „C.7.86 Section 16.3.1 Underlining, overlining, striking, and blinking: the 'text-decoration' property“ — Note that *text decorations* are *not propagated* to *floating and absolutely positioned descendants*, nor to the contents of atomic inline-level descendants such as ​_inline blocks_ and inline tables. – Ihor Zenich Nov 25 '15 at 17:19
2

When you do the text-decoration it is applied to the entire line at once. So the a:hover .bar doesn't cause any effect, because the underline is not being applied in the .bar but on the a.

Here is the specification: http://www.w3.org/TR/CSS21/text.html#lining-striking-props

fmsf
  • 36,317
  • 49
  • 147
  • 195
  • 1
    Indeed. [This jsFiddle](http://jsfiddle.net/EAmwt/5/) shows the effect without the `a` element or the `:hover` behaviour. – lonesomeday May 17 '13 at 13:51
  • 1
    If you would want to underline just the first part of the anchor you should make a separate span for that one: [jsfiddle](http://jsfiddle.net/EAmwt/6/). The parent will always draw the line behind the child. – Martin Turjak May 17 '13 at 13:55
2

UPDATE! (As @Cam suggested) :

You need the add in separate elements the parts of your text: http://jsfiddle.net/3qPyX/5/

The CSS:

.foo, a:hover .bar, a {
    text-decoration:none;
}
a:hover .foo {
    text-decoration: underline;
}
Seer
  • 739
  • 4
  • 22
  • Remove .bar text-decoration: to none. And you have the answer. Make sure to read the question thoroughly. – Cam May 17 '13 at 13:57
  • Hmm, but he would like the first word underlined on hover, and the second word underlined in normal state, no? @Robert Martin ? – Seer May 17 '13 at 14:00
  • 1
    No he wants it reversed. You got the answer just fix that and your golden. +1 – Cam May 17 '13 at 14:22