Is their a way in sass to change the digit that rounding occurs on, I would like to stop rounding of a number like this 2.0242914979757085% to this 2.024%. I would like to adjust the amount of decimals in the output css
A quick option without any extra functions would be to multiply the number by 1000, then round it, then divide by 1000.
round($percent * 1000) / 1000;
From the SASS change logs:
The numeric precision of numbers in Sass can now be set using the --precision option to the command line. Additionally, the default number of digits of precision in Sass output can now be changed by setting Sass::Script::Number.precision to an integer (defaults to 3). Since this value can now be changed, the PRECISION constant in Sass::Script::Number has been deprecated. In the unlikely event that you were using it in your code, you should now use Sass::Script::Number.precision_factor instead.
This was added in SASS 3.1.8.
You could use the following function, which is a slight improvement of the function created by Takeru Suzuki :
#function decimal-round ($number, $digits: 0, $mode: round) {
$n: 1;
// $number must be a number
#if type-of($number) != number {
#warn '#{ $number } is not a number.';
#return $number;
}
// $digits must be a unitless number
#if type-of($digits) != number {
#warn '#{ $digits } is not a number.';
#return $number;
} #else if not unitless($digits) {
#warn '#{ $digits } has a unit.';
#return $number;
}
#if $digits > 0 {
#for $i from 1 through $digits {
$n: $n * 10;
}
}
#if $mode == round {
#return round($number * $n) / $n;
} #else if $mode == ceil {
#return ceil($number * $n) / $n;
} #else if $mode == floor {
#return floor($number * $n) / $n;
} #else {
#warn '#{ $mode } is undefined keyword.';
#return $number;
}
}
Output :
decimal-round(0.333) => 0
decimal-round(0.333, 1) => 0.3
decimal-round(0.333, 2) => 0.33
decimal-round(0.666) => 1
decimal-round(0.666, 1) => 0.7
decimal-round(0.666, 2) => 0.67
You could also do the following:
#function ceilHundredths($numbers) {
$numbers: $numbers * 10000;
#if ($numbers < 1) {
$numbers: $numbers - 1;
} #else {
$numbers: $numbers + 1;
}
#return round($numbers)/ 100#{"%"};
}
.test--regular {
margin-left: percentage( -1 / 3 );
}
.test {
margin-left: ceilHundredths( -1 / 3 );
}
.test--regular--2 {
margin-left: percentage( 1 / 3 );
}
.test--2 {
margin-left: ceilHundredths( 1 / 3 );
}
Strictly speaking this is not an answer to your question but if you just want to strip decimal places, you might as well just do this:
font-size: round(12.5); /* => 12 */
It may be appropriate with values that do not require a high level of precision, as for example with font sizes.
Here is my sass rounding function
#function round($value, $fractionDigits: 0) {
$power: math.pow(10, $fractionDigits);
#return math.div(math.round($power * $value), $power);
}
Usage:
round(2.0242914979757085%, 3) // 2.024%
Don't forget to add the sass:math module, like so:
#use "sass:math";
P.S. this is a sass port of following JS method I was using:
export const round = (value, fractionDigits = 0) => {
const power = Math.pow(10, fractionDigits);
return Math.round(power * value) / power;
};
Related
I want to perform mathematical operations using the font-size information with the function below. I remove the rem unit information of $font-size using the sass build-in string functions, but then I cannot perform mathematical operations because the value type is string.
Is there a way to convert a string value type to numeric value type in sass?
#use "../abstracts/variables" as *;
#use "sass:math";
#function em($value, $font-size) {
$length: str-length(#{$font-size}); //sample-think about it font-size 1.125rem
$trim: ($length - 3);
$data: str-slice(#{$font-size}, 1, $trim);
$result: math.div($value, $data);
#return $result + "em";
}
It would probably be better to use a helper function to remove the unit of $font-size such as this one.
#function stripUnit($number) {
#if meta.type-of($number) == "number" and not math.is-unitless($number) {
#return math.div($number, $number * 0 + 1);
}
#return $number;
}
#function em($value, $font-size) {
$data: strip-unit($font-size);
$result: math.div($value, $data);
#return $result + "em";
}
Sass doesn't have a power function. So how could I do a power operation like this?
.className {
padding: 2^2; // Should equal 4
}
Any ideas?
You will have to make a function for it something like:
#function power($number, $power) {
$exponent: 1;
#if $power > 0 {
#for $i from 1 through $power {
$exponent: $exponent * $number;
}
} #else if $power < 0 {
#for $i from 1 through $power {
$exponent: $exponent / $number;
}
}
#return $exponent;
}
The credit should go to this guy who made this: https://www.bhalash.com/archives/13544805657
Unfortunately, I think I misunderstand how to use trigonometric functions in Sass. I've done a fair amount of google search, but with limited results.
In order to animate the transition of an HTML element I have code similar to the following in one of my scss files:
#home-positions {
transform: translateX(200px * sin(45deg));
}
When my Sass is compiling, however, I get the following error:
Syntax error: Undefined operation: "200px times sin(45deg)".
It is very liking I am missing something fundamental, probably pretty simple, and syntactic. Unfortunately, I've looked at a bunch of examples of trigonometric function uses in Sass, though, and I haven't been able to spot the difference between my code, and that in the examples.
The following solution is extracted from Trigonometry In Sass by Daniel Perez Alvarez.
/* power */
#function pow($number, $exp) {
$value: 1;
#if $exp > 0 {
#for $i from 1 through $exp {
$value: $value * $number;
}
}
#else if $exp < 0 {
#for $i from 1 through -$exp {
$value: $value / $number;
}
}
#return $value;
}
/* factorial */
#function fact($number) {
$value: 1;
#if $number > 0 {
#for $i from 1 through $number {
$value: $value * $i;
}
}
#return $value;
}
/* pi */
#function pi() {
#return 3.1415926535897932384626433832795028841971694;
}
/* radian */
#function rad($angle) {
$unit: unit($angle);
$unitless: $angle / ($angle * 0 + 1);
// If the angle has 'deg' as unit, convert to radians.
#if $unit == deg {
$unitless: $unitless / 180 * pi();
}
#return $unitless;
}
/* sine */
#function sin($angle) {
$sin: 0;
$angle: rad($angle);
// Iterate a bunch of times.
#for $i from 0 through 10 {
$sin: $sin + pow(-1, $i) * pow($angle, (2 * $i + 1)) / fact(2 * $i + 1);
}
#return $sin;
}
And then eventually
#home-positions {
transform: translateX(200px * sin(45deg));
}
To anyone confused by this in the future, Sass itself, as of 11/17/14 does not support trigonometric functions. Instead, the Compass framework is required to use them. (See this article for step-by-step instructions on installing compass.)
Or just
$sin45deg: .7071;
Then replace sin(45deg) with $sin45deg. Tada, no framework needed.
I want to pass two values into a function "sprite-chooser()" so that I can choose which sprite to load if it's on a light or dark background. Before I load the sprite I need to check for which UI it is first - so I've got two #if statements and nested #if statements inside but get an error saying: Syntax error: Function sprite-chooser finished without #return.
#function sprite-chooser($ui-for, $bg-color) {
#if ($ui-for == "ui-1") {
#if (lightness( $bg-color ) > 60 and $ui-for == "ui-1") {
#return #{$sprite-dark-ui-1};
}
#else {
#return #{$sprite-light-ui-1};
}
}
#else if ($ui-for == "ui-2") {
#if (lightness( $bg-color ) > 60 and $ui-for == "ui-2") {
#return #{$sprite-dark-ui-2};
}
#else {
#return #{$sprite-light-ui-2};
}
}
}
$background-color: #fff;
.class-name {
background: url(sprite-chooser("ui-1", $background-color)) 0 0 no-repeat;
}
You need another else case
...
#else if ($ui-for == "ui-2") {
#if (lightness( $bg-color ) > 60 and $ui-for == "ui-2") {
#return #{$sprite-dark-ui-2};
}
#else {
#return #{$sprite-light-ui-2};
}
}
#else { #return null; }
}
#for $i from 1 through $layer-count {
#layer-#{$i} { background: url('../layers/layer-#{$i}.png'); }
// background images are named layer-0001.png and up
}
There must be a way to achieve this, but I haven't been able to find anything.
You could do something like this:
#function zerofill($i) { #return #{str-slice("0000",0,4 - str-length(#{$i}))}$i; }
#for $i from 1 through $layer-count {
$i: zerofill($i); // now $i holds the zro-filled value for further use
#layer-#{$i} { background: url('../layers/layer-#{$i}.png'); }
}
DEMO
Or the same with a more general function, that takes a length for the zero-filled value:
#function rep($n, $s: "0") {
$out: $s;
#while str-length($out) < $n { $out: $out + $s; }
#return $out;
}
#function zerofill($i, $n) { #return #{rep($n - str-length(#{$i}))}$i; }
DEMO
Note:
To be able to use the string functions you need to run Sass v3.3, so I quickly rewrote the general function so that it works in older Sass versions (I threw in pow() too that is also already integrated in v3.3, so then you could just use the zerofill() part of this):
#function pow($b, $n) {
$f: $b; #while $n > 1 { $f: $f * $b; $n: $n - 1; } #return $f;
}
#function zerofill($i, $n){
$f: pow(10, $n - 1); $out: null;
#while $f >= 1 {
$out: $out#{floor($i / $f)}; $i: $i - floor($i / $f) * $f; $f: $f / 10;
} #return $out;
}
DEMO