19

I have a text link that is underlined when hovered. I'm adding at the beginning of the link a > symbol using the following code:

.box.blueb a { color: #0098aa; }
.box.blueb a:hover { text-decoration: underline; }
.box.blueb a:before { content: "> "; }
.box.blueb a:before:hover { text-decoration: none; }

But what I don't want the > symbol underlined when the link is hovered. How do I achieve this?

Oriol
  • 274,082
  • 63
  • 437
  • 513
Scott
  • 3,967
  • 9
  • 38
  • 56

6 Answers6

14

http://jsfiddle.net/thirtydot/LmvgM/1/

You need to wrap a span around the text inside the a:

<div class="box blueb">
    <a href="#"><span>Hello</span></a>
</div>

And then change your CSS to this:

.box.blueb a { color: #0098aa; text-decoration: none; }
.box.blueb a:hover > span { text-decoration: underline; }
.box.blueb a:before { content: "> "; }

.box.blueb a:before:hover { text-decoration: none; } doesn't work because when you set text-decoration: underline on an element (the a), you can't then remove it on a descendant (:before).

Community
  • 1
  • 1
thirtydot
  • 224,678
  • 48
  • 389
  • 349
  • 1
    Thanks for this but I don't think adding extra mark up is going to fly with the people I'm building it for. – Scott Dec 16 '11 at 15:24
  • I don't see how you can do it otherwise. The only other option I can think of is to use a `background-image` for the `>` instead of text. – thirtydot Dec 16 '11 at 15:26
  • Adding extra markup is not required, as shown by the other answer. Doing this with CSS only is more elegant. – kontur Nov 21 '17 at 08:27
  • @kontur: All of the other answers here have downsides, such as: width of `>` character can change between fonts/sizes (or if you change the character), doesn't work in older browsers, is complicated. Doing this with CSS is not more elegant, it is just less robust. We aren't doing CSS Zen Garden here, just add some `span`s! Admittedly, I haven't actually tried to solve this problem again now (or even recently), for all I know there could be some elegant CSS-only solution. I don't see it in this thread though. – thirtydot Nov 21 '17 at 18:58
  • This one might be good: https://stackoverflow.com/a/21902566/405015. I don't know if that's the one you were referring to. – thirtydot Nov 21 '17 at 19:02
  • @thirtydot The width of the added `content:` is irrelevant to the underline, you can just disable the underline for that pseudo selector without having to add any additional markup as per @user5100822 's answer. – kontur Nov 22 '17 at 09:19
  • @kontur: [user5100822's answer](https://stackoverflow.com/a/31330454/405015) doesn't work for me. Here's an implementation: http://jsfiddle.net/thirtydot/3fvj38em/. Does not work in Chrome/Firefox, the `:before` content is underlined for me on hover. It "works" in IE11, the `:before` content is not underlined. Did I implement it incorrectly? – thirtydot Nov 23 '17 at 10:53
10

http://jsfiddle.net/LmvgM/8/

It can be achieved with css only, without additional html markup by setting position:relative to the link, and respectively position:absolute to :before content.

Using this example...

<div class="box blueb">
    <a href="#">Hello</a>
</div>

... the css will look like this:

.box.blueb a { 
    color: #0098aa; 
    position: relative;
    margin-left: 5px;
    padding-left: 10px;
    text-decoration: none;
}

.box.blueb a:before { 
    content: "> "; 
    position: absolute;
    top: 0;
    left: 0;
}

.box.blueb a:hover {
    text-decoration: underline;
}
roushan
  • 101
  • 1
  • 3
8

You can do it css only adding display: inline-block to the :before element:

.box.blueb a { color: #0098aa; }
.box.blueb a:hover { text-decoration: underline; }
.box.blueb a:before { content: "> "; display:inline-block; }

Demo: http://jsfiddle.net/CaNyx/


Edit:

The problem is that with display: inline-block the space is not shown, but you can fix it with white-space: pre or white-space: pre-wrap

Demo: http://jsfiddle.net/CaNyx/1/

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Unfortunately, IE11 says no. – Jorrit Schippers Dec 13 '13 at 15:10
  • @JorritSchippers Really? I was starting to think that new versions of IE suck...less, but it seems IE will always be IE and suck a lot. – Oriol Dec 13 '13 at 21:16
  • @JorritSchippers I have tested it and it seems it doesn't work on any IE version. What a shame, that behavior is defined in CSS2.1 and according to Microsoft, IE8 should support CSS2.1 completely. – Oriol Dec 13 '13 at 21:30
  • 1
    Finally Microsoft fixed it. Works as expected on Edge. – Oriol Aug 16 '16 at 19:03
6

Try this if you want a CSS only solution. For it to work in IE, you need to explicitly turn it on before you turn it off for the pseudo elements:

a {text-decoration:none;}
a:hover {text-decoration:underline;}
a:before { text-decoration:underline;}
a:before,
a:hover:before {text-decoration:none;}

So in your example you would need it to be written:

.box.blueb a { text-decoration:none; }
.box.blueb a:hover { text-decoration: underline; }
.box.blueb a:before { text-decoration: underline; }
.box.blueb a:before,
.box.blueb a:before:hover { text-decoration: none; }
user5100822
  • 61
  • 1
  • 1
0

This question was also asked at :hover:before text-decoration none has no effects? and answer https://stackoverflow.com/a/13376725/261747 worked for me in IE too.

Community
  • 1
  • 1
Jorrit Schippers
  • 1,538
  • 12
  • 17
0

I know this doesn't answer how to stop an anchor's before content from being underlined.
But the best work-around I find when I need this behavior is not using a:before.

HTML:

<nav class="breadcrumb">
    <span><a href="#">Test 1</a></span>
    <span><a href="#">Test 2</a></span>
    <span><a href="#">Test 3</a></span>
</nav>

CSS:

nav.breadcrumb > span:before             { content: "> "; }
nav.breadcrumb > span:first-child:before { content: "";   }

So, specifying :before pseudo-class for the element that wraps the anchor, instead of the anchor itself seems like the best solution at the moment.


Another example if you prefer using lists:

HTML:

<ul class="breadcrumb">
    <li><a href="#">Test 1</a></li>
    <li><a href="#">Test 2</a></li>
    <li><a href="#">Test 3</a></li>
</ul>

CSS:

ul.breadcrumb                         { margin: 0; padding: 0; }
ul.breadcrumb > li                    { display: inline;       }
ul.breadcrumb > li:before             { content: "> ";         }
ul.breadcrumb > li:first-child:before { content: "";           }
Şafak Gür
  • 7,045
  • 5
  • 59
  • 96