To make HTML5 work in old versions of Internet Explorer (IE8 and earlier), you need to use a JavaScript shim that creates the new HTML5 elements in the DOM, and you also need to handle missing features like localStorage, querySelector, and CSS3 media queries. The most common solution is the HTML5 Shiv (also called html5shiv) combined with a polyfill library like Modernizr or Respond.js for responsive design. This article explains exactly what breaks, why it breaks, and the step-by-step fixes that work in practice.
Why Old IE Fails at HTML5
Internet Explorer 8 and earlier were built before the HTML5 specification was finalized. They don’t recognize new semantic elements like <header>, <nav>, <article>, <section>, <aside>, <footer>, and <figure>. When IE encounters an unknown element, it treats it as an inline element and, more critically, it doesn’t insert it into the DOM tree. This means you can’t style it with CSS, and JavaScript can’t access it normally. The fix is to force IE to create these elements using a small script.
The other major issue is missing JavaScript APIs. IE8 lacks Array.prototype.forEach, Object.keys, JSON.parse (though it has JSON.stringify), and the querySelectorAll method. It also doesn’t support localStorage (IE8 has userData instead), addEventListener (uses attachEvent), and CSS3 features like media queries, rgba() colors, and border-radius (though border-radius can be faked with CSS3Pie).
The HTML5 Shiv: What It Does and How It Works
The HTML5 Shiv is a tiny JavaScript snippet created by Sjoerd Visscher and popularized by Remy Sharp. It exploits a quirk in IE: if you create an element via document.createElement('header'), IE will then recognize it and allow CSS styling. The shiv loops through a list of HTML5 element names and creates them all. You include it in the <head> of your page, before any CSS that styles those elements.
Here’s the classic implementation:
<!--[if lt IE 9]> <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script> <![endif]-->
The conditional comment ensures only IE8 and below load the script. Modern browsers ignore it. The shiv also sets article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section { display: block; } in its internal stylesheet, so you don’t have to add that manually.
If you’re using the shiv, you must also add a CSS rule to make these elements display: block for browsers that don’t get the shiv (like older Firefox or Safari). The shiv does this automatically, but if you’re writing your own, add something like:
header, nav, article, section, aside, footer, figure, figcaption, main { display: block; }
Polyfills for Missing APIs and Features
The shiv only fixes element recognition. For missing JavaScript methods and CSS features, you need polyfills. A polyfill is a piece of code that implements a feature in browsers that lack it. Here are the essential ones for IE8:
- Modernizr – A feature-detection library that adds classes to the
<html>element (e.g.,no-flexbox) and lets you conditionally load polyfills. It doesn’t fix anything by itself, but it’s the standard way to manage polyfills. - Respond.js – Adds support for
min-widthandmax-widthmedia queries in IE6-8. It parses your CSS and applies the appropriate rules via JavaScript. - json2.js – Adds
JSON.parseandJSON.stringifyfor IE7 and below (IE8 has native JSON). - es5-shim – Adds ECMAScript 5 methods like
Array.isArray,Array.prototype.map,Function.prototype.bind, andObject.create. - CSS3Pie – Adds
border-radius,box-shadow, and linear gradients to IE6-9 using a HTC behavior file.
For localStorage, you can use a polyfill like storagepolyfill that falls back to IE’s userData behavior. However, a simpler approach is to use a library like Store.js which wraps localStorage and provides a fallback.
How to Choose What to Include
You don’t need every polyfill. The decision depends on your target audience and the features your site uses. Here’s a practical checklist:
- Do you use HTML5 semantic elements? If yes, include the html5shiv.
- Do you use responsive design with media queries? If yes, include Respond.js.
- Do you use
querySelector/querySelectorAll? If yes, include a polyfill likequerySelectorAllfrom thehtml5shivpackage or use a library like jQuery which handles it internally. - Do you use CSS3 properties like
border-radiusorbox-shadow? If yes, consider CSS3Pie, but note it can be slow on complex pages. - Do you use
localStorage? If yes, use a wrapper library or a polyfill. - Do you use modern JavaScript array methods? If yes, include es5-shim.
If you’re using a framework like jQuery, many of these issues are already handled. jQuery 1.x (up to 1.12) supported IE6-8. jQuery 2.x dropped IE6-8 support. So if you need old IE, stick with jQuery 1.12 or use a custom build.
Common Problems and Pitfalls
Even with the shiv, you’ll encounter issues. Here are the most frequent ones:
- Shiv not loading due to conditional comment syntax errors – Make sure you use the exact syntax
<!--[if lt IE 9]> ... <![endif]-->. A common mistake is using<![if IE]>which is not a valid conditional comment. - Elements not styled because the shiv loads after CSS – The shiv must be in the
<head>before your CSS. If you load it at the bottom of the page, IE won’t recognize the elements when it parses the CSS. - Respond.js not working with @import or external CSS – Respond.js only works with linked stylesheets, not with
@importrules. Also, it must be loaded after your CSS. - IE8 doesn’t support
addEventListener– If you’re writing vanilla JS, useattachEventor use a library that abstracts it. - IE8 has a 32KB CSS selector limit per stylesheet – This is a known IE8 limitation. If your CSS is huge, split it into multiple files.
- IE8 doesn’t support
max-widthon images in some contexts – Usewidth: 100%in a container instead.
Comparisons: HTML5 Shiv vs. Modernizr vs. Conditional Comments
These tools are often confused. Here’s a clear comparison:
- HTML5 Shiv – Only fixes the element recognition issue. It’s a single-purpose script, tiny, and fast.
- Modernizr – A feature-detection library that doesn’t fix anything by itself. It adds classes to the
<html>element so you can write CSS fallbacks. It can also load polyfills on demand usingModernizr.load(). - Conditional Comments – Not a library, but a syntax in IE that lets you include or exclude HTML/scripts based on IE version. You use them to load the shiv only for old IE.
In practice, you’ll use all three together: conditional comments to load the shiv and Respond.js, and Modernizr to detect features and apply fallback CSS. For example, if you use flexbox, Modernizr adds a no-flexbox class to <html>, and you can write .no-flexbox .container { display: table; } to provide a fallback.
Cost and Performance Considerations
Adding polyfills has a cost. The html5shiv is about 1.5KB minified, Respond.js is about 4KB, and es5-shim is about 16KB. That’s not huge, but every script adds HTTP requests and parse time. On old hardware running IE8, performance can be a real concern. To minimize impact:
- Load polyfills only for IE8 using conditional comments.
- Combine and minify your scripts.
- Defer loading of non-critical polyfills (like es5-shim) until after the page renders.
- Consider using a CDN like cdnjs or Google Hosted Libraries, which are often cached across sites.
Also, note that Microsoft itself has discontinued support for IE8 (end of support was January 2016). If you’re building a new site, you should not spend too much effort on IE8. But if you have a legacy site or a client that still uses it, these techniques are necessary.
Alternatives to Polyfills
Sometimes you don’t need to make HTML5 work in old IE. Here are alternatives:
- Graceful degradation – Design your site so that it works without the HTML5 features. For example, use a
<div>instead of<header>and add ARIA roles for semantics. - Use a framework that abstracts the differences – jQuery (1.x) handles most DOM and event differences. Bootstrap 3 supported IE8 with the shiv and Respond.js. Bootstrap 4 dropped IE8.
- Use a transpiler like Babel for JavaScript – Babel can compile ES6 code to ES5, but it won’t add missing APIs. You still need polyfills for things like
Promise. - Use a service like BrowserStack for testing – Not a fix, but essential to verify your site actually works in IE8.
Frequently Asked Questions
Does the HTML5 Shiv work in IE9 and IE10?
No, IE9 and later natively support HTML5 elements. The conditional comment <!--[if lt IE 9]> ensures the shiv only loads for IE8 and below. IE9 also supports most of HTML5, but it still lacks some CSS3 features like flexbox (it has an old syntax) and transition (it has a prefixed version).
Can I use HTML5 tags without the shiv if I just style them with CSS?
No. Without the shiv, IE8 will not insert the elements into the DOM, so CSS selectors like header { } won’t match anything. The shiv is required to make the elements exist.
How do I know if my site needs Respond.js?
If you use CSS media queries (like @media (max-width: 768px)) and you want your layout to respond to viewport width in IE8, you need Respond.js. Without it, IE8 ignores the media queries and applies the default (usually desktop) styles.
What is the difference between a shim and a polyfill?
A shim is a piece of code that intercepts API calls and provides a fallback (often for missing features). A polyfill is a specific type of shim that replicates a standard API. In practice, the terms are used interchangeably. The HTML5 Shiv is a shim because it creates elements, not an API.
Is it worth supporting IE8 in 2024?
Generally, no. IE8 usage is negligible (well under 1% globally). However, some enterprise environments, government agencies, and older POS systems may still use it. If your analytics show IE8 traffic, you might want to provide a basic experience. Otherwise, it’s better to spend time on modern browsers.
Can I use Modernizr without the HTML5 Shiv?
Yes, Modernizr can be used independently for feature detection. However, if you want to use HTML5 elements, you still need the shiv. Modernizr can include the html5shiv as part of its build if you select that option.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Valheim Server Not Showing in Community List Fixes
- DisplayPort vs HDMI: Which Cable Should You Use?
- Soundbar vs 2.1 Speaker System: Which Is Better?
- Mouse Moving on Its Own? Causes & Fixes
- Slack Channels for Construction Projects: Setup Guide
- Surface Won’t Turn On: Quick Fixes1.8 h