How i can use global properties in custom variables? (SASS) - css

I'm trying to initialize a variable from custom properties but I can't access it from another file.
More specifically I have set in my _breakpointes-variables.scss
: root {
//Main breakpoints variables
--mobile: 30em;
--tablet: 64em;
--sm-screen: 82em;
--m-screen: 120em;
--l-screen: 140em;
--xl-screen: 160em;
}
And in my _breakpointes.scss i want something like this
$breakpoints: (
"mobile": 30em,
"tablet": 64em,
"sm-screen": 82em,
"m-screen": 120em,
"l-screen": 140em,
"xl-screen": 160em,
) !default;
I already tried with var(--mobile) but I can't get the value in $breakpoints.

$mobile: 30em;
$tablet: 64em;
$sm-screen: 82em;
$m-screen: 120em;
$l-screen: 140em;
$xl-screen: 160em;
:root {
//Main breakpoints variables
--mobile: #{$mobile};
--tablet: #{$tablet};
--sm-screen: #{$sm-screen};
--m-screen: #{$m-screen};
--l-screen: #{$l-screen};
--xl-screen: #{$xl-screen};
}

Related

Loop over a sass/scss variable to generate css variables

I would like if it's possible get css variables from sass variable. I have the next sass variable:
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px,
xxl: 1400px,
);
And I'm trying to do an iteration as the next:
#each $key,$val in $breakpoints{
// Here I want to generate the css variables with a for or manually
--breakpoint-#{$key}: $val; // I tried to do something like this but it doesn't works
}
Expected output result:
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--breakpoint-xxl: 1400px;
Change your loop as below. Notice I replaced $val by #{$val}:
:root {
#each $key, $val in $grid-breakpoints {
--breakpoint-#{$key}: #{$val};
}
}
The syntax #{…} is called interpolation and it is the only way to inject dynamic values into a CSS variable (custom property). Here is a quote from the doc:
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.
$primary: red;
:root {
--primary: #{$primary}; // this one works
--primary: $primary; // this does not
}

Is there a way to use default property value if the variable not used? SCSS

First I created the UI/UX for the application in which I extracted frequently used components, color palette, fonts, and made these into libraries along with media queries. I realized that some components are essentially the same but only differ in a few properties such as height or width. So I made component styling and components that can be customized on the go, so when it comes to the actual interface implementation I can play LEGO essentially.
The question is in the title. Can I set a default value somehow for the variables? So when It is not passed in I don't get an error, but displays as default? If yes, what is the easiest way and the best practice?
Component SCSS:
#mixin component($width, $height, $color) {
.component{
height: $height;
width: $width;
.somethingNested {
color: $color;
}
...
}
#content (if something needs to be overwritten)
}
Yes it’s possible. You add a : value after the parameter.
#mixin component($width: 80px, $height: 80px, $color: white) {
...
}
Tips: mixin supports both positional argument and named argument.
// you wanna keep the default $width and $height but change $color
// with positional argument you have to repeat yourself
.foo {
#include component(80px, 80px, pink);
}
// with named argument, just provide the $color
. foo {
#include component($color: pink);
}
Ref: https://sass-lang.com/documentation/at-rules/mixin#optional-arguments

How to Assign CSS Variable Value to scss Variable or Expression

I'm trying to build my own tiny scalable grid in CSS / scss.
So far I found this decision:
:root {
--page-width: 1170px;
--gutter: 15px;
--columns: 12;
}
.wrapper {
max-width: var(--page-width);
margin-right: auto;
margin-left: auto;
padding-left: var(--gutter);
padding-right: var(--gutter);
}
.row {
margin-left: calc(-1 * var(--gutter));
margin-right: calc(-1 * var(--gutter));
}
.col {
display: block;
margin-left: var(--gutter);
margin-right: var(--gutter);
}
Then I tried to use scss to shorten columns classes description (which at the same time will allow me to change number of columns in one single place in whole code - in CSS Variable --columns) like this
#for $n from 1 through var(--columns) {
.col-#{$n} {width: calc( #{$n} / var(--columns) - var(--gutter) * 2 ); }
}
but it didn't work. The interesting detail is that when I change #for statement from #for $n from 1 throughvar(--columns)`` to #for $n from 1 through12 it compiles well. And there is no problem in compiling CSS-Variable inside #for body. .col-#{$n} {width: calc( #{$n} / var(--columns) - var(--gutter) * 2 ); } compiles well into needed series of classes.
If I use scss variable $columns instead of CSS variable then I'll need to import my grid.scss file into all other scss files of the project.
It's my first question on StackOverflow, so let me know if any other details are needed.
CSS and SCSS variables are two very different things (please see this pen)
To make it work you need a static variable for SCSS to compile
// static (SCSS) variables used produce CSS output
$page-width: 1170px;
$gutter : 15px
$columns: 12;
// dynamic (CSS) variables used at run-time
// note the values are interpolated
:root {
--page-width: #{$page-width};
--gutter : #{$gutter};
--columns: #{$columns};
}
// the for loop is aimed at producing CSS output
// ... why you need the static variable
#for $n from 1 through $columns {
// the content becomes CSS output
// ... why you can use dynamic variables
.col-#{$n} {width: calc( #{$n} / var(--columns) - var(--gutter) * 2 ); }
}
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));
}
The accepted answer is no longer valid. Newer versions of SASS require interpolation to be used for variables.
Refer here for more details
$accent-color: #fbbc04;
:root {
// WRONG, will not work in recent Sass versions.
--accent-color-wrong: $accent-color;
// RIGHT, will work in all Sass versions.
--accent-color-right: #{$accent-color};
}

Can I use mixins to generate new mixins in LESS?

I'm trying to use LESS to dynamically generate a set of mixins that would help me write cleaner media query code. So far in my limited knowledge of the language I've put together code that looks like this:
#sizes: xxs, xs, sm, md, lg;
.mediaQueries(#iterator:1) when(#iterator <= length(#sizes)) {
//Extract name
#sizeName: extract(#sizes, #iterator);
//Attempt to build min-width query
.MQ-min-#{sizeName} (#content) {
#media (min-width: #screen-#{sizeName}) {
#content();
}
}
//Attempt to build max-width query
.MQ-max-#{sizeName} (#content) {
#media (max-width: #screen-#{sizeName}) {
#content();
}
}
.mediaQueries((#iterator + 1));
}
.mediaQueries();
The goal is to have a set of mixins that would allow me to easily and cleanly define some CSS properties for a specific breakpoint, like so:
.generic-class {
background: black;
//Sizes #screen-sm and up
.MQ-min-sm({
background: transparent;
})
}
It doesn't work. Something to note, I'm trying to interpolate the size name into a variable name that would then output me a the px value of that variable into the #media query. Is something like this even possible?
Otherwise my compiler currently breaks on the start of the nested mixin (.MQ-min-#{sizeName} (#content) {) with the error:
Potentially unhandled rejection [2] Missing closing ')' in file ../mixins.less line no. 43
Is something like what I'm trying to achieve possible?
I think the simplest way for you to achieve this is by using a single parametric mixin like given below. This avoids the need for all those iterations, dynamic mixin creations etc.
#sizes: xxs, xs, sm, md, lg;
#screen-xxs: 100px;
#screen-sm: 200px;
.MQ(#content, #sizeName, #max-min) { /* get ruleset, size name and min/max as input */
#selector: ~"(#{max-min}-width: #{screen-#{sizeName}})"; /* form the media selector */
#media #selector { /* use it */
#content();
}
}
.generic-class {
background: black;
.MQ({
background: transparent;
}, /* ruleset */
sm, /* screen size */
max /* min/max */
);
}
If the mixins are for your own usage then this is all that you need. If it is for distribution as library then you may want to put some guards on #sizeName and #max-min variables to restrict invalid values.
Note: Less compiler always had a problem with the interpolation here - #media (min-width: #screen-#{sizeName}) also (I am not sure if it has been addressed) and that's why I created a temp variable.

Grouped .className + media query?

Due an effect that splits the page and lets resize one of the containers. I have to add more styles for the responsive, So I add to this resizable container a class representing my current breakpoint (xs,sm,md,lg)
Like this
if ( ui.position.left <= 480 ) { /* It represent it's width, I am using this as the drag function of draggable */
clase = 'xs';
} else if ( ui.position.left <= 768 ) {
clase = 'sm';
} else if ( ui.position.left <= 992 ) {
clase = 'md';
} else {
clase = 'lg';
}
$('.element').removeClass('xs sm md lg').addClass(clase);
for example:
#media (max-width: 320px)
h2 {
font-size:12px;
}
}
and I now have to add:
.xs h2 {
font-size:12px
}
Is there any way not to have to duplicate the styles? (I have several blocks)
Something like this that I won't work
.xs, #media (max-width:320px) {
h2 {
font-size: 12px
}
}
You can use postcss and plugin https://github.com/hail2u/node-css-mqpacker. This easy and work fine. You can use postcss with SCSS.
When using media queries, you usually have a global default, and then you override the default in the query, if a certain predicate is true (e.g. window with is less than 320px).
In your example, you would like to use the same value as the global default and the overridden value in the media query. IMHO this makes no sense whatsoever.

Resources