A Tale of CSS and Sass Precision

Share this article

A Tale of CSS and Sass Precision
Various browsers as totems looking at a mysterious percentage sign
Artwork by SitePoint/Natalia Balska

At Edenspiekermann, we rely heavily on code reviews to make sure the work we commit is good enough™. One thing I regularly come across is the fuzziness around numbers, especially the ones that have a decimal point. Hence, here is a short article to shed light on this matter.

Initial Setup

To make the whole explanation clearer before even getting started, we are going to work on a small piece of code that happens to be very relevant to our case.

.list-item {
  float: left;
  width: 33%;
}

What’s the Problem?

Maybe you are wondering what the problem is with this code snippet. In appearance, not much. It is a three-column grid layout. Quite the usual you could say.

Although, 33% + 33% + 33% equals 99%, not 100%. While it might not make any difference in most cases, when working on straight alignments — 1% can make a big difference. 1% of a 1400px large container is 14px. That’s a pretty big distance.

Why don’t we just move the decimal dot (or rather add it) to make it more precise? We could probably reduce the gap to 1.4px, or even 0.14px which is not worth bothering anymore I suppose! Let’s start with that then.

.list-item {
  float: left;
  width: 33.33%;
}

That works better but it still ain’t perfect. This problem has been extensively discussed in this absolutely great article from John Albin Wilkins entitled “Responsive Design’s Dirty Little Secret”. If you haven’t read it, read it.

Can’t the Browser Handle This?

At this point, you might be wondering why the browser cannot just make it work™. The thing is, the CSS specifications don’t specify (of the irony) anything to browser vendors about what to do in case of floating precision with percentage numbers. And when the CSS specifications omit a detail, you can be sure that every browser will do it its own way.

Take this example from the aforementioned article:

[…] with a 6 column grid, each column is 100% ÷ 6 = 16.666667% wide. On a 1000 pixel wide viewport (which I’ve conveniently picked to make our math easier), that calculates to 166.66667 pixels per column. Since the spec gives no guidelines, browser vendors are free to make their own rules. If a browser were to round to the nearest pixel, in our example, we’d arrive at 167 pixels. But since 167 x 6 = 1002 pixels, we’d no longer have room for all 6 columns in our viewport. Alternatively, if a browser rounded down to 166 pixels per column, we’d be 4 pixels short of perfectly fitting all columns into our viewport. — John Albin Wilkins

That’s exactly what happens. Old versions of Internet Explorer (mainly 6 and 7) round to the closest whole number, resulting in layout breakage. WebKit browsers round down, which prevents any catastrophic layout result but leaves us with extra space. Opera (at least in its old rendering engine) was doing some weird stuff that I won’t even bother to explain. But again, there is no rule about this behaviour in the spec, so who’s to blame? Not the browsers resorting in subpixel rendering, that’s for sure, because in the end that’s what gives the best results.

Anyway, it’s pretty much a mess, and we’ll come back to this in the conclusion of this article.

What About Sass?

Sass supports mathematical operations. It is not new and is actually one of the first few things Sass was used for (to build math-based grid systems). What we could do is tell Sass that we want to divide our container’s width in 3 equal parts.

.list-item {
  float: left;
  width: (100% / 3);
}

We could also use the percentage(..) function for the same result:

.list-item {
  float: left;
  width: percentage(1 / 3);
}

Sass, in both Ruby and LibSass, has a precision option of 5. That’s actually a problem because it is pretty low; 10 would be better but that’s not the default (although configurable, but not in an easy way).

This code will yield the following CSS:

.list-item {
  float: left;
  width: 33.33333%;
}

That does not solve our browser problem, but that does make authoring stylesheets easier. Not only do we not have to handle the calculation and the precision ourselves, but we also make the code more convenient to read and update by actually displaying the calculation.

I’d say that is a good thing.

The Best of Both Worlds

So far, we have learnt that it is good to let Sass handle the computation for us rather than hard coding the value. Now, the best approach would be to let the browser handle this in the best way it can. For this, there is the calc(..) CSS function.

.list-item {
  float: left;
  width: calc(100% / 3);
}

This code snippet does not get compiled into anything. It hits the browser as authored. Then, it is up to the browser to make the best of it. I’ll be entirely honest with you and tell you I’m not sure whether browsers handle calc(..) values the same as regular ones. I suppose they perform the calculation, then do their rounding. Some browsers appear to bring subpixel rendering into the equation. If you have any insight on this, please share in the comments.

For browsers that do not support the calc(..) expression, mostly Internet Explorer 8 and Opera Mini, we can put a static value expressed as a Sass operation right before it. This way, we get the best of both worlds.

.list-item {
  float: left;
  width: (100% / 3);
  width: calc(100% / 3);
}

Conclusion

Let’s have a little recap. For starters, percentage based layouts are hard to handle because of browser inconsistencies and a lack of specification in the matter of floating precision.

Then, hard-coding values resulting from a somehow complex calculation is usually not a good idea. We can let Sass compute an approximation (to 5 digits after the floating point).

Even better, we can let the browser compute an approximation. In a perfect world, when the browser is in charge of both the math and the rendering, it should be able to make the best out of it. To head in that direction, we rely on the calc(..) function.

That’s pretty much where it is at right now. Nothing new, but I thought a quick recap would help!

Frequently Asked Questions (FAQs) about CSS and Sass Precision

What is the difference between CSS and Sass?

CSS (Cascading Style Sheets) is a style sheet language used for describing the look and formatting of a document written in HTML. Sass (Syntactically Awesome Stylesheets) is a preprocessor scripting language that is interpreted or compiled into CSS. The key difference between the two is that Sass has features that don’t exist in CSS such as variables, nesting, mixins, inheritance, and others. These features make Sass more powerful and flexible than CSS.

How does precision work in CSS and Sass?

Precision in CSS and Sass refers to the level of detail and accuracy in the rendering of styles. In CSS, precision is often limited due to the lack of variables and functions. On the other hand, Sass, with its advanced features, allows for greater precision. For instance, you can define variables for specific colors or sizes, and use them consistently throughout your stylesheet, ensuring precision and consistency in your design.

Can I use Sass in any web project?

Yes, you can use Sass in any web project. Sass is compatible with all versions of CSS. So, you can start with CSS and then add Sass features as needed. However, keep in mind that Sass requires a preprocessor to convert it into CSS, which the browser can interpret.

What are the benefits of using Sass over CSS?

Sass offers several benefits over CSS. It allows for the use of variables, nesting, mixins, and inheritance, which can make your stylesheets more organized, reusable, and maintainable. Sass also supports mathematical operations, allowing you to calculate dimensions and colors directly in your stylesheets.

How can I improve the precision of my CSS or Sass code?

Improving precision in your CSS or Sass code can be achieved by using variables for consistent values, using mathematical operations for accurate calculations, and using functions and mixins for reusable styles. Also, using a CSS reset can help ensure consistency across different browsers.

What is a CSS preprocessor and why is it necessary for Sass?

A CSS preprocessor is a scripting language that extends the default capabilities of CSS. It allows you to use variables, nested rules, mixins, functions, and mathematical operations in your stylesheets. Sass is a type of CSS preprocessor. It’s necessary because browsers can only interpret CSS. Therefore, the Sass code needs to be compiled into CSS before it can be used in a web project.

How does Sass help in writing DRY (Don’t Repeat Yourself) code?

Sass supports features like variables, mixins, and inheritance, which help in writing DRY code. Variables allow you to define a value once and use it in multiple places. Mixins let you write reusable styles that can be included in other rules. Inheritance allows you to share a set of CSS properties from one selector to another.

What are the potential pitfalls of using Sass?

While Sass offers many advantages, it also has potential pitfalls. The need for a preprocessor can add complexity to your development process. Also, if used improperly, some Sass features like nesting and mixins can lead to bloated and inefficient CSS output.

How can I start learning and using Sass?

There are many resources available online to learn Sass. The official Sass website provides a comprehensive guide to get started. You can also find tutorials on web development sites and online learning platforms. To start using Sass, you’ll need to set up a Sass preprocessor in your development environment.

Can I convert my existing CSS code to Sass?

Yes, you can convert your existing CSS code to Sass. Since Sass is a superset of CSS, any valid CSS is valid Sass. You can start by renaming your .css files to .scss (Sassy CSS), and then gradually start using Sass features in your code.

Kitty GiraudelKitty Giraudel
View Author

Non-binary trans accessibility & diversity advocate, frontend developer, author. Real life cat. She/they.

AdvancedCSSpatrickcsass
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week