Scss how convert string to numeric value - css

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";
}

Related

SASS functions check if value is map returns error

I want to check if the value provides to a function is a map or not.
#function func($props...) {
#if(is-map($props)) {
#return 'something';
}
#else {}
}
h1 {
color: func((color: red));
}
I'm getting the error:
(color: red) isn't a valid CSS value.
What am I doing wrong?
I personally never heard about any native Sass function called is-map. If you want to check the type of something, use the type-of function, so for example, checking for type-of($props) == map would solve your problem in this case.
#function func($props...) {
#if(type-of($props) == map) {
#return 'something';
}
#else {}
}
Because function returns map. Not a color as expected. Use map-get to get the access to properties values.
#return map-get($props, color);
And you have the variable argument. To get the first of arguments use nth($props, 1).
Sassmeister demo.
Update
If parameters in map are dynamic you can use this mixin instead of function.
#mixin print($declarations) {
#if $declarations {
#each $property, $value in $declarations {
#{$property}: $value
}
} #else {
#error "mixin print: $declarations is not specified";
}
}
Mixin sassmeister demo.

sass convert px to vw

I found a tutorial on how to write function that converts pixels to vw:
#function get-vw($target) {
$vw-context: (1000*.01) * 1px;
#return ($target/$vw-context) * 1vw;
}
usage on tutorial:
.headline {
font-size: get-vw(72px);
}
but when I use it like its explained nothing happens
my browser returns:
font-size: get-vw(44px); Invalid property value
Since I don't need learn sass at this moment but need only way to convert px to vw can someone help me to make this work?
#function vw($px-vw, $base-vw: 1292px)
#return ($px-vw * 100vw) / $base-vw
.container
font-size: vw(16px)
You can try this:
1. Create a function
$vw-viewport: 1920;
#function get-vw($font){
$vw-context: $vw-viewport * 0.01 * 1px;
#return $font / $vw-context * 1vw;
#return $font;
}
2. Apply the function
.font20{
font-size: get-vw(20px);
}
Did you test this?
#use "sass:math"; //You can use "sass:math"
$vw-viewport: 1920;
#function get-vw($font){
$vw-context: $vw-viewport * 0.01 * 1px;
#return math.div($font, $vw-context) * 1vw;
}
The above didn't work for me but this did :
#function strip-unit($number) {
#if type-of($number) == 'number' and not unitless($number) {
#return $number / ($number * 0 + 1);
}
#return $number;
}
#function get-vw($px-vw, $base-vw: 1920px){
#return #{strip-unit($px-vw) * 100 / strip-unit($base-vw)}vw;
}

Return Hex Color code with SASS lighten function

How do I return a hex code using the SASS lighten function?
#function returnHexValue($color){
#debug $color;
#if $color == "white" {
#return "#fff";
}
#if $color == "black" {
#return "#000";
}
#return $color;
}
When I use something like returnHexValue(lighten(#000,100%));, I still get the value returned as white instead of #fff.
You can use following function that will force Hex value
#function force-hex($color) {
#if type-of($color) == 'color' {
$hex: str-slice(ie-hex-str($color), 4);
#return unquote("\##{$hex}");
}
#return $color;
}
body{
color: force-hex(lighten(#000,100%));
}
Already there are few request in SASS github project to prevent conversion of Hex to a color value. You can follow below issues
https://github.com/sass/sass/issues/343
https://github.com/sass/sass/issues/363

Trigonometric functions in Sass -- preprocessor error

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.

Rounding numbers in Sass and adjusting the amount of decimals

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;
};

Resources