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.

image05

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.

image06

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
::selection

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.

image02

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

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

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:

image03

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.

image07

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);
    background-image: 
        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.

image09

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.

image01

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;
    background-image:
        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);
    background-image: 
        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.

image00

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

::-ms-fill {
    border: 0;
    background-image:
        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).

image08

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);
    background-image: 
        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;
    background-image: 
        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.

image04

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;
}

Conclusion

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 http://modern.ie. 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.

Display: Grid – The Future of Responsive Grid Layouts

Brief History

The history of front-end design strategies is a wild thing to study. We started with linear page-outlines, largely consisting of a wall of text and hyperlinks. We later got clever and began co-opting <table> to give us more control over page layouts. We should have all been smacked for doing it, but it was the convention at the time.

When tables began to be more of a nuisance than a solution the community started leveraging floats, and working to define their design requirements in terms of laterally-shifted elements that sat next to one another. Of course that too presented a new set of problems – we had to perform an embarrassing amount of CSS acrobatics to clear our floats, or achieve something as simple as the Holy Grail of layouts (which was trivial with <table>).

Things got better; tried and true conventions and approaches were packaged up into wildly popular frameworks like Nathan Smith’s 960 Grid System, and appeared to have solved all of our problems for a short while. But the fact remained that while we had comfort, it came at the cost of meaningless additional markup, and cryptic classnames. The DOM was getting noisy.

Introducing Grid Layouts

Browser vendors and standards bodies took it upon themselves to start working on alternative, more reliable solutions. With the release of Internet Explorer 10 we saw the first major browser implement a CSS-based Grid System.

For the first time, we are able to author our content as it ought to be, without nesting it in arbitrary ad-hoc divs to give ourselves a little advantage in CSS. We can now turn simple markup into easily-manipulated sophisticated layouts.

No more absolutely positioned elements, pointless margins or padding, etc. CSS Grids completely liberate you – the designer – from having to wrestle with the layout engine to get the effect you want without forcing you to compromise on your markup or CSS.

Defining Columns and Rows

The CSS is remarkably very simple to grok; and if you’ve ever spent any time in the past wiggling through tables, you’ll find much of the code very familiar-sounding. We start by setting an element up as our grid container. In the code above, I used the body element:

body {
  display: -ms-grid;
}

Because this technology is still experimental, you can only access it by using the -ms- prefix. Once we have set our display mode to -ms-grid, we have to define our columns and rows. This too is very straightforward:

body {
  display: -ms-grid;
  -ms-grid-rows: 100px 200px 1fr;
  -ms-grid-columns: 1fr 150px;
}

This results in a grid that has three rows, and two columns. Think of a table that has three table rows, and two table cells in each row. Our first row is 100px tall. Our second is 200px tall. Lastly, our third row is the full remaining fractional value; so whatever is left over after 300px is taken away, that will be the height of our third row.

We took a similar approach for our columns. Our first column takes the remainder of the horizontal space left over after 150 pixels have been given to our second column. At this point, your design will be mangled beyond recognition. Until you specify where each element ought to reside, they will all be tossed into row one, column one – do you even grid, bro?

Placing and Sizing Grid Items

Once you have your rows and columns defined, it’s trivial to move your elements around from any column or row to another. For instance, suppose we wanted to move our <h1> element into the first row, and have it span both columns:

h1 {
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  -ms-grid-column-span: 2;
}

It’s so straightforward that it requires no explanation.

Not only can we specify which column and row our element resides in, we can also instruct our element to span additional columns and rows to better align our grid contents as we see fit.

Your main bag of tools consists of the following properties:

Property Description
-ms-grid-row target row
-ms-grid-row-align horizontal alignment
-ms-grid-row-span number of rows to span
-ms-grid-column Target column
-ms-grid-column-align Vertical alignment
-ms-grid-column-span Number of columns to span

The alignment properties accept values such as start, end, center, and stretch. In a left-to-right layout, start will align the element to the left while end will align it to the right. Stretch will cause the element to consume all available space in the grid location. By default grid items are stretch, so don’t freak out if an image initially looks wonky.

Responsive Grids

With this much control over the layout in our CSS, you can imagine the amount of flexibility we have when we add media queries into the mix. All of a sudden, we can rearrange everything when in portrait mode as opposed to landscape, or desktop as opposed to mobile.

Below I created a simple example that shifts the layout around above and below the 400 pixel mark. In the left image we have more of a “mobile” experience, and in the right we’ve rearranged the elements (without touching the markup, woot) to present a wider experience.

image02image00

Here are the two media queries. Note the small amount of changes needed to completely restructure things.

body {
  -ms-grid-columns: 50% 50%;
  -ms-grid-rows: auto auto 1fr;
}

@media screen and (max-width: 400px) {
  nav  {
    -ms-grid-row: 2;
    -ms-grid-column: 1;
    -ms-grid-row-align: center;
    -ms-grid-column-align: center;
  }
  h1 {
    -ms-grid-row: 1;
    -ms-grid-column: 1;
    -ms-grid-column-span: 2;
    -ms-grid-row-align: center;
    -ms-grid-column-align: center;
  }
  img {
    -ms-grid-row: 2;
    -ms-grid-column: 2;
  }
  article {
    -ms-grid-row: 3;
    -ms-grid-column: 1;
    -ms-grid-column-span: 2;
  }
}

@media screen and (min-width: 400px) {
  nav  {
    -ms-grid-row: 3;
    -ms-grid-column: 2;
  }
  h1 {
    -ms-grid-row: 2;
    -ms-grid-column: 2;
  }
  img {
    -ms-grid-row: 1;
    -ms-grid-column: 2;
  }
  article {
    -ms-grid-row: 1;
    -ms-grid-column: 1;
    -ms-grid-row-span: 3;
  }
}

I have purposefully kept the examples here relatively simple, but only because I don’t feel this requires a great deal of explanation to get my point across – grids are freaking amazing.

In this short introduction we’ve seen how to create a grid container, assign arbitrary numbers of columns and rows with various dimensions. We placed elements, moved them around, and dynamically updated their properties to completely reconfigure our layout.
In the midst of all this excitement, there is a bit of bad news (isn’t there always?).

The Caveat

As of writing this the only browser to currently support CSS Grids is Internet Explorer 10. This means all of the code from above will have no effect in Chrome, Firefox, Opera, or any of the other major browsers. Check caniuse.com/css-grid for most recent changes.

If you are interested in developing Windows Store Applications with HTML, CSS, and JavaScript, you can definitely put this feature into your bag of tricks to ensure your app looks and feels the way you expect.

Although you can’t put it to much use on the open web, it is still good to begin developing a familiarity with the technology as the W3C Grid Layout spec is in the works and will hopefully find its way to Candidate Recommendation in the future.

Need More Direction?

If you’re looking for some assistance with any of the above content, or even with IE’s implementation of CSS Grids, you have a few places you can go to get assistance. Stack Overflow is almost always my first suggestion, though it currently doesn’t have much content around IE’s CSS Grids implementation (likely to change in the near future).

Another great place to look would be the @IEDevChat account on twitter. Additionally, if you want to get the attention of the User Agents (of useragents.ie) you can tag your tweet with #IEUserAgents. This notifies a developer experienced in Internet Explorer to come and assist you. Sweet deal, right?

On a Mac? Don’t have Internet Explorer 10? You’re not out of luck – you can test all of these features using http://browserstack.com. Additionally, you can download a free virtual machine with IE10 from http://modern.ie. I happen to be working on this demo in a virtual machine, and the performance is stellar on my MacBook Air in Parallels.

That’s it. Go be awesome.

Taming the Lawless Web with Feature Detection

The Lawless Web

Over the past 15 years or so that I’ve been developing websites, I’ve seen various conventions come and go. Common practices arise, thrive for a while, and die. I, myself, spent a great portion of my past hammering out lines of tabular markup (and teaching classrooms to do the same) when working on my layout.

When I wasn’t building complicated table-based layouts littered with colspans, I was double-wrapping elements to iron out the differences between browser-interpretations of the box-model.

Fortunately, these practices have died, and others like them continue to die every day.

The Web Hasn’t Been Completely Tamed

While atrocities like table-based layouts are quickly becoming a thing of the past, other old habits have chosen not to go as peacefully. One that has managed to stick around for some time is user-agent sniffing; the practice of inferring a browser’s abilities by reading an identification token.

var browser = {
     vendor: navigator.userAgent.match(/Chrome|Mozilla|Opera|MSIE/),
    version: navigator.userAgent.match(/\d+/)
};

if ( browser.vendor == “Mozilla” && browser.version == 5 ) {
    // This matched Chrome, Internet Explorer, and a Playstation!
    // Nailed it.
}

Since shortly after the dawn of the epoch, developers have been scanning the browser’s navigator.userAgent string for bits and pieces of data. They then couple this with a knowledge of which browsers support which features, and in conclusion make judgements against the user’s browser and machine. Sometimes their conclusions are correct, but the ends don’t justify the means.

Don’t Gamble With Bad Practices

Sniffing a browser’s user agent string is a bit like playing Russian Roulette. Sure, you may have avoided the loaded chamber this time, but if you keep playing the game you will inevitably increase your chances of making a rather nasty mistake.

The navigator.userAgent string is not, and has never been, immutable. It changes. It gets modified. As browsers are released, as new versions are distributed, as browsers are installed on different operating systems, as software is installed in parallel to the browser, and as add-ons are installed within the browser, this string gets modified. So what you sniff today, is not what you will sniff tomorrow.

Have a quick look at a handful of examples for Chrome, Firefox, Opera, and Internet Explorer. Bottom line is that you can’t be sure what you’ll get when you approach the user agent string buffet. As is immediately clear, the above approach would not even match version 12 of Opera consistently with its variations.

So, have I thoroughly convinced you that sniffing is bad? And have you sworn it off as long as you shall live? Let me give you something to replace it; something reliable that will nearly never let you down – feature detection.

Go With What’s Reliable

Feature detection is the practice of giving the browser a test, directly related to the feature you need, and seeing whether it passes or fails. For instance, we can see if the browser supports the <video> tag by quizzing it on whether it places the correct properties on a freshly-created instance of the element. If the browser fails to add the .canPlayType method to the element, we can assume support isn’t there, or isn’t sufficient to be relied upon.

This approach doesn’t require us to make any assumptions. We don’t couple poorly-scavenged data with naive assumptions about which browsers support which feature. Rather, we invite the browser out onto our stage, and we demand it do tricks. If it succeeds, we reward it. If it fails, we ditch it and take another approach.

What Does “Reliable” Look Like?

So how exactly do we quiz the browser? Feature-detections come in all shapes and sizes; some very small and concise, while others can be somewhat lengthy and verbose – it all depends on what feature you’re trying to test for. Working off of our example of checking for <video> support, we could do the following:

if ( document.createElement(“video”).canPlayType ) {
    // Your browser supports the video element
} else {
    // Aw, man. Gotta load Flash.
}

This approach creates a brand new video element for testing. We then check for the presence of the .canPlayType method. If this property exists, and points to a function, the expression will be truthy and our test will pass. If the browser doesn’t understand what a video element is, there won’t be a .canPlayType method, and this property will instead be undefined – which is falsy.

The Work Has Been Done For You

You could be rightly freaked out about now, thinking about all of the tests you would have to write. You might want to see if localStorage is supported, gradients, video, audio, or geolocation. Who on Earth has time to write all of those tests? Let alone learn the various technologies intimately enough to do so? This is where the community has saved the day.

Modernizr is an open-source library packed full of feature-detection tests authored by dozens of talented developers, and all bundled up in an easy to use solution that you can drop into any new project. You build your custom download of Modernizr, drop it into your project, and then conditionally deliver the best possible experience to all visitors.

Modernizr exposes a global Modernizr object with various properties. You can test for the support of certain features simply by calling properties on the Modernizr object.

if ( Modernizr.video ) {
    // Browser supports the video element
}

Additionally, it can optionally add classes to your <html> element so your CSS can get in on the action too! This allows you to make conditional adjustments to your document based upon feature support.

html.video {
    /* Woot! Video support. */
}

html.no-video #custom-video-controls {
    /* Bummer. No video support. */
    display: none;
}

Building A Better Web

By using feature-detection, and forever turning your back on user agent sniffing, you create a more reliable web that more people on more devices and browsers can enjoy. No longer are you bound to hundreds upon hundreds of user agent strings, or naive assumptions that will come back and bite you in the end. Feature-detection liberates you so that no babysitting of the browser landscape is necessary.

Code for features and APIs. Don’t code for specific browsers. Don’t get caught writing “Best viewed in WebKit” code – build something for everybody. When you focus on features, rather than ever-changing strings that don’t give you much insight, you help make the Internet better for us all. Do it for the children ;)

You’re Not Alone

When you set out to do things the right way, you will undoubtedly run into obstacles and complications. Let’s face it, quality work often times requires more of an investment than the slop that is so often slung out onto the web. The great news though is that you’re not alone – the web is more open than ever before, full of those willing to help you along the way.

Drop in to Stack Overflow to catch up on the various feature detection questions being asked there. Or if you’re trying to get Chrome and Internet Explorer to play nice with one another, post a question on Twitter using the #IEUserAgents hashtag. This notifies an “agent” to come to your aid.

Just be sure to pay it forward. As you learn, and grow, help others to do so as well. Maybe even write a few feature-tests and contribute them back into Modernizr along the way.

HTML Hangout Concludes after 16 Hours

For months I have been doing a weekly HTML Hangout where I work, slowly, through the W3C Specification for HTML5. I’m pleased to say that after 15 videos, and 16 hours, we’ve gotten to the point where we can progress on to bigger and better things.

HTML is now taken care of, and we will now move on to making this a weekly CSS Hangout. If you’d like to watch the HTML5 lessons, you can do so by viewing this playlist of YouTube: http://www.youtube.com/playlist?list=PL3IYnZmsleiXRVk1G-dcX4AJ_9kcSIO99.

If you’d like to join us in the future, simply show up to http://learn.sampson.ms on Thursdays at 7:30PM Eastern. Broadcast usually starts about 10 minutes early, and we open up the last 10-15 minutes for questions and answers.

Progress Dots

From time to time I need to throw together a small script to do something relatively simple. Today I had to write something that would animate a series of dots. You’ve seen it, those little lines of dots that grow and shrink to give indication that something, somewhere is happening.

It’s a relatively straight forward script, so I’ll just drop it in here with comments:

(function () {

    "use strict";

    // Find #dots, run setDots every 500ms, define your dot, and set size limit
    var dots = document.getElementById("dots"),
        loop = setInterval(setDots, 500),
        _dot = ".",
        size = 3;

    function setDots () {
        // #dots will be truncated when limit is reached, otherwise grows by one
        dots.innerHTML = (dots.innerHTML.length >= size) ? _dot : (dots.innerHTML + _dot);
    }

}());

It’s worth noting that you could probably whip up something similar with CSS alone using pseudo-elements, animation, @keyframes, and content, or even animating a sprite’s location on a background. Of course browser support would be far more limited.

Visualizing :hover Propagation

The :hover pseudo-class can be tossed into a CSS selector to target the state of the element when the user’s cursor is currently positioned over the element. Due to the hierarchical structure of the DOM, anytime you activate the :hover state of an element, you activate it for all ancestral elements too. Wanting a quick illustration for this, I took to JSFiddle.

http://jsfiddle.net/FwKqq/6/show/

Polyfill for Reversed Attribute on Lists

Lists in HTML typically appear in decimal fashion, starting from 1 and going to n. Sometimes these are instructed to appear in reversed order via the reversed boolean attribute on the ol element.

<ol reversed>
    <li>I am number two.</li>
    <li>And I am number one.</li>
</ol>

Some browsers don’t understand the reversed attribute, and thus will not reverse the list. Although you cannot reverse the entire list in some browsers with this attribute, you can manually override the value associated with each list item in most browsers via the value attribute.

<ol>
    <li value="2">I am number two.</li>
    <li value="1">And I am number one.</li>
</ol>

Using jQuery, we can quickly create a short polyfill that will give us reversed functionality in browsers where it’s not natively understood.

(function () {
    if ( $("<ol>").prop("reversed") === undefined ) {
        $("ol[reversed]").each(function () {
            var $items = $(this).find("li");
            $items.attr("value", function ( index ) {
                return $items.length - index;
            });
        });
    }
}());

The code should be fairly straight-forward, but let me explain what is going on just to be on the safe side.

We start with an IIFE (Immediately Invoked Function Expression) which runs our code instantly, as well as keeps all declared variables out of the global namespace.

Next we kick things off with a quick feature-test on a freshly-made ol. In browsers that understand the reversed property, the default value is false. In other browsers, the property is undefined.

We then grab a collection of all lists that have the reversed attribute. Next we cycle over this collection of lists, assigning the list items from each iteration to the variable $items.

We then take the $items jQuery collection and begin an implicit loop setting the value attribute of each item in the collection to collection.length - itemIndex. If there are five items in the list, and we’re on index 0 (first item), five will be returned as the value. When we enter the second iteration, and the index is 1, (5-1) will be returned, resulting in a value of 4.

Voila, we have polyfilled reversed. There are some shortcomings; this won’t work on lists created after this code runs. You could however put this logic into a function declaration and call it after the DOM has been updated asynchronously, so as to handle any new lists that might have populated the document.

One very important note when using jQuery as a means to polyfill older browsers, you will have to use jQuery 1.8.3 or below. Around the release of jQuery 1.9, a lot of antiquated code was removed that once propped up older browsers. jQuery 1.9 and forward are meant for modern browsers, and as such they will fail in carrying your polyfilled functionality back to older browsers like Internet Explorer 6, and its contemporaries.

IE10 Gotcha: Animating Pseudo-Elements on Hover

I came across a question on Stack Overflow today asking about animating pseudo-elements. This is something I have lamented over in the past since it’s been a supported feature in Internet Explorer 10 for a while, but only recently implemented in Chrome version 26. As it turns out, there was a small edge-case surrounding this feature that I had yet to encounter in Internet Explorer 10.

The following code does two things; first it sets the content and transition properties of the ::after pseudo-element for all paragraphs (there’s only one in this demo). Next, in the :hover state (or pseudo-class), it changes the font-size property to 2em. This change will be transitioned over 1 second, per the instruction in the first block.

p::after {
    content: ", World.";
    transition: font-size 1s;
}

p:hover::after {
    font-size: 2em;
}

Although simple and straight forward, this demo (as-is) doesn’t work in Internet Explorer 10. Although IE10 supports :hover on any element, and IE10 supports pseudo-elements, and IE10 supports animating pseudo-elements, it does not support all three, together, out of the box.

If you change your markup from using a paragraph to using an anchor element, the code begins to work. This seems to suggest some type of regression has taken place, causing Internet Explorer 10 behave similar to Internet Explorer 6 where only anchors could be “hovered” — support for :hover on any element was added in version 7.

Upon playing with this a bit, there does appear to be a few work-arounds:

  1. Change your markup
  2. Use sibling combinators in your selector
  3. Buffer a :hover selector on everything

Let’s look at these one at a time.

Change Your Markup

Rather than having a paragraph tag, you could nest a span within the paragraph, or wrap the paragraph in a div. Either way, you’ll be able to modify your selector in such a way so as to break up the :hover and ::after portions. When the user hovers over the outer element, the content of the inner-element’s pseudo-element is changed.

I don’t like this option; it’s far too invasive and demanding.

Use Sibling Combinators in Your Selector

This was an interesting discovery. I found that if you further modify your selector to include consideration for sibling elements, everything is magically repaired. For instance, the following targets our paragraph based on some other sibling paragraph:

p~p:hover::after {
    font-size: 2em;
}

This is interesting; it doesn’t break the connection between :hover and ::after, but it does modify the root of the selector, which somehow causes things to repair themselves.

What I don’t like about this approach is that it requires you to explicitly declare the sibling selector, as well as the element you’re wishing to target. Of course, we could fix this a bit by targeting a class or id, as well as going with a different sibling combinator:

*~.el:hover::after {}

This targets any element with the .el class that is a sibling of any other element. This gets us a little closer, but still, a bit messy. It requires us to modify every single selector that is part of a pseudo-element animation.

Buffering the :hover Selector

Provided with the question on Stack Overflow was one solution to the problem. As it turns out, if you provide an empty set of rules for the hover state, this fixes all subsequent attempts to animate pseudo-element properties. What this looks like follows:

p:hover {}

p::after {
    content: ", World.";
    transition: font-size 1s;
}

p:hover::after {
    font-size: 2em;
}

Oddly enough, this small addition does indeed resolve the issue. Given the nature of CSS, you can even drop the p portion, and just go with the following fixing it for all elements:

:hover{}

This too results in a functioning Internet Explorer 10 when it comes to animating pseudo-element properties.

Experiment: http://jsfiddle.net/jonathansampson/N4kf9/

Creating a (autofocus) Polyfill

In the ever-changing world of browser topography, every so often there exists an expectation in the community that some feature or API will be available in a browser, and it’s not.

We have an approach to mitigating these types of issues though, and we call it polyfilling. To quote Remy Sharp, “A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. Flattening the API landscape if you will.”

A question was recently asked on Stack Overflow about automatically applying focus to an input element when the page loads. The first responses suggested using a tool like jQuery to target the element, and invoke its focus method. While this works, it adds additional overhead in environments where it’s not needed.

My initial solution to the question was to use the autofocus boolean attribute on the input element of choice. Shortly after suggesting this, I realized this attribute was only introduced in Internet Explorer at version 10, meaning users of 6, 7, 8, and 9 wouldn’t get the behavior the developer expected – perfect opportunity to author a polyfill.

Our goal in building a solid polyfill is to not make its presence known; we want the web developer to author their markup as they would normally, while we quietly teach the browser to make sense of the unknown autofocus attribute.

So we start with basic HTML:

<input name="name" placeholder="John Doe" autofocus />

In browsers like Internet Explorer 10, Chrome 26, or Firefox 20, focus will be immediately given to this element upon page load. But for Internet Explorer 6-9 and versions of Firefox prior to 4.0, we’ll have to add a bit of assistance.

We start by first performing a feature-detect for the autofocus property in a freshly-created input element. In browsers that support this property, the default value is false:

// Proceed only if new inputs don't have the autofocus property
if ( document.createElement("input").autofocus === undefined ) {

}

This condition will only evaluate to true in browsers that don’t natively understand the autofocus attribute, and as such, this will be our sandbox to play in while constructing our polyfill. We’ll need to go through a few steps for this polyfill, so let’s have a look at what they are:

  1. Cycle over all forms
  2. Cycle over all elements in each form
  3. Check attributes of each element for autofocus
  4. If found, trigger focus, and break out of all loops (only one instance of autofocus should exist on in a document, otherwise you’ll get inconsistent cross-browser results)

Our first step in the above list is to cycle over all the forms. We can use the document.forms collection to find all of the forms on the document. We’ll also create a variable to track our index in the collection of forms. Lastly, we’ll add a label to this loop so that we can break from it later:

// Get a reference to all forms, and an index variable
var forms = document.forms, fIndex = -1;

// Begin cycling over all forms in the document
formloop: while ( ++fIndex < forms.length ) {

}

Next, within our formloop, we need to get a collection of the current form’s elements. Additionally, we will be creating another index variable to help us navigate this new collection:

// Get a reference to all elements in form, and an index variable
var elements = forms[ fIndex ].elements, eIndex = -1;

// Begin cycling over all elements in collection
while ( ++eIndex < elements.length ) {

}

The third step in our process is to check for the autofocus attribute in each element. There are various ways you can do this, and I explored several of them. For instance, you could use the hasAttribute method, but this is only supported in Internet Explorer from version 8 (meaning you’d have to polyfill it in earlier versions).

In the end I wound up checking for the attribute as a key in the element.attributes collection. If not present, the result will be falsey, and the loop will skip to the next element in the nodeList:

// Check for the autofocus attribute
if ( elements[ eIndex ].attributes["autofocus"] ) {

}

Finally, we arrive at our last step. We have found an element that has the attribute we’re looking for, and it’s time to focus on it, break out of the loops, and call it quits.

// If found, trigger focus
elements[ eIndex ].focus();

// And break out of outer loop
break formloop;

This is where the formloop label comes in handy; a simple break would have broken the element loop, but not the forms loop, meaning subsequent form elements (and their children) would be evaluated. Since only one instance of autofocus should appear in a document, this is not the behavior we want.

The final result is wrapped in an IIFE (Immediately Invoking Function Expression) which runs our code immediately, as well as prevents our variables from appearing in the global namespace, potentially causing harm to the rest of the document or application.

(function () {

    // Proceed only if new inputs don't have the autofocus property
    if ( document.createElement("input").autofocus === undefined ) {

        // Get a reference to all forms, and an index variable
        var forms = document.forms, fIndex = -1;

        // Begin cycling over all forms in the document
        formloop: while ( ++fIndex < forms.length ) {

            // Reference all elements in form, and an index variable
            var elements = forms[ fIndex ].elements, eIndex = -1;

            // Begin cycling over all elements in collection
            while ( ++eIndex < elements.length ) {

                // Check for the autofocus attribute
                if ( elements[ eIndex ].attributes["autofocus"] ) {

                    // If found, trigger focus
                    elements[ eIndex ].focus();

                    // And break out of outer loop
                    break formloop;

                }

            }

        }

    }

}());

There you have it, a polyfill that gives autofocus behavior to browsers that don’t natively support it. By dropping this in to your website, you can now carry on your merry way using great features of HTML like this, without worrying what negative effect it might have on your Internet Explorer 6, 7, 8, or even 9 visitors.

IE10 Gotcha: Optgroup Indexes and the Required Attribute

I came across a rather interesting gotcha in Internet Explorer 10.0.9200.16519 this evening (via @dstorey, who showed me this question). Setting the required attribute on a select element that has various optgroup elements within may result in unexpected warnings upon form submission.


The above form will be “invalid” if the index of the selected option among its siblings matches the index of its parent optgroup among its siblings. So the first optgroup and the first option will trigger the unexpected results when the parent select has the required attribute.

This pattern is consistent with the second, third, and fourth optgroup elements. Selecting the second option in the second optgroup, or the third option in the third optgroup, will cause form submission to fail.

Workarounds

Update: As Claude pointed out in the comments below, adding a non-empty value attribute to the optgroup elements will resolve the issue.

I have found only one way around this, but it may not work in most situations. Adding the multiple attribute to the same select will prevent the confusing behavior, but at the cost of affecting the presentation and behavior of your element. The size attribute could remedy this to some degree, but is not favorable.