Let's Embrace CSS3 Calc()

Powerful and widely supported, this handy CSS3 property helps save us from headaches when dealing with layout and box model. Back in the day, everything on the web was coded in pixels, but as the desire for flexible design arose, font sizes were frequently defined in ems and more recently in rems. With several units at hand, designers and developers started to dream of being able to combine them and make basic computations. Calc() made this dream come true, allowing mathematical expressions like addition (+), subtraction (-), multiplication (·), and division (÷) to be used as component values. So, if we need to divide a container into 3 boxes, instead of { width: 33.333% } we could write { width: 100% / 3 }. A couple of nasty problems solved The example above does not seem so life-changing, but calc() unveils its real power with the possibility to combine absolute and relative units. If we need to divide a container of unknown width into 3 equal boxes but… each box should have a 20px margin, well we’re in trouble until calc() comes to the rescue. We could simply write: .box { width: calc(100% - 40px); } Note that we need to subtract 40px since our 20px margin is on both sides. Another great use for calc() is when we want to give a margin to a flexible element that’s allowed to expand up to 100%. We need to set this element’s margin to auto if we want it to be centered, but we also want it to have a minimum distance of 2em from the edge of the container: .box { width: calc(100% - 2em); margin: 0 auto; } In this last example we have a fixed-height element with two other elements inside; one fixed, and the other one that expands to cover all of the remaining space. You could try something like this: #container { width: 200px; height: 600px; margin: auto; } .box-1 { height: 140px; } .box-2 { height: 100%; } However, the second box will overflow the container, and this is not what we usually want. Setting the height of the second box to calc(100% - 140px) will solve the problem brilliantly. Life is easier with calc() The examples above greatly show how calc() solves issues that cannot be solved otherwise (except with SASS/LESS of course), but there are many situations in which calc() will make your life just a bit easier. Consider this quite common case: a box of a given height that needs to be centered in a 100% height container. Normally, we shift the box down by 50% of its parent’s height and then shift it up by half of its height: .box {  height: 100px; margin:auto; position: relative; top: 50%; transform: translateY(-50%); } Here, calc() lets us condense the code which makes it easier to understand and maintain it (though the above definition comes in handy if we don’t know the height of the box).: .box {    height: 100px;   margin:auto;   position: relative;   top: calc(50% - 50px); } If we are feeling a bit lazy (we all have those days on occasion) we could make calc() do some calculations for us: .box { width: calc(100% / 6) } This is much clearer than: .box { width: 16.666666667% } Syntax, rules and errors Special attention must be given to the syntax: There must be no space between the function name and the opening bracket, addition and subtraction signs must have white space around them, so: .box { width: calc (100% - 40px) } and .box { width: calc(100%-40px) } are both invalid; the correct syntax is: .box { width: calc(100% - 40px) } As you may have expected, dividing by zero is not possible. Compatibility Compared to other CSS3 properties, the compatibility grade for calc() is pretty good: on the desktop side, Firefox, Chrome, Safari and Opera support it fully since 2012, while IE decently supports it starting at version 9. Speaking about mobile, iOS fully supports it from version 6.1 (prefixed only for that version), while Android has introduced support for it starting with version 4.3 but lacks the ability to perform multiplication and division. The Chrome browser for Android supports it fully. There are still issues to take into account when dealing with calc(). Most browsers do not support it when used in table cells, IE 9 does not support it when used with background-position, and when using any IE version, you may encounter problems with transform, generated content (:before, :after), box-shadow and when using transitions. It’s also noteworthy that expressions utilizing calc() and viewport units (vh, vw) are not re-evaluated after resizing browser windows in Safari 6 and 7 (applies to desktop as well as mobile versions). CSS3 has always scared some people: it has a lot of interesting possibilities but some lack IE8 support. It was still widely used in some places and using the principle of “graceful degradation” has always been a risky path to follow. Now that support for IE8 has been ended we can use most of the CSS3 features safely, including calc() and this dramatically extends the box model possibilities.

More great blog posts from Alessandro Lo Verde