The Ins and Outs of CSS Resets
Dave Ward | September 29th, 2010
We’ve all felt that sinking feeling – the one that comes after discovering cross-browser layout problems on a page that appeared to be finished in our development browser of choice. Even a single block-level element rendered just a few pixels too large can easily cause a cascade of layout issues that eventually prove too significant to ignore. The end result is that relatively small cross-browser inconsistencies may result in a serious, seemingly nondeterministic impact on how a given page looks in various browsers.
Sometimes these variances are symptoms of well-publicized CSS incompatibilities, such as those highlighted by the Web Standards Project’s Acid tests. Especially when using CSS3, these significant differences in implementation cause rendering to vary across even standards-compliant browsers.
However, there’s also an entirely separate class of cross-browser layout issues, stemming from a more fundamental inconsistency in the way that various browsers render HTML. In this article, I’ll explain what those issues are, illustrate how they impact your pages, and show you a variety of approaches to solve the problem.
Rendering Defaults – Starting on uneven ground
The World Wide Web Consortium (W3C) – a group that recommends how browser vendors should implement web standards such as HTML and CSS – provides detailed guidance about the syntactical and semantic properties of HTML. However, HTML standards do not specify a default presentation for that markup. Troublesome as it is, that ambiguity is natural: The markup standard is specifically compartmentalized to avoid mixing guidance on content and presentation. The markup in an HTML document should be little more than semantic metadata that describes its content.
Ultimately, that lack of authoritative guidance on styling means that no two standards-compliant browsers are guaranteed to present a given page identically. In fact, most browsers on the market do vary at least slightly in their default styling of some elements.
An example
The <h1> element — known as the “level one heading” — is a good example of this inconsistent default behavior. The <h1> element renders with a default font size of 24pt in IE7, 2em in IE8, and 32px in most other browsers. The top and bottom margins render even less consistently: They default to 14.25pt in IE7, 0.67em in IE8, and about 21px in most other browsers.
For example, consider this HTML markup:
<h1>This is an H1</h1>
Even that very simple markup renders differently enough in IE and Firefox – likely the two browsers most frequently used to view your pages – that the difference is visually obvious:
Another example
The <p> element – known as the paragraph element – is troublesome in the same way as the heading elements. Its top and bottom margins vary across browsers in both size and unit of measure. As one of the most common elements on most pages, even the smallest variance quickly compounds into a layout-altering issue.
Consider this simple example, combining a paragraph element and the inline quote element:
<p>This is a paragraph, including <q>a quote.</q></p>
It’s enlightening how different such simple markup looks in the latest versions of Internet Explorer, Firefox, and Safari:
Just when the similar rendering in Firefox and Safari seem like a silver lining, notice how they both rendered the quotation marks around the <q> differently. Introducing even more inconsistency, Internet Explorer renders no quotation marks whatsoever – which is ironically the only of these browsers that matches the W3C’s CSS 2.1 styling suggestion.
More common than you might think
It’s important to understand that these examples aren’t contrived using an old browser like IE6. These screenshots depict rendering in the latest versions of the most popular browsers in use today. Unless you have complete control over your users’ browser choice, it is certain that your pages are being viewed with these inconsistent baseline rendering styles.
What’s worse, the variance shown in these two examples is not the exception. Many block-level elements suffer from the top and bottom margin issues seen above. Even the <fieldset> element’s border renders in a variety of styles and border sizes across browsers.
When developers are new to CSS-based layout, we often lament that CSS is “flimsy”, “fragile”, or “unpredictable.” As it turns out, combinations of these seemingly trivial layout variances are often responsible a large portion of that perception. By understanding the underlying issues and taking simple steps to mitigate them, you can take back control of your CSS layouts. Without consciously taking steps to create a stable foundation, it’s exceptionally difficult to build a site that looks consistent in every browser.
A solution
Even though browsers do start with inconsistent defaults, it’s possible to override them. In the hierarchy of CSS specificity, the browser’s default stylesheet is at the very bottom. Any inline or externally defined styles will override browser defaults.
With the ability to override those default styles, you’re able to explicitly define a new set of your own default rendering styles. Instead of allowing each browser to decide how much space should be above and below block level elements, for example, you have the opportunity to preemptively dictate styling that renders identically across all browsers.
In other words, there’s nothing preventing you from resetting all of the default styling for HTML elements to a predictable baseline style. In fact, doing so will almost entirely negate the cross-browser variances in default styling.
This technique is called a CSS reset.
How?
By now, you’re probably sold on the idea of using a CSS reset, and just want to know how to do that. While most agree that CSS resets are a great idea, there are a variety of opinions regarding which elements should be reset and how to reset some of the more tricky edge cases.
As you’ve seen in the previous examples, the <q> element automatically adds quotation marks around its content in some browsers, but doesn’t in others. Even in the browsers that do add quotes by default, the type of quote character varies between them. That type of inconsistent behavior is certainly part of what a good CSS reset should normalize, but isn’t as obvious as padding and margins on block-level elements.
The following are a few of the most popular approaches:
Manual Resets
Perhaps the most intuitive solution is to skip the reset altogether and explicitly specify values such as margins and padding. You’re probably already doing this in the course of coding your site, so why bother with the preliminary reset in addition?
In fact, the syntax for CSS shorthand helps guide you toward the “pit of success” in this case. For example, even if you only wanted to specify a left and/or right margin on a paragraph element:
/* Doesn’t reset the varying top/bottom margin, but is more verbose anyway */
p { margin-left: 5px; margin-right: 5px; }
/* More common usage; takes care of the reset issue as a by-product.
p { margin: 10px 5px; }
While this is great for those elements that you do explicitly style, it lacks the comprehensive coverage that the global selector achieved. The later example does properly reset the paragraph across all browsers, where the former leaves a cross-browser inconsistency intact.
However, relying solely on this approach has drawbacks.
- Specificity – A manual reset only replaces a true reset if you define styles with HTML element selectors. Resetting a paragraph element’s top and bottom margins with common selectors such as .bodyParagraph, #body, or even p.body will successfully mitigate the cross-browser variances on those specific elements, but will leave those inconsistencies intact on paragraph elements as a whole. It’s easy to forget to reset the underlying elements, allowing the browser’s default stylesheet to affect other areas of your pages.
- Dynamic Markup – With server-generated HTML and client-side DHTML plugins abstracting so much of the markup in our pages these days, it’s understandable that you may not even be aware of every type of element that occurs on them. For example, you might be using a third-party control or plugin that generates a navigation menu, not knowing whether the actual markup is a <table>, <ul>, block-level <a> elements, or something else. When you don’t put markup on the page yourself, it’s harder to remember that elements in auto-generated markup need to be reset as well.
Appendix D
Though the W3C’s HTML specification does not require compliant browsers to render elements in a specific or uniform style, Appendix D, an appendix to the CSS 2.1 spec, does suggest a set of default styling for use with HTML 4 documents. In fact, most modern browser defaults are somewhat similar to this set of suggestions, but unfortunately not normatively (as seen in the earlier screenshots).
As with the manual approach, this can’t truly be considered a CSS reset. Even so, Appendix D does address the same problem that a reset does. You could almost consider it the earliest CSS framework.
Further, since the Appendix D stylesheet sets defaults for the majority of HTML elements, it mitigates the issue of dynamically-generated content using elements that you hadn’t explicitly considered styling.
However, it doesn’t cover several of the edge cases that more mature resets do. Each browser’s individual defaults will continue to be applied to any element/property combination that the explicit rules in Appendix D don’t restyle. The issue of inconsistent quotation marks surrounding a <q> element’s content is an example of a problem not addressed by Appendix D.
The Global Reset
Instead of mixing the reset styles with your desired styling, a better approach is to separate the reset out to a reusable section of CSS code. By including that block of CSS ahead of your usual styling, you insure that you’re starting with an even foundation.
Perhaps the earliest attempt at that sort of generalized CSS reset was simply this:
* { margin: 0; padding: 0; }
Leveraging the “*” selector – known as the global or universal selector – this line of CSS will reset every single HTML element’s padding and margins to zero.
Unfortunately, the global reset has several drawbacks:
- Edge Cases – Though margins and paddings typically have the greatest impact on a page’s layout, there are more properties that need to be reset in order to achieve a consistent foundation. Default font sizes, weights, styles, text alignment, borders, and even list item styling also vary between browsers, not to mention the inconsistent quotation marks around the <q> element that we saw earlier.
- Collateral Damage – Even though it only targets margins and paddings, using the global reset wreaks havoc on form styling. Even though it’s inconsistent, this is one area in which it’s generally better to present the user with a familiar UI. Once the global reset has been applied, it is all but impossible to regain that custom form styling.
- Performance – The global selector has negative performance implications in almost every scenario, whether a CSS reset or routine CSS styling. This usage is no exception.
The global reset should be credited for opening a discussion on the issue and for being the first step toward developing the more comprehensive CSS resets we now have. However, its negative consequences outweigh any benefits that its concise syntax might appear to confer. It should be avoided in favor of the more mature CSS resets that have been developed in recent years.
YUI Reset
To mitigate the global reset’s negative consequences, while still achieving reusability, a newer generation of CSS resets has emerged. Of those, the YUI Reset is one of the earliest.
Long before their YSlow fame, the Yahoo! Developer Network team researched, developed, and released one of the first general, reusable CSS resets: YUI Reset. The first iteration of YUI Reset was released as part of the Yahoo! User Interface Library in early 2006.
Since that initial release, the YUI Reset has continued to be refined and improved. In late 2009, it was re-released as part of YUI 3.
Of the approaches we’ve looked at so far, YUI’s reset is the first that could truly be considered a CSS reset by current standards. Notable improvements over methods reset and Appendix D include:
- Margins and paddings – YUI Reset explicitly sets the margins and paddings on block-level elements to 0. Everything from mundane elements like <div> and <ul> to less common elements such as <pre> and <legend> are reset. In total, over 25 individual block-level elements have their margins and paddings reset.
- Fonts – Font styles and weights on appropriate element types are reset to normal. This avoids inconsistent bolding, italicizing, underlining, or strikethrough formatting across browsers. Similarly, font sizes are reset to 100%. Coupled with a typography framework, this brings type-rendering as nearly similar as possible with CSS 2.1 alone.
- Lists – The <li> element’s list-style is reset to none. Coupled with <ol>, <ul> and <li> being included in the margin and padding reset, this gives lists a consistent default rendering across browsers.
- Quotes – YUI Reset also normalizes the beginning and ending quotes that some browsers wrap around the <q> element. It resets them completely, which matches the W3C’s suggestion in Appendix D.
- Fieldsets – The <fieldset> element is a bit of an oddity. It behaves as a block-level element, not all that different than a <div>, yet browsers apply uniquely customized styling to its border (even to the extent of rounded corners). YUI Reset mitigates that issue by resetting its border completely.
The YUI Reset is one of – if not the – first comprehensive CSS resets designed with reuse in mind. In fact, Yahoo! even hosts it on their public CDN for reference on your own pages if you wish.
This approach may seem tedious at first, but establishing a consistent foundation across all browsers is worth the effort. Coupled with a CSS typography and/or layout framework, a full reset like YUI Reset will save you countless hours over the long term.
You can find the YUI 3 CSS Reset here: https://developer.yahoo.com/yui/3/cssreset/
Eric Meyer’s reset
Shortly after Yahoo! published their YUI 2 Reset, a web developer named Eric Meyer took Yahoo!’s work and refined it even further. Over the course of a year and several iterations, Eric arrived at what is one of the most ubiquitous CSS resets currently in use.
The latest revision hasn’t been updated in a couple years, but it still works great. Its refinements over YUI 2 Reset include:
- Quotes – Eric’s reset handles the <q> issue more cleanly than YUI Reset. Rather than setting the “before” and “after” styles to an empty string, it uses the cleaner “quotes: none” approach.
- Ins – He chose to reset the <ins> element’s text-decoration style. Most browsers default to styling <ins> elements with an underline, which should be reserved for links for usability.
- Caption and th – Some browsers apply different combinations of centering and/or bolding to the text in <caption> and <th> elements. Eric’s latest reset makes the conscious choice of resetting those elements to be left aligned and to have a normal font weight.
You can find Eric’s reset on his site: https://meyerweb.com/eric/tools/css/reset/
HTML5 reset
One notable omission in these popular CSS resets is support for HTML5. HTML5 includes several new elements, such as <header>, <time>, and <video>. Those new elements are structurally similar to <div>s and <span>s, but a CSS reset targeting only the <div> and <span> elements won’t automatically apply to the new HTML5 elements.
Time will tell if browsers also diverge in their default styling for HTML5 elements, but it’s a good idea to preempt potential problems by including the new elements in your CSS reset.
An HTML5 reset – aptly named reset5 – that extends Eric Myers’ CSS reset has already been developed to address those concerns. It is available here: https://code.google.com/p/reset5/.
Conclusion
A lot of attention has been given to JavaScript frameworks recently, due in no small part to their knack for smoothing out the myriad inconsistencies in DOM implementations between browsers. Knowing that a single bit of client-side functionality won’t require several browser-specific workarounds removes friction from the development process and encourages you to attempt more ambitious features.
I think that CSS resets - and CSS frameworks in general - are the underappreciated presentational counterpart of these JavaScript frameworks. Mitigating the fundamental inconsistencies in how browsers render elements by default has the same liberating effect on your development process, knowing that you can rely on elements to be positioned and spaced how you declare they should be.
Next Steps
Keep in mind that a reset is just a starting point. Resetting every element to have no margin, padding, border, or font styling by default means that you must subsequently re-style all of them yourself. Though this additional work may seem tedious, it is well worth a bit of extra effort in order to ensure a consistent, stable presentation.
A variety of CSS frameworks have been created to help to accelerate that process of reestablishing basic styling and typography for common elements. Among them, these are some of the most popular:
About the Author
Dave Ward is an independent ASP.NET consultant in Atlanta, Georgia, specializing in creating functional, interactive web applications with HTML, CSS, and JavaScript. With over fifteen years’ experience developing websites, he has been recognized as a Microsoft ASP.NET MVP and a member of the ASP Insiders. He is co-author of the upcoming book ASP.NET AJAX in Action, Second Edition (Manning Publications, 2010).
Find Dave on:
- Twitter: @Encosia
- At work - Encosia