Sass function to convert pixels to ems - sass

Take this function in Sass:
#function pem($pxval, $base: 16) {
#return #{$pxval / $base}em ;
}
(source: https://gist.github.com/2237465)
pem(16) returns 1em and it's ok, but pem(16px) returns 1pxem.
how can this function accept both types of input?
thanks

This seems like a good use for SASS's unitless() function.
#function pem($pxval, $base: 16) {
#if (unitless($pxval)) {
$pxval: $pxval * 1px;
}
#if (unitless($base)) {
$base: $base * 1px;
}
#return $pxval / $base * 1em;
}

Related

Using sass #function inside #for

I have some sass function to create same margin, and it is inside loop like this
$short-margins: ( top: 'mt', left: 'ml', bottom: 'mb', right: 'mr' );
#for $i from 0 through 200 {
#each $position, $prefix in $short-margins{
.#{$prefix}-#{$i} {
margin-#{$position}: #{$i}px;
}
}
}
This will create margin classes like this mr-0 and so on until mr-200, the problem is in line
margin-#{$position}: #{$i}px;
There I create px in loop, but i need that to be in rem? I ahve some function like this
$base-font-size: 14px;
// Remove units from the given value.
#function strip-unit($number) {
#if type-of($number) == 'number' and not unitless($number) {
#return $number / ($number * 0 + 1);
}
#return $number;
}
// convert only single px value to rem
#function single-px-to-rem($value) {
$unitless-root-font-size: strip-unit($base-font-size);
#return $value / $unitless-root-font-size * 1rem;
}
But when i want to use function inside loop like this
#for $i from 0 through 200 {
#each $position, $prefix in $short-margins{
.#{$prefix}-#{$i} {
margin-#{$position}: single-px-to-rem(#{$i});
}
}
}
It does not compile throw me error, does any body knows how ti use sass #function inside #for?
You are doing it right, but you need to send the $i value without interpolation:
#for $i from 0 through 200 {
#each $position, $prefix in $short-margins{
.#{$prefix}-#{$i} {
margin-#{$position}: single-px-to-rem($i);
}
}
}

How to use #if within #function to check the orientation of the screen in SCSS?

I've been trying to write conditional SCSS that sets the height of my device to one value if the device is landscape or another if it is in portrait.
I understand I can use a media query to determine the orientation but I don't believe I'm receiving the correct calculation. Currently this is what I have. How can I check that my condition is written properly?
#function calculateRootHeight ($width, $orientation: landscape)
{
$heightPaddedRatio: 1.0;
$heightToWidth: 2/3;
#if (orientation: portrait) {
$heightToWidth: 3/2;
}
#return $heightPaddedRatio * $heightToWidth * $width;
}
#mixin describeRoot($bodyWidth) {
#root {
background-color: #EAE5E5;
}
#media (orientation: portrait) {
#root {
height: calculateRootHeight($bodyWidth, portrait);
}
}
#media (orientation: landscape) {
#root {
height: calculateRootHeight($bodyWidth, landscape);
}
}
}
I think you only need to change the syntax in your #if statement slightly, the rest seems ok.
Using the #debug directive is helpful if you want to check a value in your Sass functions.
#function calculateRootHeight ($width, $orientation: landscape) {
$heightPaddedRatio: 1.0;
$heightToWidth: 2/3;
#if ($orientation == "portrait") {
$heightToWidth: 3/2;
}
#debug "Orientation is '#{$orientation}'";
#return $heightPaddedRatio * $heightToWidth * $width;
}
.portrait {
height: calculateRootHeight(200px, portrait); /* Orientation is 'portrait' */
}
.landscape {
height: calculateRootHeight(200px); /* Orientation is 'landscape' */
}

sass function using only the second argument [duplicate]

This question already has an answer here:
Skipping an optional argument in Sass mixin
(1 answer)
Closed 3 years ago.
sass
I want to use that function
#function baseFontSize($vw : .05vw, $coef : 1){
$return : calc((10px + #{$vw}) * #{$coef});
#return $return;
}
I call it in that way
font-size: baseFontSize();
or
font-size: baseFontSize(1vw);
or
font-size: baseFontSize(1vw, 1.2);
but what if I want to keep the first argument as is and set only the second one ?
font-size: baseFontSize(default, 1.2); ?
how can I do it ?
thanks
how about this.
#function baseFontSize($vw : .05vw, $coef : 1) {
#if ($vw == ''){
$vw : 0.5vw;
}
#if ($coef=='') {
$coef: 1;
}
$return : calc((10px + #{$vw}) * #{$coef});
#return $return;
}
.test1{
font-size: baseFontSize();
}
.test2{
font-size: baseFontSize( '',1.5 );
}
.test3{
font-size: baseFontSize( .08vw,'' );
}

Mixin (PXTOEM) provides error in CSS output

I use Drupal FortyTwo theme. The theme provides a mixin named PXTOEM:
// PXTOEM
// Calculate percentage with font-size as context
#function pxtoem($pixels...) {
$result: '';
#each $item in $pixels {
$result: $result + ($item + 0) / $default-font-size + em + ' ';
}
#return #{$result};
}
In my scss file I use it like:
.header-menus {
padding: pxtoem(0, $grid-gutter-width);
}
But after compiling it doesn't get the proper output?
padding: 0/pxem 0.75/pxem; (see screenshot)[![Screenshot][2]][2]
Instead of + 0 you should add pixels: + 0px. And instead of + em use + 0em.
Sassmeister demo.
If you can not modify source code of the theme, create your own function.
$default-font-size: 16px;
// PXTOEM
// Calculate percentage with font-size as context
#function pxtoem($pixels...) {
$result: '';
#each $item in $pixels {
$result: $result + ((($item + 0px) / $default-font-size) + 0em) + ' ';
}
#return #{$result};
}
.header-menus {
padding: pxtoem(0, 30, 30px);
}
Css output:
.header-menus {
padding: 0em 1.875em 1.875em ;
}

SASS Multiplication with units

If I try to multiply two value with units I get an unexpected error.
$test: 10px;
.testing{
width: $test * $test;
}
result: 100px*px isn't a valid CSS value.
I have used interpolation in the past when I want to do math with variables, and I think it is the simplest solution. If this doesn't work for you, perhaps it is due to a difference in compilers?
$test: 10px;
.testing{
width: #{$test * 2};
}
In fact width: $test * 2; compiles to width: 20px for me, you don't even need to use interpolation for simple math. I am using ember-cli-sass, which uses broccoli-sass-source-maps, which uses node-sass, which wraps libsass, to compile my SCSS to CSS. But it seems to work fine in this jsbin which uses SCSS with Compass.
Where interpolation really helps is if you need to use calc.
$test: 10px;
.testing{
width: calc(50% + #{$test * 2}); // results in calc(50% - 20px)
}
Multiplying units in SASS works like multiplying units in physics / engineering / chemistry / [insert science here].
(see more about this at https://www.sitepoint.com/understanding-sass-units/)
Multiplying two pixel values, will get you px^2, which is an area, not a distance.
What can you do? If you are certain you will be multiplying pixels, use a function and divide by 1 pixel.
$test: 10px;
#function multiply-px($value1, $value2) {
#return $value1 * $value2 / 1px;
}
.testing {
width: multiply-px($test, $test);//100px
}
If you don't know which units you'll be using in advance, you can strip the units from $value2, such that you always get the units of $value1.
(read more on that at https://css-tricks.com/snippets/sass/strip-unit-function/)
$test: 10in;
#function strip-unit($number) {
#if type-of($number) == 'number' and not unitless($number) {
#return $number / ($number * 0 + 1);
}
#return $number;
}
#function multiply-use-first-unit($value1, $value2) {
#return $value1 * strip-unit($value2);
}
.testing {
width: multiply-use-first-unit($test, $test);//100in
}
//try this
$test: 10;
.testing{
width: $test * $test px;
}
You cannot multiply two px values. Better way of doing it is function, but you have to use add in it to achieve it: -
$test: 10px;
#function calc-width($value1, $value2) {
#return $value1 + $value2;
}
.testing {
width: calc-width($test, $test);
}

Resources