Designing with Pseudo Elements in IE10

Pseudo Elements in IE10

When Internet Explorer 10 came onto the scene as one of the first desktop browsers engineered for touch, it brought with it a few upgrades to many form elements. Input fields began, overnight, to render with their own clear buttons, causing some anguish among designers who had already provided similar functionality on their own.


It wasn’t long until Stack Overflow, and other communities, began hearing the groans of web designers wanting to know how they can turn off these new progressive enhancements. But what initially appeared to be a nuisance is actually a great opportunity. These new pseudo elements give us more control than ever before.

Quick Brushup

Pseudo elements are parts of the document that are not declared in our markup, but are provided by the browser when rendering certain elements. For instance, pseudo-elements exist that represent the ::first-line of text in a paragraph. This requires no additional markup to function, but gives us great control over how things look.


I would like to cover nearly 20 pseudo elements in the remainder of this article, demonstrating with each what type of effect(s) we can achieve in our presentation.

Here’s a list of what we’re going to cover:

::after ::before
::first-letter ::first-line
::-ms-browse ::-ms-value
::-ms-check ::-ms-clear
::-ms-expand ::-ms-fill
::-ms-fill-lower ::-ms-fill-upper
::-ms-reveal ::-ms-thumb
::-ms-ticks-after ::-ms-ticks-before
::-ms-tooltip ::-ms-track

Before and After Pseudo Elements

The ::before and ::after pseudo elements create virtual children within the container (like an invisible <span> element). These appear before all other children, and after all other children, respectively. You can use these to achieve many great effects, such as fading an image out and adding text over the top of it.


The HTML for the above is very simple. It’s nothing more than an image within a figure element.

    <img src=”jonathan-sampson.jpg">

In the CSS we’re using ::after (::before is used the same way) to add a positioned element over the top of our image, give it a gradient background, and some text content.

figure {
    position: relative;

figure::after {
    /* Text and Color */
    color: white;
    font: 1em "Segoe UI";
    content: "@jonathansampson";
    text-shadow: 0 .1em .2em #004D71;
    /* Size and Placement */
    left: 0; bottom: 0;
    width: 100%; padding: 2em 0;
    display: block; position: absolute; 
    /* Background */
    background: linear-gradient(to top, white 1em, transparent);

First Line and Letter Pseudo Elements

By using the ::first-line and ::first-letter pseudo elements we can target the first line of text in a text block, as well as the first letter in that line, and modify their styles independently of their surroundings. By combining both of these, we can achieve an effect like the following:


The above consists of nothing more than a simple paragraph, as far as markup is concerned.

<p>When Internet Explorer 10 came onto the scene...</p>

The styles too are very concise and easy to understand.

p {
    font: 1em "Segoe UI";

p::first-line {
    font-weight: bold;

p::first-letter {
    font: 5em "Script";
    float: left;
    line-height: .5em;
    padding: .15em .15em 0;

Browse and Value Pseudo Elements

File uploads have always been a pain to style; in the past we didn’t have much access to the button itself. Today with the ::-ms-browse and ::-ms-value pseudo elements we can target individual parts of the file upload control and create a far better presentation than was ever possible before.


The markup here is familiar and short; it’s just a single file input.

<input type="file">

The CSS, on the other hand, is slightly more verbose since we’re targeting the input element, the browse and value pseudo elements collectively, as well as individually.

input {
    background: transparent;

::-ms-browse, ::-ms-value {
    border: 0;
    padding: 1em;
    color: rgb(71,194,254);
    background-color: rgb(1,132,195);
        linear-gradient(to bottom, transparent 1px, rgb(71, 194, 254) 1px, transparent 1em),
        linear-gradient(to top, transparent 1px, rgba(0,0,0,.2) 1px, transparent 2em);

::-ms-browse {
    font-weight: bold;
    background-color: rgb(1, 107, 157);
    border-radius: 0 .5em .5em 0;

::-ms-value {
    border-radius: .5em 0 0 .5em;

Check Pseudo Element

With ::-ms-check we now have access to the inner-part of a radio or checkbox. This means we can now modify its presentation just as easily as we could the rest of the element itself. In the example below we’ve increased padding, changed the background color of the checked-portion, updated the foreground color, and even added a subtle inner glow.


The CSS is very straightforward.

::-ms-check {
    border: 0;
    color: white;
    padding: .25em;
    background-color: rgb(1,132,195);
    box-shadow: inset 0 0 .5em rgb(71, 194, 254),

Clear and Reveal Pseudo Elements

This article opened with an example of the new ::-ms-clear pseudo element, and a short description of the frustration it has caused many designers who have already had long-standing functionality in place to clear fields. Often times designers just want it to go away.

::-ms-clear {
    display: none;

Easy enough.

Similar to the ::-ms-clear pseudo element is the ::-ms-reveal pseudo element. This is represented as a button in password fields. When pressed, and held, it reveals the password in the text box to which it is associated.

You can also set its display to none if you wish to get rid of it.

Expand Pseudo Element

The ::-ms-expand pseudo element grants you power over the button typically displayed with select menus. By leveraging this pseudo element we can round corners, set gradient backgrounds, and so much more.


I cheated here just a bit and added styles to both the select element, and the ::-ms-expand pseudo element.

select {
    color: #333;
    padding: .25em;
    border-radius: .5em;
    background-color: #f1f1f1;
        linear-gradient(to bottom, white, transparent);
    border: 1px solid rgb(71, 194, 254);

::-ms-expand {
    padding: .25em;
    margin-left: .25em;
    border-radius: 50%;
    color: rgba(0, 0, 0, .25);
    background-color: rgb(71, 194, 254);
        linear-gradient(to bottom, rgba(255, 255, 255, .8), transparent 1em);
    border: 1px solid rgba(71, 194, 254, .5);

Fill Pseudo Element

The ::-ms-fill pseudo element works with the <progress> element, which shows an advancement in a set of sequences or length of time. The “filled” portion of the progress bar is exposed to us for additional styling on top of those styles applied directly to the main element itself.

While this element, visually, isn’t as complex as others we can still have some fun with it.


progress {
    border: 0;
    height: 1.5em;
    border-radius: .25em;
    background-color: #f1f1f1;

::-ms-fill {
    border: 0;
        linear-gradient(to top, transparent 1px, rgba(255,255,255,.5) 1px, transparent 1em),
        linear-gradient(to left, rgba(0,0,0,.3) 3px, transparent 3px),
        linear-gradient(to right, rgba(0, 0, 0, .3), transparent);

Fill Upper/Lower, Ticks Before/After, Thumb, Tooltip, and Track Pseudo Elements

The range control is full of pseudo elements. The right side of the range, the left, the (optionally visible) ticks above or beside the control, the track itself, the popup tooltip, and the handle to change the value. In the following image you can see nearly every pseudo element adjusted in some way, shape, or form (tooltip not visible).


The upper fill was given a slight glimmer while the lower fill was left solid. The ticks before (above the slider) and after (below) were made lighter. The thumb was rounded, given a slight gradient for depth, and a hollow-looking center. Lastly the track pseudo element was given white, semi-opaque, markers.

::-ms-tooltip {
    display: none;

::-ms-ticks-before, ::-ms-ticks-after {
    color: #999;
    display: block;

::-ms-ticks-before {
    background: linear-gradient(to top, #CCC, transparent 30%);

::-ms-ticks-after {
    background: linear-gradient(to top, transparent 70%, #CCC);

::-ms-fill-upper {
    background-color: rgb(1, 107, 157);
        linear-gradient(to bottom, transparent 1px, rgba(255,255,255,.25) 1px, transparent 70%);

::-ms-fill-lower {
    background-color: rgb(1,132,195);

::-ms-thumb {
    background-color: white;
        radial-gradient(circle, rgb(1, 107, 157) 20%, transparent 20%),
        linear-gradient(to top, #CCC, white);
    border-radius: 50%;
    border: 0;

::-ms-track {
    color: rgba(255, 255, 255, .5);

Selection Pseudo Element

The last pseudo element we’re going to look at is the ::selection pseudo element. This represents any selection of text in the document. The control you have over this is extended to the foreground color, and background color of the selection.


By default selected text is white with a blue background. In the example above we have changed the text to black, and the background to hot pink (in true Irish fashion).

::selection {
    color: black;
    background: pink;


We’ve looked at nearly every pseudo element available in Internet Explorer 10, as well as a few types of modifications we can make to the UI by leveraging their presence in the document. It’s important to note that different browsers may have different pseudo elements you’ll have to target in order to modify the same (or similar) document elements. This post was merely an exploration of those that presently exist in Internet Explorer.

If you have any questions about the above examples, please feel free to reach out to myself, or any of my fellow IE User Agents. You can do so by leaving a comment below on this post, or tagging your tweet with the #IEUserAgents hashtag (we’re listening). If you have questions about general development and Internet Explorer, follow and interact with @IEDevChat on twitter.

If you would like access to Internet Explorer from your Mac to test these features, you can use BrowserStack, or download a free Virtual Machine from I use both methods regularly – I would encourage the virtual machine route if you have the space/memory.

That’s it. Go change the web.