calc
isn’t a new feature, but at the time of writing MDN describes it as experimental:
this technology’s specification has not stabilized, check the compatibility table for the proper prefixes to use in various browsers. Also note that the syntax and behavior of an experimental technology is subject to change in future versions of browsers
– MDN
According to caniuse.com, it’s a little safer than MDN suggests.
One area where it does fall over is media queries. For a number of reasons, it’s better practice to use proportional media queries (em
) than pixel based media queries.
This falls over with range based media queries, consider the following:
@media (min-width:64px) and (max-width:127px) {
/* two cells/row */
.grid-cell:nth-child(2n+1) { clear: left; }
}
@media (min-width:128px) {
/* three cells/row */
.grid-cell:nth-child(3n+1) { clear: left; }
}
calc
becomes necessary when converting this exactly to proportional based media queries:
@media (min-width:4em) and (max-width:calc(8em - 1px)) {
/* two cells/row */
.grid-cell:nth-child(2n+1) { clear: left; }
}
@media (min-width:8em) {
/* three cells/row */
.grid-cell:nth-child(3n+1) { clear: left; }
}
As far as I am concerned, the above code demonstrates why calc
is one of modern CSS’s most elegant features. You can have your animations, your gradients, your rounded corners. I will take calc
.
Unfortunately it doesn’t work in media queries*.
Options for calc-less media queries
Hoping browsers round down and using @media (min-width:4em) and (max-width:59.99em)
.
Hoping browsers include media queries in zoom calculations and using pixel based values. Not including them started as a bug, in up-to-date browsers it is squashed.
Hoping reverting the value in this code block won’t cause unforeseen interference with other code.
@media (min-width:4em) {
/* two cells/row */
.grid-cell:nth-child(2n+1) { clear: left; }
}
@media (min-width:8em) {
/* three cells/row */
.grid-cell:nth-child(2n+1) { clear: none; }
.grid-cell:nth-child(3n+1) { clear: left; }
}
Regardless, there is some amount of hope involved. Fortunately, the amount of hope in web development is in sharp decline, I’m sure it won’t be too long before the above is resolved.
*Checked Jan 20, 2015 against Chrome 39, Firefox 34 & Safari 8 on OSX
Peter, I hate that we have to deal with this, but we do. :(
I use Sass, so I use a couple of different solutions, depending on the project:
1. Using variables for em values:
$midBp: 45em;
$midBpLess: 44.9375em;
(why that value for BpLess? 1px/16 of 1em is .0625em)
Then you can use the mediaquery:
@media only screen and (min-width: #{$midBp}) {}
@media only screen and (max-width: #{$midBpLess}) {}
and you have no issue with browsers rounding incorrectly, which they’ve been known to do.
2. Using Sass’s arithmetic.
Writing this mediaquery:
@media only screen and (min-width: (767em/16)) {}
@media only screen and (min-width: (768em/16)) {}
results in:
@media only screen and (min-width: 47.9375em) {}
@media only screen and (min-width: 48em) {}
Both are great techniques for covering the edge cases you’re talking about here.