SASS Functions with Variables - sass

I'm fairly new to SASS functions and mixins. I would like to make a SASS function that multiplies a base spacing unit variable based on the number that is provided in the class name.
It would work like this. Say you had a variable called $base-spacing-unit with a value of 10. If you put the class ".pad-top-b5" on an HTML element it would give it a top padding of the $base-spacing-unit x 5.
The function might look something like this:
$base-spacing-unit: 10;
#function pad-top-b($val) {
padding-top: ($base-spacing-unit * $val);
}
On the HTML element you could put a class like this:
<div class="pad-top-b10"></div>
And the element would have a top padding of 100px. Is this even possible with SASS?

You can use a #for loop that generates a set of classes:
$class-slug: pad-top-b;
$base-spacing-unit: 10;
$classes-amount: 10;
#for $i from 1 through $classes-amount {
.#{$class-slug}#{$i} {
padding-top: ($base-spacing-unit * $i);
}
}
Demo on SassMeister.

Related

how to avoid SCSS from recognizing slash symbol as a Division in a function

I'm using SCSS (sass) and there is a problem whenever I use a function with input variables if the variables are being used with a slash symbol (/) they will be recognized as Equation
here I have 2 examples for you so in the first one I used a slash symbol (/) and it's considered as a division
and the next one I used percent (%)and it considers as a mod instead of a simple percentage
so how can you avoid it being considered as an Equation?
here is some example :
#mixin grid_column_row($column_1,$column_2,$row_1,$row_2) {
grid-column: ($column_1)/($column_2);
grid-row: ($row_1)/($row_2);
}
in this example I want this to be considered as a normal grid-row and grid-column like :
grid-row:1/3;
grid-colmun:6/12;
not as a division like :
grid-row: 0.33;( 1/3)
grid-colmun :0.5; (6/12)
and second example with percentage (%) :
#mixin font-size_p($percent) {
font-size: $percent% ;
}
For your first mixin, you need to use interpolation:
#mixin grid_column_row($column_1,$column_2,$row_1,$row_2) {
grid-column: #{$column_1}/#{$column_2};
grid-row: #{$row_1}/#{$row_2};
}
For your second mixin, as indicated in the documentation:
Percentages in Sass work just like every other unit. They are not interchangeable with decimals, because in CSS decimals and percentages mean different things. For example, 50% is a number with % as its unit, and Sass considers it different than the number 0.5.
You can convert between decimals and percentages using unit arithmetic. math.div($percentage, 100%) will return the corresponding decimal, and $decimal * 100% will return the corresponding percentage. You can also use the math.percentage() function as a more explicit way of writing $decimal * 100%.
You can write your mixin as:
#mixin font-size_p($percent) {
// Or + 0%, depending on how your want to write your percentage values
font-size: $percent + 100%;
}
Or like this:
#mixin font-size_p($percent) {
font-size: math.percentage($percent);
}
You need a sass library made for that use case (You can use [list.slash()] to force / to be used as a separator):
#use "sass:list";
#mixin grid_column_row($column_1,$column_2,$row_1,$row_2) {
grid-column: list.slash($column_1, $column_2);
grid-row: list.slash($row_1, $row_2);
}
And second case you can use the library math:
#use "sass:math";
math.percentage($number) // converts number to a percentage number

sass percentage of a number

I am stuck here.
I want to calculate 2/3 of 10rem like this:
$percentage : percentage(2/3); // 66.666667%
$width : 10rem;
$calculate : do magic: 66.666667% of 10rem;
img { max-height: calc( 100vh - $calculate ); }
I have been looking in the SASS documentation. I can only find some stuff about math function and not too much about percentage.
The percentage(2/3) function call appends a %. You can not multiply that with a non-unitless value like 10rem. Instead, calculate it directly like:
img {
max-height: calc(100vh - #{2/3 * 10rem});
}
The #{} (interpolation) is needed to render the result of the calculation inside the Css calc() expression.
Read more on...
Sass interpolation: https://sass-lang.com/documentation/interpolation
Operators: https://sass-lang.com/documentation/operators/numeric

SASS width percentage in #for loop

I have another question I can't seem to get answered anywhere.
Currently working with a team that needs custom classes to style their elements. They wanted a width percentage class they can put on anything to make something a certain percentage width.
I made this:
#for $i from 0 through 100 {
.width-percentage-#{$i} {
width: #{$i}% !important;
}
}
But IntelliJ is throwing an error..
You get this error by using DartSass. The following error should be shown:
Undefined operation "0 % !important".
I suppose DartSass try to use the % as math operator modulo which is not possible because !important isn't a number (and $i is interpolated). You need to interpolate the % too (#{"%"}):
#for $i from 0 through 100 {
.width-percentage-#{$i} {
width: #{$i}#{"%"} !important;
}
}

Check if SASS parent selector exists. Is it possible

I have a question. So in a mixing I am making a reference to the parent selector "&". This works as long as the mixin is not nested. Is there a way to to detect if the mixing is being used in a non nested scenario, or to check if "&" is null?
This works when the mixin call is not nested
=myresponsiveMixin($media)
#if $media == small {
#media only screen and (max-width: $break-small)
#content
#else if $media == medium
#media only screen and (min-width: $break-small + 1) and (max-width: $break-large - 1)
#content
This works great when the mixin call is nested, but will not resolve '&' when not nested
=myresponsiveMixin($media)
#if $media == small {
#media only screen and (max-width: $break-small)
.classInHTMLToAllowMediaQueries &
#content
#else if $media == medium
#media only screen and (min-width: $break-small + 1) and (max-width: $break-large - 1)
.classInHTMLToAllowMediaQueries &
#content
So the question is, if there is a way to be able to check the value of parent selector "&", so I can cover all bases in a single mixin?
#mixin does-parent-exist {
#if & {
.exists & {
color: red;
}
} #else {
.doesnt-exist {
color: red;
}
}
}
http://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-script
You're trying a wrong solution to solve your issue.
Have a look at how this problem is addressed in powerful SASS frameworks. Let's take Susy by Eric Meyer as a great example.
Let's imagine you've got the following HTML:
<div class="container">
<div class="parent">
<div class="child">
Bla bla
</div>
</div>
</div>
When you call a mixin for the first time, you're doing it simply (the code is in the indented .sass syntax):
$total-columns: 8 // Declaring a varible that will be used by the mixin
.parent
+span-columns(4) // Span four of eight columns
But when you call that for a child element, the proportions would be crooked, because the parent is already proportioned:
.child
+span-columns(2) // This will fail. You want 2 of 8 columns,
// but due to nesting the math is crooked.
// It will be "2 of (4 of 8)".
To address the issue, you provide an optional argument: a context that is used to do the math:
.child
+span-columns(2, 4) // Now the mixin will take 2 parts of 4
// instead of 2 parts of four
The source code for this mixin is available on GitHub.
In short, it creates an optional argument like this (the code is in the CSS-like .scss syntax):
#mixin span-columns(
$columns,
$context: $total-columns
//...
) {
//...
width: columns($cols, $context /*...*/);
//...
}
See how $context has a default value? Thanks to the default value this argument can be omitted. In other words, $context is an optional argument.
When calling this mixin, if $context is not provided (e. g. span-columns(2)), then it is set equal to $total-columns. The $total-columns variable should be set prior to calling the mixin for the first time (see my example above).
Then the two arguments are used to calculate the width.
UPD 2013-03-30
I am not trying to figure out things in regards to columns... I have modifier my question to make it clearer.
First of all, my recommendation concerns not only grid columns. It's a universal technique you can adopt.
Secondly, now i see that you're trying to nest media queries.
Well, some media queries of different type can be combined in CSS3: e. g. print and width. But you can't put a min-width: 601px inside max-width: 600px, this just won't work!
There's an extensive answer here on StackOverflow describing why you should not nest media queries of the same type: https://stackoverflow.com/a/11747166/901944
Thirdly, you're trying to invent the wheel. There's already a fantastic mixin for crunching media queries: Respond To by Snugug. It's super easy to use and very effective.
Fourthly, the XY thing. Instead of asking about your crooked mixin, please describe the problem that you're trying to solve with it! Show us the actual HTML and explain what behavior you would like to achieve.
We will show you that it can be solved with a simple, elegant, semantic solution that does not require SASS hacking.

Using variables for CSS properties in Sass

I am writing a #mixin with some math in it that calculates the percentage width of an element, but since it is very useful I would like to use the same function for other properties too, like margins and paddings.
Is there a way to pass the property name as an argument to a mixin?
#mixin w_fluid($property_name, $w_element,$w_parent:16) {
$property_name: percentage(($w_element/$w_parent));
}
You need to use interpolation (eg. #{$var}) on your variable in order for Sass to treat it as a CSS property. Without it, you're just performing variable assignment.
#mixin w_fluid($property_name, $w_element, $w_parent:16) {
#{$property_name}: percentage(($w_element / $w_parent));
}
In addition to the #rcorbellini response
You can use string and variable together
#mixin margin($direction) { // element spacing
margin-#{$direction}: 10px;
}

Resources