Skip to content

Instantly share code, notes, and snippets.

@jareware
Last active December 16, 2015 16:49
Show Gist options
  • Save jareware/5465928 to your computer and use it in GitHub Desktop.
Save jareware/5465928 to your computer and use it in GitHub Desktop.
CSS calc() function.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, height=device-height"/>
<title>CSS calc() function</title>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
code {
color: black;
}
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
#example1 {
border: 1px solid gray;
overflow: hidden;
margin-bottom: 10px;
}
#example1 > div {
float: left;
text-align: center;
background: #CCC;
padding: 30px;
}
#example1 > div:first-child {
width: calc(100% - 250px);
width: -webkit-calc(100% - 250px); /* for Safari, Blackberry et al */
border-right: 1px dotted gray;
}
#example1 > div:last-child {
width: 250px;
}
#example2 {
border: 1px solid gray;
overflow: hidden;
padding: 0 0 10px 10px;
margin-bottom: 10px;
}
#example2 > div {
float: left;
width: calc(100% / 3 - 10px);
width: -webkit-calc(100% / 3 - 10px); /* for Safari, Blackberry et al */
border: 1px dotted gray;
margin: 10px 10px 0 0;
padding: 30px;
text-align: center;
background: #CCC;
}
</style>
</head>
<body class="container">
<h1>CSS calc() function</h1>
<p>CSS function for computing values of various types.</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/CSS/calc">MDN documentation</a>
<li><a href="http://caniuse.com/#search=calc">Browser support</a>
<li>Applicable to
<code>length</code>,
<code>frequency</code>,
<code>angle</code>,
<code>time</code>,
<code>number</code> and
<code>integer</code> CSS types
<li>Is supposedly nestable, e.g. <code>calc(100% - calc(5em + 1px))</code> should be valid, but didn't work for me
<li>Then again standard precedence tools get the job done, so not sure what's the point: <code>calc(100% - (5em + 1px))</code>
</ul>
<h2>Use cases</h2>
<p>You can use <code>calc()</code> to compute between compatible unit types:</p>
<pre>calc(10cm + 5mm)</pre>
<p>This is a bit silly, because you can do that beforehand, and SASS can also handle it for you:</p>
<pre>$ sass -i
>> 10cm + 5mm
10.5cm</pre>
<p>But CSS supports
<a href="https://developer.mozilla.org/en-US/docs/CSS/length">two classes of length unit types</a>
which are fundamentally incompatible<sup>(asterisk)</sup>: absolute lengths (such as <code>1px</code>) and relative
lengths (such as <code>50%</code>):
</p>
<pre>$ sass -i
>> 1px + 1em
SyntaxError: Incompatible units: 'em' and 'px'.</pre>
<p>
This is because <em>relative lengths</em> reference other elements in the DOM (usually the parent node, but also
the viewport for example), and they aren't known until <em>render time</em>.
</p>
<h2>Practical examples</h2>
<p>
This demonstrates one of the intuitive use cases of being able to calculate between relative and absolute lengths:
</p>
<div id="example1">
<div>Fluid main container<br>(width: 100% - 250px)</div>
<div>Fixed-width sidebar<br>(width: 250px)</div>
</div>
<p>
There's several ways in which the example above can be implemented without <code>calc()</code>, however, for
example by absolutely positioning both elements, but it's an intuitive example on where the function's useful.
</p>
<p>
The following, on the other hand, is very hard to do without <code>calc()</code> (or helper elements or flexboxes):
</p>
<div id="example2">
<div>#1</div>
<div>#2</div>
<div>#3</div>
</div>
<p>
In the example, the width of each box is relative to the width of the parent, but the padding between them is
absolutely <code>10px</code>.
</p>
<h2>Notes</h2>
<ul>
<li>Not everything that should conceptually work does, e.g. <code>calc(50vw - 50px)</code> won't fly on Chrome Canary
<li>
SASS <a href="http://sass-lang.com/docs/yardoc/file.SASS_CHANGELOG.html#_support">won't be bothered</a>, but also Compass won't help
<ul>
<li>There's a <a href="https://coderwall.com/p/qac-og">mixin</a> for that!
<li>Can't be implemented as a <code>@function</code>, because need to output several <code>width:</code> properties
<li>Variable expansion won't work directly with <code>width: calc(100% - $padding)</code> but <code>width: calc(100% - #{$padding})</code> sure enough</li>
</ul>
</li>
<!-- TODO: Does this work on Chrome for Android? -->
</ul>
<!-- TODO: Final word; should you use this? -->
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment