Evanss
Evanss

Reputation: 23613

Issue with min and max media queries due to using ems?

Im working on a mobile first site. The media queries are set with ems like so:

html {
    font-size: 62.5%;
}
body {
    font-size: 16px;
    font-size: 1.6rem;
}

@media (min-width: 320em) {
}
@media (min-width: 600em) {
}
@media (min-width: 770em) {
}

I now need to add a max-width media query just below the same breakpoint as my middle media query, so that any screen size is either one or the other.

If I was working with px this would be easy:

@media (max-width: 599px) {
}
@media (min-width: 600px) {
}

Can the same be done with ems? Just to reiterate, I need it so any screen size will be in either the min or max media query. I cant have any 'no mans land' in between.

As its possible to have decimal places on ems I think the following wont work. A screen could be 599.5ems wide as so be in between the 2 media queries.

@media (max-width: 599em) {
}
@media (min-width: 600em) {
}

Upvotes: 3

Views: 3024

Answers (4)

IMI
IMI

Reputation: 2469

Yes, you can use decimals in your em based media queries.

The em values of the media queries will be based on the Browser's "initial" font-size value. This is typically 16px. So you are usually safe calculating your em based media queries by dividing the pixel value by 16.

Example: to get the em equivalent of @media (min-width: 600px) you would divide 600px by 16 which would result in 37.5 and a media query of @media (min-width: 37.5em)

No Man's Land: If you have to mix min-width and max-width media queries it is best to use a max-width media query that equals the min-width of your next media query as stated in @maioman's answer and that should get rid of the "no man's land" gap problem. That way, a device with a max of 600px will use all your styles up to and including the max-width:37.5em styles while devices with have a higher resolution will use the following relevant styles including the min-width:37.5em.

Snippet Example of em based media queries with decimals:

html {
    font-size: 62.5%;
}
body {
    font-size: 16px;
    font-size: 1.6rem;
	color:black;
}

@media (min-width: 20em) { /* = 320px */
	body {color:red;} /* You wont see this color since the max-width media query is overrides it */
}
@media (max-width: 37.4375em) { /* = 599px */
	body {color:green;} /* Be careful where you place the max-width media query. It will override the smaller min-width if placed after. */
}
@media (max-width: 37.5em) { /* = 600px */
	body {color:green;} /* As stated in @maioman's answer, using a max-width that equals the min-width of your next media query should get rid of the "no man's land" problem. */
}
@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>

Upvotes: 2

Yandy_Viera
Yandy_Viera

Reputation: 4380

The “em” is a scalable unit. An em is equal to the current font-size, for instance, if the font-size of the document is 12px, 1em is equal to 12px. Ems are scalable in nature, so 2em would equal 24px, .5em would equal 6px, etc.

The size can be calculated from pixels to em using this formula: pixels/12(current font-size)=em

Check out http://www.w3schools.com/css/css_font.asp

In media queries “rem” as well as “em” don’t refer to the root element (html) but to the browser defaults directly which can only be changed using the browser settings for base font size. This means that even if you specify a font size of 30px on your html element, media queries will still use "user agent's (browser's) initial font-size" as “em” / “rem” based for the media queries unless you also change your default font size in the browser settings.

I will use(for the good of math):

"user agent's initial font-size" = 10px;

So let say you have:

@media (max-width: 59em) {
}

@media (min-width: 60em) {
}

When the browser compute the em that will be equal to:

@media (max-width: 590px) { // 59 * 10(supposed font-size)
}

@media (min-width: 600px) { // 60 * 10(supposed font-size)
}

Here you have a range of 10px where the screen could between the 2 media queries.

Probably you would say, I do a little math and solve the problem but to do math in css there is calc

like this:

@media (max-width: calc(60em - 1px);) { // 60 * 10 = 600px - 1px = 599px
}

@media (min-width: 60em) {  // 60 * 10 = 600px 
}

But unfortunately calc() not working within media queries.

But 1px = 0.1em 1 / 10(supposed font-size)

So you have to do the math a priori:

@media (max-width: calc(59.9em);) { // 60em - 0.1em(1px) = 59.9 * 10 = 599px
}

@media (min-width: 60em) {  // 60 * 10 = 600px 
}

So the only that you have to do is change the "10" to the "user agent's (browser's) initial font-size" and do the math a priori.

I hope this help you.

Upvotes: 1

Bmd
Bmd

Reputation: 1317

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>

Upvotes: 3

maioman
maioman

Reputation: 18764

since min-width will override max-width if you do something like this you should be safe:

@media screen and (max-width: 600em) {
}
@media screen and (min-width: 600em) {
}

div {
    width:5em;
    height:5em;
}
@media screen and (max-width: 12em) {
    div {
        background:green
    }
}
@media screen and (min-width: 12em) {
    div {
        background:red
    }
}
<div>test</div>

fiddle

Upvotes: 1

Related Questions