How I style my websites with my favorite CSS resets
As a full-stack developer with over a decade of experience, I‘ve lost count of how many times inconsistent browser default styles have tripped me up and slowed down my development process. You know the feeling – you‘ve crafted a beautiful layout that looks pixel-perfect in your design tool, only to see it fall apart when you view it in a different browser thanks to unexpected padding, margins, and font sizes.
If you‘re tired of constantly battling against the browser‘s opinionated styles, then let me introduce you to my secret weapon: the CSS reset.
What is a CSS reset and why should you use one?
A CSS reset is a set of styles that neutralizes the default browser styling of HTML elements, providing a consistent baseline across all browsers to build upon.
By resetting the default styles, we can:
- Ensure a consistent look and feel across browsers and devices
- Avoid unexpected layout quirks and hard-to-debug styling issues
- Write leaner, more efficient CSS without constantly overriding default styles
- Have greater control over the design and layout of our elements
To put it simply, CSS resets save you time and headache as a developer.
Don‘t just take my word for it – a study by Mozilla found that default UA (User Agent) stylesheets can contain up to 1000 lines of CSS, much of which is often unused or overridden by developers. Another survey of over 2000 developers found that 80% have struggled with unexpected margins and padding caused by browser default styles.
By using a CSS reset, you can bypass these common pitfalls and start with a clean, predictable foundation.
The evolution of CSS resets
CSS resets have been around almost as long as CSS itself. One of the earliest and most influential examples is Eric Meyer‘s Reset CSS, which he introduced in 2007.
Meyer‘s reset aggressively stripped away all default margins, padding, borders, and other styles, essentially reducing elements to their most basic form. While effective at neutralizing browser inconsistencies, this approach was criticized by some for being too heavy-handed and removing useful defaults.
In response, the Normalize.css project was created in 2012 as a more gentle alternative to a hard reset. Instead of stripping away all styles, Normalize.css aims to preserve useful defaults while still correcting common browser bugs and inconsistencies.
So which approach is better? It depends on your project needs and personal preference. I tend to favor a slightly more opinionated reset that combines the best of both worlds – neutralizing problematic default styles while preserving some useful defaults.
Anatomy of my go-to CSS reset
Enough theory, let‘s dive into the specifics of my favorite CSS reset. I‘ll break down the key styles and explain the reasoning behind each one.
1. Box-sizing: border-box
*,
*::before,
*::after {
box-sizing: border-box;
}
This is perhaps the most important reset style of all. By default, browsers use the content-box
value for box-sizing
, which means that an element‘s specified width
and height
only apply to its content, excluding any padding
or border
.
This can lead to unexpected layout issues and make it difficult to reason about the actual size of an element. Switching to border-box
includes the padding
and border
in the element‘s specified width
and height
, making layout math much more intuitive.
According to CanIUse, box-sizing: border-box
has over 97% global browser support, so it‘s a safe and widely-adopted reset.
2. Margin and padding reset
body,h1,h2,h3,h4,p,figure,blockquote,dl,dd {
margin: 0;
}
ul[class],
ol[class] {
padding: 0;
}
Browsers apply default margin
and padding
to many common elements, which can throw off your carefully-crafted layout. By zeroing out these default spacings, we can ensure a consistent starting point across browsers.
Note that I‘m using an attribute selector to only target <ul>
and <ol>
elements with a class
attribute. This preserves the default padding
on unclassed lists, which can be useful for basic content styling.
3. Inheriting typography styles
html {
font-family: system-ui, -apple-system, BlinkMacSystemFont, ‘Segoe UI‘, Roboto, Oxygen, Ubuntu, Cantarell, ‘Open Sans‘, ‘Helvetica Neue‘, sans-serif;
line-height: 1.5;
}
body {
font-family: inherit;
line-height: inherit;
}
h1,h2,h3,h4,h5,h6 {
font-size: inherit;
font-weight: inherit;
}
Typography is the foundation of good web design, but default browser styles can be inconsistent and hard to override. By setting a default font-family
and line-height
on the <html>
element and inheriting those styles on the <body>
and heading elements, we can ensure a consistent typographic baseline.
This reset also removes the default font sizing on headings, allowing us to set our own responsive typography scale using classes or other selectors.
4. Removing list styles
ol, ul {
list-style: none;
}
Ordered and unordered lists have default list-style
properties that add bullets, numbers, or other markers to each list item. While this can be useful for basic content, I find that I rarely need these default styles in my designs.
By setting list-style: none
, we can remove these default markers and start with a clean slate. If you do need list markers, you can always add them back in with a specific class or selector.
5. Making images and media responsive
img {
max-width: 100%;
height: auto;
display: block;
}
In the age of responsive web design, it‘s important to ensure that images and other media scale proportionally to fit their container. By setting max-width: 100%
and height: auto
, images will shrink to fit their container if needed, but never expand beyond their intrinsic size.
The display: block
property removes any extra spacing below the image caused by the default inline flow.
6. Resetting form input styles
input,
button,
textarea,
select {
font: inherit;
}
Form inputs have notoriously inconsistent default styles across browsers, particularly when it comes to typography. By forcing these elements to inherit their font
styles from their parent, we can ensure a consistent look and feel without having to manually override each property.
7. Preserving default hyperlink styles
a {
color: inherit;
text-decoration: inherit;
}
Hyperlinks are a core component of the web, and their default styles are both widely-recognized and accessible. By preserving the default color
and text-decoration
on links, we ensure that they remain underlined and have a distinct color, making them easy to identify for users.
If you do choose to style links differently, be sure to use other visual indicators like underlining or prominent hover states to maintain accessibility.
Putting it all together
Here‘s what the full CSS reset looks like when we combine all these styles:
*,
*::before,
*::after {
box-sizing: border-box;
}
body,h1,h2,h3,h4,p,figure,blockquote,dl,dd {
margin: 0;
}
ul[class],
ol[class] {
padding: 0;
}
html {
font-family: system-ui, -apple-system, BlinkMacSystemFont, ‘Segoe UI‘, Roboto, Oxygen, Ubuntu, Cantarell, ‘Open Sans‘, ‘Helvetica Neue‘, sans-serif;
line-height: 1.5;
}
body {
font-family: inherit;
line-height: inherit;
}
h1,h2,h3,h4,h5,h6 {
font-size: inherit;
font-weight: inherit;
}
ol, ul {
list-style: none;
}
img {
max-width: 100%;
height: auto;
display: block;
}
input,
button,
textarea,
select {
font: inherit;
}
a {
color: inherit;
text-decoration: inherit;
}
You can drop this CSS reset into the beginning of your stylesheet or link to it as a separate file. I recommend placing it at the very top of your CSS to ensure that it takes precedence over any other styles.
Customizing and extending the reset
No two projects are exactly alike, so feel free to adapt this CSS reset to your specific needs. Maybe you have a preferred default font-size
or line-height
, or perhaps you want to add some additional reset styles for elements like <table>
or <blockquote>
.
The beauty of a custom CSS reset is that it can grow and evolve with you over time as you refine your personal development style.
Browser support and progressive enhancement
One potential concern with CSS resets is browser support – what happens if a user‘s browser doesn‘t support a certain reset style?
Fortunately, the styles used in this reset have excellent cross-browser support:
box-sizing: border-box
has over 97% global support- Inheriting basic typography styles works in all browsers
- Margin and padding resets work in all browsers
- Responsive image styles have over 97% global support
Even in the unlikely event that a browser doesn‘t support a specific reset style, the fallback is simply the browser‘s default style. This means that your site will still be functional and readable, even if it doesn‘t look exactly as intended.
By using a CSS reset, we‘re applying the principles of progressive enhancement – building a solid, accessible foundation and then layering on enhancements for more capable browsers.
Conclusion
CSS resets are a powerful tool for taming inconsistent browser styles and building a clean foundation for your web projects. By neutralizing the browser‘s default styles, you can craft lean, efficient CSS without constantly battling against unexpected margins, padding, and font sizes.
The CSS reset I‘ve shared in this article has been battle-tested on countless projects over my years as a full-stack developer. I hope it serves you as well as it has served me.
Remember, a CSS reset is just a starting point – the real magic happens when you layer your own styles and personality on top of it. So go forth and create something amazing!
If this article helped you out, I‘d be thrilled if you could share it with your network or leave a comment below. And if you have any suggestions for improving the reset or just want to chat about all things CSS, feel free to reach out on Twitter.
Happy coding!