17

Calc()ulating layouts & backgrounds with CSS

Using relative units of measurement like percentages is excellent for creating responsive and fluid designs, but it's a pain to combine with absolute units (px, em, and such). The calc() CSS function finally relieves that pain, and can give your layouts quite a kick!

Stop! Demo-time!

This is a percentage width block, it should scale! The image next to it has a fixed width of 100px. The height is calculated automatically. We use calc(100% - 100px /* image width */ - 10px * 2 /* padding */ - 10px /* margin */)
Two adjecent floats: one percentage width block next to fixed width image
Content would go here...
Centering a fixed-width block with left and right spanning background and a gradient that automatically adjusts to the width. Unfortunately does not work in regular Firefox yet.
Some more content goes here...
Creating one-element flexible ribbons
Going nuts with the vh/vw units
Using vh/vw units with calc(). Unfortunately, this will only work in Firefox Aurora at the moment.

How does it work?

It's pretty easy — the calc() function can be used anywhere lengths are required. This means it can be used in margin, padding, width, heights background-position, background-size, gradient-stops, and a lot more. Plus you can nest multiple calc() calls if you want.

The calc() function accepts any regular arithmetic: addition (+), subtraction (-), multiplication (*) and division (/). There are a few things to keep in mind: first off, you have to have a space between the minus/plus/whatever signs, or the browser interprets it as a sign instead of an operator. Secondly, you can't divide by a length, only by a number. For example, this would be a valid expression: calc(100% - 1em + 1px).

It would get even better if we could use the code>min(a, b) and max(a, b) functions, but they have not ye been implemented by any browser vendor.

Useful?

Ok, looks quite useful, but where would I need it? Here are some hands-on examples:

  • Put a fixed width float next to a percentage width float:
    width: calc(100% - FIXED_FLOAT_WIDTHpx)
  • Center content with retaining backgrounds by using:
    padding: 0 calc(50% - WIDTHpx / 2);
  • Making gradients that combine percentages and pixels and measure from both sides:
    background-image: linear-gradient(top, 
      black 1px, 
      powderblue 1px, skyblue calc(100% - 1px), 
      black calc(100% - 1px)
    );

Sweet, but can I use it today?

Yes, almost all major browser vendors support calc() — the only absentee seems to be Opera.

Chrome, Safari and Firefox still have a bit of trouble using them in combination with the new vh and vw units. Also, Chrome and Safari don't seem to recalculate the values if used in a gradient (so you'd have to refresh to see it properly). Firefox does not seem to like calc() in a gradient, it works however in Firefox Aurora.

Show me the source!

Feel free to look around the differente source files we used for this example.