HTML & CSS - - By Craig Buckler

CSS3 Gems: The calc() Function

There are many hidden gems in the modular CSS3 specifications. In this post we’ll look at calc(); an incredibly useful property which may change the way you approach layout design.

The CSS3 calc() function is primarily used to calculate lengths, numbers, angles, transition/animation times or sound frequencies. However, it allows you to mix measurement types — a powerful concept in CSS.

Consider a website layout containing two floated elements. You want both elements to be an equal width separated by a 60px horizontal margin. Sounds easy? It’s not a problem in fixed-width design; if the page width is 960px, both elements will be 450px.

But what about fluid or responsive layouts? It’s not possible to determine the page width so most developers would set each element to, say, 45%. The 10% margin will only be 60px if the page happens to be 600px; a wider or narrower browser window will enlarge or contract the margin accordingly.

Fortunately, the new calc() function allows us to calculate widths. In this case, we want both elements to be 50% minus 30px, e.g.

#element1, #element2 { 
  float: left;
  width: calc(50% - 30px);
}

#element2 { 
  margin-left: 60px;
}

Perhaps you want a margin which is relative to the font size — such as 4em? No problem:

#element1, #element2 {
  width: calc(50% - 2em);
}

Or maybe you want a 2px border around both elements:

#element1, #element2 { 
  width: calc(50% - 2em - 4px);
  border: 2px solid #000;
}

I recommend you keep calculations simple, but it’s possible to use complex formulas, e.g.

 #element1, #element2 { width: calc((50% + 2em)/2 + 14px); } 

Browser Support

The calc() function is a W3C recommendation so guess which browser offers native support?

You’re wrong. At the time of writing, it’s just Internet Explorer 9. Firefox also supports it with a prefix; -moz-calc(). It’s not been implemented in webkit (Chrome and Safari) or Opera yet but, it’s so useful, I suspect we won’t need to wait long.

Fortunately, you can use progressive enhancement in your stylesheets:

#element1, #element2 {
  width: 45%; /* all browsers */
  width: -moz-calc(50% - 30px); /* Firefox 4+ */
  width: calc(50% - 30px); /* IE9+ and future browsers */
}

Remember that you’d also need to adjust margins accordingly, e.g.

#element2 {
  margin-left: 10%; /* all browsers */
  margin-left: -moz-calc(60px); /* Firefox 4+ */
  margin-left: calc(60px); /* IE9+ and future browsers */
}

CSS3 min() and max()

If you like calc(), you’ll love the min() and max() functions. They accept two or more comma-separated values and return the minimum or maximum accordingly, e.g.

#myelement {
  width: max(300px, 30%, 30em);
  font-size: min(10px, 0.6em);
}

The functions will be especially useful when using relative font sizes to ensure text does not become too large or small.

Unfortunately, min() and max() are not currently supported in any of the latest browsers. Let’s hope they appear soon.

Sponsors