“text-decoration” and the “:after” pseudo-element, revisited
Asked Answered
S

12

64

I'm re-asking this question because its answers didn't work in my case.

In my stylesheet for printed media I want to append the url after every link using the :after pseudo-class.

a:after {
    content: " <" attr(href) ">";
    text-decoration: none;
    color: #000000;
}

In Firefox (and probably Chrome but not IE8), text-decoration: none is ignored, and the underline stretches unattractively across the bottom of the url. The color however is correctly set to black for the url. Is there a way to make the text-decoration work?

The original question appended fixed size images instead of variable width text. Its answers use padding and background images to avoid having to use the text-decoration property. I'm still looking for a solution when the content is variable width text.

Sickler answered 6/8, 2009 at 13:26 Comment(2)
The most robust way to achieve this is the background image based approach.Rhapsody
I rewrote the question to clarify that I'm not using images at all.Sickler
M
22

IE8's implementation of the :before and :after pseudo-elements is incorrect. Firefox, Chrome and Safari all implement it according to the CSS 2.1 specification.

5.12.3 The :before and :after pseudo-elements

The ':before' and ':after' pseudo-elements can be used to insert generated content before or after an element's content. They are explained in the section on generated text.

...

Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification

The specification indicates that the content should be inserted before or after the element's content, not the element (i.e. <element>content:before content content:after</element>). Thus in Firefox and Chrome the text-decoration you're encountering is not on the inserted content but rather on the parent anchor element that contains the inserted content.

I think your options are going to be using the background-image/padding technique suggested in your previous question or possibly wrapping your anchor elements in span elements and applying the pseudo-elements to the span elements instead.

Medial answered 6/8, 2009 at 14:11 Comment(5)
After some more testing, I found out that text-decoration isn't applied, but color is. How does that behavior follow from the spec?Sickler
@palm3D: What you are not understanding is that the pseudo-selectors are not inheriting text-decoration, the anchor's text-decoration is just showing through. If you set a text-decoration for the pseudo-selector, it is rendered on top of the selector's text-decoration. Additionally if you set a background-color to the pseudo-selector it correctly blots out the text-decoration of the selector in Firefox, Chrome and Safari. Also switching between rendering modes in IE8/IE7 changes handling of pseudo-selectors dramatically so watch your DTD.Medial
In fact when you put eg. text-decoration: line-through; on "parent" element and eg. text-decoration: underline; on ::before/::after element, then BOTH styles are applied. And since you definitely can apply different styles to ::before/::after pseudo-ELEMENTS it's more like <element><before>content:before</before>content<after>content:after</after></element> structure than what you described. The possibility of inserting generated content doesn't mean it is only the content that is inserted.Qktp
@Qktp : I don't think you clearly articulated your point because nothing you said conflicts with my prior statements. In fact, despite trying to be contrary, you have only reinforced what I said.Medial
From your statement, particularly <element>content:before content content:after</element>, one may understand that ::before and ::after only generates content, while in fact it also generates, as this selector name suggests, pseudo-ELEMENTs. It might be easier to understand what's going under the hood, if one keep that in mind. And I wasn't contrary, I was supplementary or explanatory. 8)Qktp
L
147

If you use display: inline-block on the :after pseudo, the text-decoration declaration will work.

Tested in Chrome 25, Firefox 19

Laoighis answered 28/3, 2013 at 17:23 Comment(4)
But sadly not in IE, see my question: #18069725Stableboy
You're partially correct. The text-decoration doesn't actually work at all in this context, because the parent text-decoration can't be applied to inner inline-blocks in general. If you left out the text-decoration: none out entirely, it would still work.Smoker
Brilliant (Edge 42)Winebaum
Sadly, this method fails if your A tag is display:flex.Tibia
M
22

IE8's implementation of the :before and :after pseudo-elements is incorrect. Firefox, Chrome and Safari all implement it according to the CSS 2.1 specification.

5.12.3 The :before and :after pseudo-elements

The ':before' and ':after' pseudo-elements can be used to insert generated content before or after an element's content. They are explained in the section on generated text.

...

Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification

The specification indicates that the content should be inserted before or after the element's content, not the element (i.e. <element>content:before content content:after</element>). Thus in Firefox and Chrome the text-decoration you're encountering is not on the inserted content but rather on the parent anchor element that contains the inserted content.

I think your options are going to be using the background-image/padding technique suggested in your previous question or possibly wrapping your anchor elements in span elements and applying the pseudo-elements to the span elements instead.

Medial answered 6/8, 2009 at 14:11 Comment(5)
After some more testing, I found out that text-decoration isn't applied, but color is. How does that behavior follow from the spec?Sickler
@palm3D: What you are not understanding is that the pseudo-selectors are not inheriting text-decoration, the anchor's text-decoration is just showing through. If you set a text-decoration for the pseudo-selector, it is rendered on top of the selector's text-decoration. Additionally if you set a background-color to the pseudo-selector it correctly blots out the text-decoration of the selector in Firefox, Chrome and Safari. Also switching between rendering modes in IE8/IE7 changes handling of pseudo-selectors dramatically so watch your DTD.Medial
In fact when you put eg. text-decoration: line-through; on "parent" element and eg. text-decoration: underline; on ::before/::after element, then BOTH styles are applied. And since you definitely can apply different styles to ::before/::after pseudo-ELEMENTS it's more like <element><before>content:before</before>content<after>content:after</after></element> structure than what you described. The possibility of inserting generated content doesn't mean it is only the content that is inserted.Qktp
@Qktp : I don't think you clearly articulated your point because nothing you said conflicts with my prior statements. In fact, despite trying to be contrary, you have only reinforced what I said.Medial
From your statement, particularly <element>content:before content content:after</element>, one may understand that ::before and ::after only generates content, while in fact it also generates, as this selector name suggests, pseudo-ELEMENTs. It might be easier to understand what's going under the hood, if one keep that in mind. And I wasn't contrary, I was supplementary or explanatory. 8)Qktp
V
9

I had the same problem and my solution was to set height and overflow:hidden

http://jsfiddle.net/r45L7/

a {
    text-decoration: underline;
}

a:after {
    content: "»";
    display: inline-block;
    text-decoration: none;
    height:16px;
    overflow: hidden;
    padding-left: 10px;
}

It works on IE, FF, Chrome.

Vistula answered 30/5, 2014 at 17:30 Comment(2)
Looks like display: inline-block declaration is enough.Pfaff
If the above by extempl was an answer, not a comment, it would be the answer with the big tick.Evangelinaevangeline
G
6

As an alternative, you can use a bottom border rather than a text-decoration. This assumes that you know the color of the background

a {
  text-decoration: none;
  border-bottom: 1px solid blue;
}
a:after {
  content: "foo";
  border-bottom: 1px solid white; /* same color as the background */
}
Golding answered 8/10, 2012 at 9:30 Comment(0)
A
6

1)

:after{
    position: absolute;
}

is not perfect, because element content will not wrap

2)

:after{
    display: inline-block;
}

is not perfect, because sometimes we wish after content should always wrap with last word of element content.

For now, I could not find find a perfect solution fits all 3 conditions(1. content could auto-wrap if it's too long 2.after content should wrap with element content, which means after content should not occupy single by it self. 3.text-decoration should only apply on element condition not apply to after content.) I thoughts for now is using other way to mimic text-decoration.

Abeu answered 17/10, 2018 at 23:27 Comment(0)
C
5

What I do is I add a span inside the a element, like this :

<a href="http://foo.bar"><span>link text</span></a>

Then in your CSS file :

a::after{
  content:" <" attr(href) "> ";
  color: #000000;
}

a {
  text-decoration:none;
}

a span {
  text-decoration: underline;
}
Cyclostome answered 28/4, 2017 at 12:41 Comment(0)
C
3

The only thing that worked for me was declaring a separate repeated selector with the same text-decoration property that it was inheriting from its parent, then in the main selector, setting text-decoration to none.

IE apparently does not know what to do when you set text-decoration: none on a pseudo element without that element having the text-decoration property declared (which by default, it has nothing declared by default). This makes little sense because it is obviously being inherited from the parent, but alas, now we have modern browsers.

span.my-text {
  color: black;
  font-size: 12px;
  text-decoration: underline;
}

span.my-text:after {
  text-decoration: underline; // Have to set text-decoration here so IE knows it can be overwritten below
}

span.my-text:after {
  color: red;
  text-decoration: none; // In the same repeated selector, we can now overwrite text-decoration in our pseudo element.
}
Cott answered 25/5, 2016 at 18:12 Comment(0)
B
1

I realise this isn't answering the question you're asking, but is there a reason you can't use the following (background-based approach):

a.file_pdf {
background-image: url(images/pdf.png);
background-position: center right;
background-repeat: no-repeat;
padding-right: 15px; /* or whatever size your .png image is plus a small margin */
}

As far as I know, the Firefox implementation of :after observes the property of the selector's class, not the psuedo-class. It might be worth experimenting with different doctypes, though? The transitional, rather than strict, sometimes allows for different results (albeit not always better results...).

Edit:

It appears that using

a:after {
    content: " <" attr(href) ">";
    text-decoration: none;
    color: #000000;
    background-color: #fff; /* or whatever colour you prefer */
}

overrides, or at least hides, the text-decoration. This doesn't really provide any kind of answer, but at least offers a workaround of sorts.

Blaney answered 6/8, 2009 at 13:58 Comment(2)
Firefox's behavior is according to specification. The pseudo-selector content is nested inside the selector as it should be. See my answer for clarification.Medial
I rewrote the question to clarify that I'm not using images at all.Sickler
O
0

You can autoselect links to pdf-files by:

a[href$=".pdf"]:after { content: ... }

IE less than 8 can be enabled to work properly by implementing this link in the head of the html-file:

<!--[if lt IE 8]><script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script><![endif]-->

It works also very good in al IE versions when you use the after-before-content-thing for dosplaying quotation marks.

Onomatology answered 6/8, 2009 at 20:15 Comment(1)
I rewrote the question to clarify that I'm not interested in selectors, only the behavior of text-decoration in the :after pseudo-class.Sickler
P
0

Position the content absolutely as follow:

a {
    position: relative;
    margin: 0 .5em;
    font-weight: bold;
    color: #c00;
}
a:before,
a:after {
    position: absolute;
    color: #000;
}
a:before {
    content: '<';
    left: -.5em;
}
a:after {
    content: '>';
    right: -.5em;
}

This works for me in Firefox 3.6, not tested in any other browsers though, best of luck!

Perceive answered 6/10, 2010 at 15:37 Comment(0)
I
0

Hi I was also having trouble with this as well and happened to stumble across a workaround.

To get around it, I wrapped the URL in div and used something like this.

.next_page:before {
    content: '(';
}

.next_page:after {
    content: ')';
}
Illustration answered 11/3, 2013 at 1:37 Comment(0)
I
0

For hide underline I use the same color for underline as the background color of pseudo element:

<a class="a-element">link text</a>

And css:

a {text-decoration: underline;}
a::after{content:"external";text-decoration-color:white;} /* IF background color is white */

Another example

 a {text-decoration: underline;}
    a::after{
    content:"external";
    background-color: red;
    text-decoration-color:red; /* same as background color */
}
Incinerate answered 29/5 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.