Pixelastic

You can cut our wings but we will always remember what it was like to fly.

Posts tagged with ":after"

IE8 ghost :after and :before pseudo elements

IE8 has a strange bug (what bugs aren't strange in IE ?) when dealing with :after and :before pseudo-elements.

I was adding a nice looking arrow after one of my elements using :after. I wanted this arrow to only display when my element was hovered, so I wrote the following code :

<a href="#">Example</a>
a {
position:relative;
display:block;
height:30px;
}
a:after {
position:absolute;
content:"";
top:0px;
right:-15px;
width:15px;
height:30px;
background:url(arrow.gif) top left no-repeat;
display:none;
}
a:hover:after {
display:block;
}

As you can see, nothing too fancy. I positionned my arrow using an empty :after element and a background image. I defaulted the arrow to hidden, and only show it when hovering the element.

IE in action

It does work pretty well in moder browsers. It also seems to work on IE8. When you hover the element in IE8, the arrow gets displayed. But it does not gets hidden when you stop hovering it.

There's a kind of ghost element that keeps getting displayed. It gets removed if you directly mouse it, or scroll your page, or alt-tab, etc. This clearly is a display artefact.

To counter this I had to write it in an other fashion (less readable in my opinion). Removing the default a:after rule and adding all properties to a:hover:after :

a {
position:relative;
display:block;
height:30px;
}
a:hover:after {
position:absolute;
content:"";
top:0px;
right:-15px;
width:15px;
height:30px;
background:url(arrow.gif) top left no-repeat;
display:block;
}

Update

It should be noted that more generally, I gets confused and create ghost elements and styling when we try to update the :after/:before properties based on a rule selecting its parent.

There seems to have a little lag/delay before the properties gets applied, and most of the time they do not.

Text emboss in CSS

I know only two unperfect ways of displaying an emboss text in CSS. As we can't use inset shadows with text-shadow, unlike box-shadow, we have to resort to other hacky ways.

Let me show you what can be done.

Simulate it with an optical illusion

Instead of creating a real inner shadow, you can just create an optical illusion by adding the correct shadow to make the viewer believe your text is embossed.

If you have dark text, just add a subtle white shadow at the bottom, while if you have light text, just add a subtle black one at the top.

<a class="emboss light">Lorem ipsum</a>
<a class="emboss dark">Lorem ipsum</a>
.emboss { font-size:1.2em; padding:50px; font-weight:bold; background:#0A539C; display:block; }
.light { color:#FFFFFF; text-shadow:0px -1px 0px rgba(0,0,0,0.9); }
.dark { color:#000000; text-shadow:0px 1px 0px rgba(255,255,255,0.1); }

I added an emboss class to more easily spot the effect, but the important code is in the light and dark rules.

Add an almost transparent layer

For this second solution we will simply add a second layer with the exact same text above the first text. Just slightly moving it and making it partly transparent.

You could add twice your element in your markup, but that would be bad for accesibility as well as SEO, so we'll instead use the :before pseudo-class.

We can set the :before content using the content: property, and we can also use the attr() method to get the content of one of our element's attributes. We just need to put the exact same text in one of our attributes and we're good to go.

This can be easily done with a link and its title attribute.

<a class="emboss lightAgain" title="Lorem ipsum">Lorem ipsum</a>
<a class="emboss darkAgain" title="Lorem ipsum">Lorem ipsum</a>
.lightAgain { color:#FFFFFF; position:relative; }
.lightAgain:before {
    content: attr(title);
    position:absolute;
    color:rgba(0,0,0,0.1);
    top:-1px;
    left:-1px;
    padding:50px;
}
.darkAgain { color:#000000; position:relative; }
.darkAgain:before {
    content: attr(title);
    position:absolute;
    color:rgba(255,255,255,0.1);
    top:1px;
    left:1px;
    padding:50px;
}

The effect is much better with this technique but it also has it share of drawback :

  • You have to write your content twice, once in the element and once in an attribute
  • You have to copy all your padding rules in the :before element or it won't get correctly positionned
  • You can't select the text with this effect

Hope those two little techniques helped someone, anyway.

Using :after and :before

:after and :before pseudo-elements allow one to add generated content before or after an other element. It can be used to add quotes around text, icons after a link to specify the language of the target page and a lot of other useful stuff like that.

It can also be mastered to create more powerful styling. I'll post more about that later.

Anyway, IE6 and IE7 don't support it. Firefox is supposed to support it from the 3.0 version but in fact it is still buggy in this release.

Pseudo-elements must be inline elements and can't be absolutly positionned in FF3.0, thus greatly reducing the number of fun things we could do with them in this browser.

It faced me with a challenge. If I wrote :before and :after rules, they would be only understood by FF3.0 but badly rendered, resulting in half the styling I expected.

Browsers that don't understand the rules would not apply them and keep the default rendering, compliant browsers will render all the rules, but the grey area in between is filled with FF3.0 that will think it can handle them and will finally badly render them.

I haven't found a way to specificaly target FF3.0, so I used an alternate method.

All the browsers that understand the :only-of-type selector also understand :before/:after. But FF3.0 and IE7 do not understand :only-of-type. So if I wrote a rule starting with body:only-of-type, it will only be applied to browsers with complete :after and :before support (excluding FF3.0). This solved my problem.

Unfortunatly, it will also filter out IE7 who does not understand :only-of-type but does understand :after/:before. I usually remove all fancy form styling for IE anyway so that's not a big deal for me, but if you really care, you just have to override the rule in a IE7 specific stylesheet.

Rendering bug with generated content on form fields in Opera

If you try the following code in Opera 10.51, you'll have some weird rendering bug :

<style>
.test:after {
content:"This should be on red background";
background:red;
}
</style>
Text input : <input type="text" value="I'm unstyled" class="test" />

The generated content is added to the page, but the background color isn't rendered. Worse, the input lose all styling, it does not have a background color nor borders anymore.

The same effect also apply to every input (radio, checkbox and password).

On a select tag, the generated content correctly have it's background color, but still lose all styling.

On a textarea, the styling is gone too, and the background color is here. Well, sort of, it is actually cropped after a while and the end of the text is on transparent background.

I sent a bug report to Opera about that.

Opera, input  generated content bug