Switching to Em-Based Media Queries
In modern browsers there should be no difference between em-based and pixel-based media queries if the browser handles the zoom correctly.
I actually had trouble with em-based media queries in one project because in one of the media queries the base font size changed and then all of the other media queries got messed up. That may have just been a stupid mistake, but you get the idea. I'd go with pixels.See update below. While zoom does not have an effect on modern browsers, base font size still does.The biggest problem I see you could run into with the 62.5% technique and
rem
is if you run into browsers that don't understand it. If you're worried about that you could add a fallback for less-capable browsers, and setrem
for the modern ones.html { font-size: 62.5%; }
body { font-size: 14px; font-size: 1.4rem; }
h1 { font-size: 24px; font-size: 2.4rem; }If there's any difference in how fast browsers process
px
vsem
, it's not noticeable. Browsers calculate CSS really, really fast (much faster than JS). So it's probably not worth worrying about.
Measurement pros, cons, and uses
px
I have used px
for media queries in the past because they're so reliable and, like you say, they zoom just fine. Update: However, if a user changes their default style sheet, your media queries will be off.
- Independent of CSS cascade
- Mostly non-relative measurement (just depends on how the browser measures font pixels)
- Zoomable in all modern browsers
em
Ems are awesome for making flexible grids and measurements. For example, if a container width is specified in ems, I can proportionally resize the container and its contents in my media queries with one declaration.
- Responds to the CSS cascade
- Relative to the container font size
- Zoomable in all modern browsers
In this example, resizing the font also resizes its container proportionally.
h1.title {
font-size: 2em;
width: 20em;
background-color: #baff1e;
}
@media (min-width: 400px) {
h1 {
font-size: 2.5em
}
}
rem
I haven't actually used rem
much, but I can see why a lot of people like it. You've got the power of a relative unit, but you don't have to deal with the crazy stuff that can happen when you throw in the CSS cascade.
Sizing things based on the browser's base font size seems like the web-standards thing to do, because then you allow for browsers whose optimal base font size might not be 16px. In practice, though, it kind of works the other way. From what I've seen, browsers use 16px
as the base font size because that's what everyone expects, and set the actual size of that CSS measurement to look decent in the browser.
- Independent of CSS cascade
- Relative to base font size
- Zoomable in all modern browsers
A note on the 62.5% technique
This has been around for quite awhile, and right now I don't know any reason not to use it. There was a 2007 article on A List Apart where they did some tests and found that font sizes displayed more reliably across browsers when the base font was declared at 100%
and text was sized in em
. But I'd be surprised if any of the browser constraints listed there are really relevant anymore. I still have a hard time feeling good about setting my base font size to 10px
, but that's probably just personal preference.
Update
After doing some tests, I'm reversing my practice of using pixels for media queries. I'm now recommending em
:
Users do change their base font size. One thread on the Mozilla support network, "How can I increase the browser default font size?" has over 5,000 views. And a similar thread has over 15,000. Another study found a percentage of users (0.3%) who did have a default font size smaller or larger than 'medium'. How often users actually change it seems irrelevant (see a previous SO answer). If some people do, it's probably worth supporting them.
Ems are likely more future-proof. They will work for any device whose optimal default font size is not 16px (as well as those that are).
The thing that convinced me the most was to see it in action. Here's a codepen demo. Notice that the browser's zoom probably makes no difference (I tested in Chrome). But if you actually go into your browser's settings and change the default font size from "medium" to something else, the widths are way off. In my opinion, this is unacceptable.
Confusion about ems in media queries
In normal situations, 1em
is a relative unit, and in a font-size it's relative to the font-size of its parent element. medium
is an absolute unit. In different browsers it can be set to different pixel sizes, and is chosen to be comfortable to read on a device. A common value for medium is 16px, but other values could be chosen. For example, a user might configure their browser to use a different px value for medium so that they can read the text better.
In media queries, there is no parent element for 1em
to be relative to. So it takes the initial value of medium
.
So yes, the two sources are saying the same thing, the spec with just a little more precision.
The rem
unit plays no part in this. If you use rem
in your media query, it will also evaluate to medium
. i.e. It would not be affected by any font size assigned to the root element in your styling.
CSS Breakpoints and em unit
I asked this question not long after yours. I finally found the definitive answer from the html-gods buried deep in the Media Queries page.
Relative units in media queries are based on the initial value, which means that units are never based on results of declarations. For example, in HTML, the ‘em’ unit is relative to the initial value of ‘font-size’.
It doesn't matter what you set in your html, media queries will always be set on the browsers initial font-size attribute.
Using rems to specify breakpoints in media queries
You are correct that if the base font size is 16px, then
@media screen and (min-width: 30rem) {}
and
@media screen and (min-width: 480px) {}
will both give the same results.
If you zoom in with your browser they will also give the same result.
As you point out though, if a user resets their browser font size then the 2 media queries give different results.
There's a good pen on Codepen to illustrate this.
Note that in this pen, if you set your browser font size larger or smaller than 16px the green em based box is either smaller or larger than your viewport, so this wouldn't be ideal in responsive design.
So I think px vs rem in the media query depends partly on your personal preference and partly on the specifics of your design.
FWIW, one easy option for responsive design is to use px in the media query and rems (or ems) for the styling, e.g.
/* Document level adjustments */
html {
font-size: 17px;
}
@media (max-width: 900px) {
html { font-size: 15px; }
}
@media (max-width: 400px) {
html { font-size: 13px; }
}
/* Modules will scale with document */
.header {
font-size: 1.5rem;
}
.footer {
font-size: 0.75rem;
}
.sidebar {
font-size: 0.85rem;
}
/* Type will scale with modules */
h1 {
font-size: 3em;
}
h2 {
font-size: 2.5em;
}
h3 {
font-size: 2em;
}
source: https://css-tricks.com/rems-ems/
Issue with min and max media queries due to using ems?
I've built a few sites with both min and max width media queries, and for me they've been painfully difficult to maintain and didn't actually add any value.
I like to use min-width queries for mobile-first sites, because it makes sense to me to think about my design from my smallest screen width first and then slowly add or change features as the width increases. This has the added bonus of eliminating the "no man's land" issue. See example: (thanks @IMI for calculating the pixel widths)
When you build a site like this, you end up specifying everything that changes from the previous query in each subsequent query, but behavior is also much more predictable as your screen will either fall into one category or the other, and whichever one it falls in, you know exactly what properties are being applied.
html {
font-size: 62.5%;
}
body {
font-size: 16px;
font-size: 1.6rem;
color:black;
}
@media (min-width: 20em) { /* = 320px */
body {color:red;}
}
@media (min-width: 30em) { /* = 480px */
body {color:green;}
}
@media (min-width: 37.5em) { /* = 600px */
body {color:pink;}
}
@media (min-width: 48.125em) { /* = 770px */
body {color:cyan;}
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p> This is some random text.</p>
</body>
</html>
Related Topics
How to Convert Markdown + CSS -> PDF
CSS Media Queries, Pixel Density, Desktop and Mobile Devices
Dynamic Stylesheets Using Razor
CSS Transitions Between Absolute and Relative Positioning
Why Do I Have to Put Media Queries at the Bottom of the Stylesheet
Flexbox Misbehaving with Max-Height
Vertically Center in Viewport Using CSS
Prevent Children from Inheriting Rotate Transformation in CSS
Fieldset Does Not Support Display: Table/Table-Cell
Sass:Making Underscore File Names Actually Create CSS Files
Limit the Width of a Column to the Width of a Particular Grid Item
Make Outer Div Be Automatically the Same Height as Its Floating Content
Responsive Bootstrap Jumbotron Background Image
How to Apply Global Styles with CSS Modules in a React App
Remove Duplicate CSS Declarations Across Multiple Files