Support em units in media queries. #18

Closed
scottjehl opened this Issue Apr 28, 2011 · 23 comments

Comments

Projects
None yet
8 participants
Owner

scottjehl commented Apr 28, 2011

Respond.js should translate em-based Media Queries such as the following:

@media screen and (min-width: 375em){ ... }

Idea from @jonikorpi via Twitter: https://twitter.com/jonikorpi/status/63614290787184641

In order to support, I'll need to add an em conversion function, such as:
https://gist.github.com/946707

Simpler implementation ideas welcome!

Collaborator

beep commented Apr 28, 2011

I haven’t personally found a use for em-based media queries, so I don’t have any strong opinions to share. Go nuts!

pyrsmk commented Apr 29, 2011

According to beep, I don't find any reason to use em-based media queries. Could you give us a quick example of such a thing?

My reason is properly supporting page-zoom. If the layout is set in ems and the media queries are in pixels, you easily end up with overly wide mobile layouts and overly narrow desktop layouts when zooming.

A couple of quick examples from @beep's site (sorry!):
Mobile layout zoomed out: http://dl.dropbox.com/u/1231109/Screen%20shot%202011-04-29%20at%2012.06.10%20.PNG
Desktop layout zoomed in: http://dl.dropbox.com/u/1231109/Screen%20shot%202011-04-29%20at%2012.06.26%20.PNG

If the media queries were in ems instead, the zoomed in example would've used the mobile layout, and the zoomed out example would've used the desktop layout. The behaviour would be kinda similar to elastic layouts.

pyrsmk commented Apr 29, 2011

Very interesting, I hadn't saw this behavior... So I join the idea :D

As I'm not a senior js developer or something, I'm not sure at all but does your function support em-based font-size in body?

Owner

scottjehl commented Apr 29, 2011

@jonikorpi: In order to implement this, I'll need to know which element's font-size to calculate the value of 1em from. I assumed it was body, but from what I can tell, changing the body's font-size has no effect on the em values in the queries. Same for the HTML element.

The spec says it's relative to the "root" element, which I guess means html / documentElement. However, it seems dependent on the browser's default font-size of the body (independent of your stylesheets). Usually that's 16px, but I'm not sure that's always a safe assumption to bake in..?

Any insight on this would be great, thanks!

I've actually been pretty confused about that myself. It seems at least Safari seems to just use the browser's default font-size, like you said. Changing 's font-size had no effect on the queries.

I'm not really sure if there's any sort of a safe assumption to make here. Some people do change their browser's default font-size, and I think the system-wide "make fonts bigger" -option in Windows changes it too. However, if there's no way to detect what the default font-size actually is, 16px is always the least unsafe choice. :)

Owner

scottjehl commented Apr 29, 2011

hmm k. I'd really like to be able to detect the size before translating it.

So if you're making layouts with a default font-size of say, 62.5%, do you still write your em queries based on a font-size of 16px?

The 62.5% value made sense on the desktop as we were trying to approximate physical print sizes on screens that somewhat varied in size but were by and large consistent at 72 dpi. Because of the much larger variance in dpi, big differences in physical size, and differences in browser implementation on mobile, if you are trying to make a responsive site, I don't think using this value to gauge a font baseline is relevant any more..(...unless you only use it for the largest and presumed desktop layout but then use a different set of values altogether for the presumed mobile layouts...and I say presumed because of certain tablets or larger mobiles whose landscape dimensions are similar to the size of a PC so end up matching to a 'desktop' media query).

I will definitely have to check out the issue Jonni Korpi demonstrated. I haven't run into it yet either but then I also haven't played with em based media queries. :-P

pyrsmk commented Apr 29, 2011

I've just made some tests and:

  • chromium 11, since it's webkit based, matches media queries as safari does (with an internal value of 16px)
  • firefox 4 just matches with the user preferences
  • opera 11.10 does the work with the user preferences and the body's font-size
Owner

scottjehl commented Apr 29, 2011

Hey great research, thanks!

Given the variance, and the fact that IE 9 and 10 may handle it differently as well, I think the only way to reliably support this would be to set HTML and Body to 100% fontsize, append a 1em fontsize element, test its font size, then undo all that.

I'm not thrilled with this idea. If I used it at all, I'd only want to do it once, before the body was present, and assume it won't change after that.

Still, feels intrusive...

@stephrieger: I tend to use 62.5% for simplifying the math when translating font sizes from design to dev. At least so far, that's continued to work well across many devices for me, but the fact that media queries are sometimes (but not always) affected by that font-size shift REALLY complicates things. If em-based media queries are actually beneficial, maybe scrapping 62.5 is the only reliable way to build (like you said :) )...

pyrsmk commented Apr 29, 2011

@scottjehl: Sounds as a great idea, but we'll must add the script at the top of the page to get the body not loaded yet, no?

Owner

scottjehl commented Apr 29, 2011

yeah. I'd recommend doing that with respond.js anyway though (or load it synchronously with JS). Otherwise you'll get flash of un media'd content in IE...

jayf commented Sep 25, 2011

I just got snagged on this issue, using Respond with @jonikorpi's Golden Grid System (GGS), which uses ems in the media queries.

So, funny thing that's maybe a useful hack, though it's what messed me up: It was only my minified CSS that was breaking in IE. The source CSS was working as if Respond were recognizing the em widths in the media queries.

The reason, I finally figured out, is this convention in the GGS stylesheet:

/* @media screen and (min-width: 1680px) */
@media screen and (min-width: 105em) {

In the minified CSS, the comment is stripped out. In the source CSS, that comment is of course there--and parsed by Respond as if it were uncommented CSS.

So, in a very weird way, one could therein use ems for modern browsers and pixels equivalents in IE with Respond. Not the kind of thing I'd want to maintain in my CSS, but an option right now, nonetheless.


Suggestion: if there isn't a super great way for Respond, by itself, to figure out how to calculate 1em, then let us set this via the API. A simple call might be:

respond.emInPixels = 16;

jayf commented Sep 26, 2011

I forked and added simple support for ems in the media queries, and submitted a pull request. I just used a hardcoded conversion value of 1em = 16px. I did not implement an effective way to change this via the Respond API.

So, I was thinking that, rather than Respond tracking the user's font size, perhaps this should be external code. One might need to track the font size on page load, but also if the user "zooms" at any point after load. I don't know if there's already a good library that tracks user zooming, but this doesn't seem to be anything handy one could just slot into Respond.

But if there were an external way to track user zooming, I think it could make sense to allow developers to set a new pixelToEm value in Respond, and re-translate the CSS. This would be a bigger bunch of work though.

Owner

scottjehl commented Sep 26, 2011

Hi Jay. Thanks - this sounds really great!

By chance, did you test the em-support branch to see how it holds up / compares? It has a rough attempt at getting the font size of 1em based on the HTML element's font size.

Anyway, this looks great - I'll take a look this week.
Thanks again

On Sep 25, 2011, at 11:10 PM, Jay Fienberg wrote:

I forked and added simple support for ems in the media queries, and submitted a pull request. I just used a hardcoded conversion value of 1em = 16px. I did not implement an effective way to change this via the Respond API.

So, I was thinking that, rather than Respond tracking the user's font size, perhaps this should be external code. One might need to track the font size on page load, but also if the user "zooms" at any point after load. I don't know if there's already a good library that tracks user zooming, but this doesn't seem to be anything handy one could just slot into Respond.

But if there were an external way to track user zooming, I think it could make sense to allow developers to set a new pixelToEm value in Respond, and re-translate the CSS. This would be a bigger bunch of work though.

Reply to this email directly or view it on GitHub:
#18 (comment)

jayf commented Sep 26, 2011

slaps forehead! Ah, I hadn't see the em-branch.

But, I'm testing it now--it's not working for me, but I'll see if I can add to it.

At the very least, I'll add support for decimals (e.g., 61.5em) to the em-branch, and do another pull request. But, I'll also see if I can get the eminpx calculation to work (better).

Thanks too, Scott, for creating Respond--I don't think I'd use responsive layouts with out it (at least for another couple years until even IE 8 is history).

Owner

scottjehl commented Sep 26, 2011

Thanks so much, Jay! I'll be anxiously awaiting your changes. :)

On Sep 26, 2011, at 3:23 PM, Jay Fienberg wrote:

slaps forehead! Ah, I hadn't see the em-branch.

But, I'm testing it now--it's not working for me, but I'll see if I can add to it.

At the very least, I'll add support for decimals (e.g., 61.5em) to the em-branch, and do another pull request. But, I'll also see if I can get the eminpx calculation to work (better).

Thanks too, Scott, for creating Respond--I don't think I'd use responsive layouts with out it (at least for another couple years until even IE 8 is history).

Reply to this email directly or view it on GitHub:
#18 (comment)

jayf commented Sep 26, 2011

Please see this new pull request of changes to the em-support branch. Adds: support for decimals in media query dimensions, and fixes some issues with grabbing the base font size in IE and converting it from points into pixels.

So, while working on this, as I had to deal with units in points, I was wondering about other valid CSS units of measure that might get used in media queries. There are a bunch that would be both valid and make sense, in theory. Practically, though I think probably pixel, em, rem and the most useful ones.

I am guessing that always 1rem = 1em in a media query. Any ideas on this? Any thoughts on whether, given that some of us are using em in media queries, if there's any clarity or confusion over supporting rem as well?

I am curious, in part, what units you think might be useful in media queries in a "best practice" sense, beyond Respond. Of course, from there, it'd be natural then to see if Respond should support other units.

Collaborator

beep commented Sep 26, 2011

Great questions, Jay.

I think you’re right: em and rem would be functionally equivalent for media queries. If ex or ch had better support, those might be worthwhile. But at least for now, I think px/em would be the clinchers.

Please see this new pull request of changes to the em-support branch. Adds: support for decimals in media query dimensions, and fixes some issues with grabbing the base font size in IE and converting it from points into pixels.

So, while working on this, as I had to deal with units in points, I was wondering about other valid CSS units of measure that might get used in media queries. There are a bunch that would be both valid and make sense, in theory. Practically, though I think probably pixel, em, rem and the most useful ones.

I am guessing that always 1rem = 1em in a media query. Any ideas on this? Any thoughts on whether, given that some of us are using em in media queries, if there's any clarity or confusion over supporting rem as well?

I am curious, in part, what units you think might be useful in media queries in a "best practice" sense, beyond Respond. Of course, from there, it'd be natural then to see if Respond should support other units.

Reply to this email directly or view it on GitHub:
#18 (comment)

I just sent in a pull request (yesterday) for this issue. I think I have it fixed, but would like the approval of those much smarter than me. Any feedback would be appreciated. Thx

Owner

scottjehl commented Jan 16, 2012

Hey folks!
So, with the help of @NetEffect's great additions to the branch (Thanks so much @NetEffect), and some additional work today, I think we're in pretty good shape to land this feature in master, at which point, I'll tag the release of version 1.1.0 :)

Here's the diff of what all will change. master...em-supportdiff-1

The filesize, minified, will jump from 3.5kb to 3.8kb. Not too bad for a great upgrade. Gzipped, we're still looking at about 2kb transferred.

Here's the branch itself: https://github.com/scottjehl/Respond/tree/em-support

Of course, you can focus on the changes to respond.src.js, as the rest is related to unit testing, demo files, and minified version. Please give the unminified version a test and let me know if you run into any issues.

Also of note: I'm only calculating the value of 1em once, on-demand when it's first needed, as it requires a costly test that just can't run on every media query check. I think this is a safe bet anyway, as resizes are unlikely to change the document's default font size, but let me know if I'm forgetting something.

One case to consider is when the user changes their font size or zooms the page. Currently, FF and Opera adjust media queries when the user changes their font size, but Chrome does not. This codebase matches the behavior of Chrome, as it is now. If we want it to update the value of 1em (and thereby toggle media queries) on font-size changes, we'll likely have to listen for font-size changes (perhaps in a not-so-concise way).

I'm open to suggestions and looking for overall feedback. Thanks!

Owner

scottjehl commented Jan 17, 2012

Em support just landed in master. I've changed the version number to 1.1rc1.

https://github.com/scottjehl/Respond/blob/master/respond.src.js

Please test and let me know if any issues arise!

Thanks

@scottjehl scottjehl closed this Jan 17, 2012

I believe both the html element and media-queries, when put in relative units, refer to the same root value -- depending on device, browser and/or user zoom. On desktop browsers the default is 16px; but this is nearly irrelevant. The important thing is that it's a common reference point and it allows a design to respond automatically to any of those factors in any combination.

I just answered a related question on stackoverflow... correct me if I'm wrong

@carasmo carasmo referenced this issue in twbs/bootstrap Dec 6, 2013

Closed

Pixels vs EM & Vertical Rhythm #1943

graaff added a commit to graaff/Respond that referenced this issue Sep 18, 2014

Support media queries with widths expressed in rem.
Add rem to the regular expressions for width-based media queries. This
was already discussed in #18 but not implemented as part of this change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment