Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Append unit type to the result of a calculation in Sass

Tags:

css

sass

I've been refactoring my CSS to a SASS style sheet recently. I'm using the Mindscape Web Workbench extension for VS2012, which re-generates the CSS each time you save your SCSS. I started with code similar to this:

/* Starting point: */ h1 { font-size: 1.5em; /* 24px ÷ 16px */ } 

Then I tried to refactor it first to this:

/* Recfator: */ h1 { font-size: (24px / 16px)em; } 

But this unfortunately produces:

/* Result: */ h1 { font-size: 1.5 em; }              /* doesn't work, gives "1.5 em" */ 

Notice the extra space, which I don't want there. I've tried several alternatives, here are a few:

h1 { font-size: (24/16)em; }           /* doesn't work, gives "1.5 em" */ h2 { font-size: 24 / 16em; }           /* doesn't work, gives "24/16em" */ h3 { font-size: (24px / 16px) * 1em; } /* works but "* 1 em" feels unnecessary */ h4 { font-size: (24em) / 16; }         /* works, but without "px" it's not                                            really conveying what I mean to say */ 

I've also tried these variants with variables (because I want those anyways), but that didn't change the situation much. To keep the examples in this question sleek I've left out variables. However, I'd happily accept a solution that relies on using variables (in a clean way).

I've gone through the relevant SASS documenation on '/', and appreciate that this is a tough one for SASS because the '/' character already has a meaning in basic CSS. Either way, I was hoping for a clean solution. Am I missing something here?

PS. This blogpost does offer one solution, using a user defined function. That seems a bit heavy-weight though, so I'm interested if there's "cleaner" solutions in line with my attempts above. If someone can explain the "function approach" is the better (or even only) solution then I'll accept that as an answer too.

PS. This related question seems to be about the same thing, though that one specically wants to do further calculations. The accepted answer there is my third workaround (multiplying by 1em), but I'd love to know if there's a different (cleaner) way if I'm willing to forego the ability to do further calculations. Perhaps the method mentioned in said question ("interpolation") is useful for me?


Bottom line: how can you cleanly append the unit type (e.g. em) to the result of a calculation in SASS?

like image 885
Jeroen Avatar asked Dec 16 '12 20:12

Jeroen


People also ask

How do you divide in Sass?

Division permalinkDivision Unlike other mathematical operations, division in Sass is done with the math. div() function. Although many programming languages use / as a division operator, in CSS / is used as a separator (as in font: 15px/32px or hsl(120 100% 50% / 0.8) ).

What are number operations in Sass?

SASS allows for mathematical operations such as addition, subtraction, multiplication and division. You cannot use incompatible units such as px * px or while adding number with px and em leads to produce invalid CSS. Therefore, SASS will display an error if you use invalid units in CSS.

How do I declare a variable in Sass?

Declaration of a variable in SASS: In SASS, you can define a variable by using $ symbol at the starting of the name of the variable and followed by its value. Understanding scope of a variable: SASS variables can be declared anywhere in the document before it is used.


2 Answers

The only way to add a unit to a number is via arithmetic.

To perform operations like concatenation (eg. 1 + px) or interpolation (eg. #{1}px) will only create a string that looks like a number. Even if you're absolutely 100% certain that you're never going to use your value in another arithmetic operation, you should not do this.

More important than not being able to perform arithmetic operations, you won't be able to use them with other functions that expects a number:

$foo: 1; // a number $foo-percent: $foo + '%'; // a string  .bar {     color: darken(blue, $foo-percent); //Error: "1%" is not a number! } 

$amount: "1%" is not a number for `darken'

There is nothing to be gained by casting your numbers to strings. Always use arithmetic (multiplication by 1, or addition by 0) to add a unit:

$foo: 1; // a number $foo-percent: $foo * 1%; // still a number! //or: $foo + 0%  .bar {     color: darken(blue, $foo-percent); //works! } 

Output:

.bar {   color: #0000fa; } 

Here's a mixin I wrote as part of my Flexbox mixin library that will choke if you pass in a string (for those not familiar with Flexbox, the original specification only allows integers for the box-flex property. flex: auto or flex: 30em cannot be made compatible with the comparable box-flex property, so the mixin doesn't bother trying)

@mixin flex($value: 0 1 auto, $wrap: $flex-wrap-required, $legacy: $flex-legacy-enabled) {     @if $legacy and unitless(nth($value, 1)) {         @include legacy-flex(nth($value, 1));     }      @include experimental(flex, $value, flex-support-common()...); }  @mixin legacy-flex($value: 0) {     @include experimental(box-flex, $value, $box-support...); } 
like image 125
cimmanon Avatar answered Sep 28 '22 12:09

cimmanon


You can try either of these:

font-size: $size * 1px; 

or

font-size: $size + unquote("px"); 

Where $size is the result of your calculation.

like image 23
Naoise Golden Avatar answered Sep 28 '22 13:09

Naoise Golden