How to use functions in :root in SCSS for custom properties? - sass

I'm trying to generate custom properties in the :root using SCSS. I have a function called fluidClamp() that generates a clamp function for text sizes. It accepts a minimum value and a maximum value.
However, I can't get any functions to work in SCSS when they're used inside :root{}.
For example:
:root {
--text-s: fluidClamp(1.4, 1.6);
--text-m: fluidClamp(1.6,1.8);
}
It completely ignores the function, even though the function works everywhere else. What are my options?

You can't use function in your :root pseudo element.
To achive your goal, you need to declare in your :root the basic rules, like:
$text_s: 1.4;
$text_m: 1.6;
:root{
--text-s: $text_s;
--text-m: $text_m;
}
Then in your component you can call:
.myClass{
font-size: fluidClamp(var(--text-s), var(--text-m))
}
Hope it help.

Related

How to make an alias for a Sass mixin with multiple arguments?

Since I couldn't find a Question for this specific problem, I will post the solution I came up with.
I want to create an alias for a Sass mixin which has multiple arguments (partially optional ones).
#mixin box(
$width,
$height,
$background-color: transparent
) {
width: $width;
height: $height;
background-color: $background-color;
}
For this mixin I want to create an alias which just takes all arguments given and passes them through to the original mixin:
#mixin box_alias(
$width,
$height,
$background-color: transparent
) {
#include box( $width, $height, $background-color );
}
It feels very redundant to keep listing all arguments again, this totally works agains the DRY principle. So I am looking for a more elegant solution.
In Sass you have the possibility to allow a mixin (or function) to have an arbitrary number of arguments. To do this you make the last argument an argument list by appending three dots (...) to its definition. If there is only one argument and it ends with the three dots, then the resulting arument list will contain all arguments passed to the mixin. This works very similar to the spread operator in ES2015.
The resulting argument can be passed on to original mixin, adding the three dots again to unfold them as separate arguments for the call:
#mixin box_alias($arguments...) {
#include box($arguments...);
}
This works well for positional and keyword arguments (even in combination) and also for optional arguments.

Sass: rgba function is not working as per documentation

I have two examples that I'm trying to solve:
Example 1
$test: #101E41
body
--colors-dim: rgba(#{$test}, 0.64)
Output: rgba(#101E41, 0.64)
Example 2
body
--colors-active: #101E41
--colors-dim: rgba(var(--colors-active), 0.64)
Output: rgba(var(--colors-active), 0.64)
Both of these look like are examples that should be valid as shown here: https://sass-lang.com/documentation/modules#rgb
Is there something I'm missing?
You need to make use of interpolation to use Sass inside CSS Custom Properties
CSS custom properties, also known as CSS variables, have an unusual declaration syntax: they allow almost any text at all in their declaration values. What’s more, those values are accessible to JavaScript, so any value might potentially be relevant to the user. This includes values that would normally be parsed as SassScript.
Because of this, Sass parses custom property declarations differently than other property declarations. All tokens, including those that look like SassScript, are passed through to CSS as-is. The only exception is interpolation, which is the only way to inject dynamic values into a custom property.
$bar: #900;
:root {
--foo: #{rgba($bar, 0.5)};
}
Results in:
:root {
--foo: rgba(153, 0, 0, 0.5);
}
For your second example, you're going to have to get a little... creative... since Sass will bail and ignore any CSS Custom Property syntax it sees, you can't make use of Sass's rgba function with Custom Properties - the Sass compiler won't resolve the values for you.
Thankfully, you can still use the native CSS rgba function with Custom Properties, the only downside is that you'll need to break your hexadecimal value into its R, G, and B values.
#function toRGB($color)
#return red($color), green($color), blue($color)
$bar: #900
:root
--foo: #{$bar}
--foo-rgb: #{toRGB($bar)}
--foo-dim: #{rgba($bar, 0.5)}
--foo-dim: rgba(var(--foo-rgb), 0.5)
.button
background-color: var(--foo-dim)
Compiles to:
:root {
--foo: #900;
--foo-rgb: 153, 0, 0;
--foo-dim: rgba(153, 0, 0, 0.5);
--foo-dim: rgba(var(--foo-rgb), 0.5);
}
.button {
background-color: var(--foo-dim);
}
https://www.sassmeister.com/gist/39ffc57c492de73066831afe5a9696f6

SASS/SCSS: Define variables based on other variables

How does one define variables with the use of other variables in SASS?
This is how one could do it with LESS:
// import Google Material Colors
// returns variables ie #blue-500, #blue-400 etc
#import 'material.colors.less';
// base
#_color: 'blue';
#_secondary: 'amber';
// primary colors
#color-primary: ~"#{#{_color}-500}";
#color-primary-bright: ~"#{#{_color}-300}";
#color-primary-brighter: ~"#{#{_color}-200}";
#color-primary-brightest: ~"#{#{_color}-50}";
// secondary colors
#color-secondary: ~"#{#{_secondary}-500}";
#color-secondary-bright: ~"#{#{_secondary}-300}";
#color-secondary-brighter: ~"#{#{_secondary}-200}";
#color-secondary-brightest: ~"#{#{_secondary}-50}";
The LESS-way certainly isn't clean and dandy, but -- it works™
The idea is to set a base primary and then just set the other color(s) dynamically based on that.
I can't imagine that one would have to loop/map etc just to do this with SASS?(!)
Sass does not support dynamic variables, period.
You will need to use maps, but I'm not sure this will help you in this specific case (as you are already using external colors):
#import 'material.colors';
$colors: (
primary: (
default: $blue-500,
bright: $blue-300,
brighter: $blue-200,
brightest: $blue-50
),
secondary: (
default: $amber-500,
bright: $amber-300,
brighter: $amber-200,
brightest: $amber-50
)
);
#function color($color, $brightness: default) {
#return map-get(map-get($colors, $color), $brightness);
}
h1 {
color: color(primary, bright);
background-color: color(secondary);
}
Of course you can do it. You can use neat sass color functions and do what you need in a nice and clean way. Take a look at lighten function and even darken function, or at other color functions in general.
Basically, you do it like this:
$primary-color: #08f;
$primary-light-color: lighten($primary-color, 20%);
$primary-lighter-color: lighten($primary-color, 30%);
$primary-dark-color: darken($primary-color, 20%);
$primary-darker-color: darken($primary-color, 30%);
You can see this in action here:
https://codepen.io/anon/pen/PjXRjM?editors=1100#0
Or if you feel like it's a good idea, you could automate it a little with lists and loops. Take a look at this article: https://www.sitepoint.com/managing-color-values-with-sass/, where its author gets through it. (To be honest, I'm not sure if that a good idea at all, as it easily may be hard to understand and maintain later. That's another topic, though.)

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

Using SASS Function on an existing Mixin?

I have an existing mixin which creates a background gradient:
#include bg_gradient($dark:#292446, $light:#3e395b, $highlight:#65617d);
I want to have a hover lighten it , I cannot seem to figure out how to hand that off to the function:
lighten(#include bg_gradient($dark:#292446, $light:#3e395b, $highlight:#65617d), 10%);
does not work , I have also tried rolling into into the end as you can do with other CSS attrs:
#include bg_gradient($dark:#292446, $light:#3e395b, $highlight:#65617d, lighten ($dark, 10%));
Also, tried assigning the mixin to a variable and passing it in as such:
lighten($gradient-value, 10%);
Mixins don't return a value, so you can't use functions on them. In your 2nd example, what you need is to be able to pass the function itself as an argument, which isn't currently possible. Your only option is this (assuming you wanted to apply the function to all 3 arguments):
#include bg_gradient($dark: lighten(#292446, 10%), $light: lighten(#3e395b, 10%), $highlight: lighten(#65617d, 10%));

Resources