What does :where(:root) mean in SCSS - sass

I have an example code with :where(:root)
:where(:root) {
//code
}
I know about :root, but not about :where().
I can't find anything on google. What it does actually?

The :where() CSS pseudo-class function takes a selector list as its argument, and selects any element that can be selected by one of the selectors in that list.
/* Selects any paragraph inside a header, main
or footer element that is being hovered */
:where(header, main, footer) p:hover {
color: red;
cursor: pointer;
}
/* The above is equivalent to the following */
header p:hover,
main p:hover,
footer p:hover {
color: red;
cursor: pointer;
}
More info here:
:where() Docs

Related

sass merge selectors on ampersand

assuming I have an existing SASS rule like:
[dir] .foo {
background-image: ...;
// ... some more
}
And I want to add specific behaviors for ltr / rtl like:
[dir] .foo {
background-image: ...;
[dir='ltr'] & {
padding-right: ...;
}
[dir='rtl'] & {
padding-left: ...;
}
}
this would generate undesired css like:
[dir='rtl'] [dir] .foo {
padding-left: ...;
}
This will not match what I want.
Assuming I cannot change the parent selectors (due to specificity), is there any way I can write such nested selectors in a way that compiles to just [dir='rtl'] .foo {...} for the nested elements?
Some resources about the ampersand: https://css-tricks.com/the-sass-ampersand/#aa-qualifying-based-on-context
There is no way that I know to merge selectors as requested.
As you're not allowed to change the parent selector, the only solution I see would be to use the #at-root rule.
#at-root
The #at-root rule is usually written #at-root { ... } and causes everything within it to be emitted at the root of the document instead of using the normal nesting. It's most often used when doing advanced nesting with the SassScript parent selector and selector functions.
Definition on sass-lang.
Here is an example:
[dir] .foo {
$root: '.foo';
background-image: linear-gradient(black, white);
#at-root {
[dir=ltr] #{$root} {
padding-right: 1em;
}
[dir=rtl] #{$root} {
padding-left: 1em;
}
}
}
This will compile to:
[dir] .foo {
background-image: linear-gradient(black, white);
}
[dir=ltr] .foo {
padding-right: 1em;
}
[dir=rtl] .foo {
padding-right: 1em;
}
You could create a mixin to help you with that:
#mixin dir($dir: ltr, $selector: &) {
#at-root {
[dir=#{$dir}] #{$selector} {
#content;
}
}
}
[dir] .foo {
$root: '.foo';
background-image: linear-gradient(black, white);
#include dir(ltr, $root) {
padding-right: 1em;
}
#include dir(rtl, $root) {
padding-right: 1em;
}
}
Food for thougt
If you don't have to support internet explorer, you might want to check padding-inline-end and padding-inline-start properties.
They will free you from the need to have different rules for different directions.
padding-inline-end
The padding-inline-end CSS property defines the logical inline end padding of an element, which maps to a physical padding depending on the element's writing mode, directionality, and text orientation.
MDN Docs - padding-inline-end
padding-inline-start
The padding-inline-start CSS property defines the logical inline start padding of an element, which maps to a physical padding depending on the element's writing mode, directionality, and text orientation.
MDN Docs - padding-inline-start

Import scss file but do not render its contains

I have a SCSS file that contains CSS. I want to extend those classes yet I don't want to render those on my main file (refer below).
File structure:
_vars.scss
main.scss
main.scss
#import 'vars';
//extend margin class
body{
margin: #extend .m10;
}
In my _vars.scss
.m10{margin:10px;}
.p10{padding:10px;}
If the main SCSS is compiled, it will be compiled to:
main.css
.m10{margin:10px;} /* <-- i dont want to see this in my compiled scss --> */
.p10{padding:10px;} /* <-- i dont want to see this in my compiled scss --> */
body{
margin: 10px; /* <-- but still extent from the .m10 class of _vars.scss --> */
}
Any ideas to not display those classes from the _vars.scss yet still extending those classes in the main.scss? Is there a way to do that with SASS?
The way to go is to use placeholders instead of classes:
_vars.scss:
%m10 {
margin:10px;
}
%p10 {
padding:10px;
}
main.scss
#import 'vars';
body {
#extend %m10;
}
Which produces, compiled:
body{
margin: 10px;
}
Placeholders only produce CSS if they are used. Better, they'll concatenate all selectors using them, to avoid duplicate contents:
body {
#extend %m10;
background: red;
}
main > article {
#extend %m10;
}
Will outputs:
body, main > article {
margin: 10px;
}
body {
background: red;
}
The output you get is exactly what it's supposed to be.
If you don't want to have:
.m10{margin:10px;} /* <-- i dont want to see this in my compiled scss --> */
.p10{padding:10px;} /* <-- i dont want to see this in my compiled scss -->
*/
body{
margin: 10px; /* <-- but still extent from the .m10 class of _vars.scss -->
*/
}
You shouldn't use a class and an #extend but a mixin and an #include
Here is what you could do:
#mixin m10 {
margin: 10px;
}
body{
#include m10;
}
It would even be better to add a variable :
#mixin myMargin($size) {
margin: #{$size}px;
}
.input {
#include myMargin(10);
}
This way, you can choose your margin size.

Passing arguments from a mixin to a content block

This open issue in the Sass queue seems to imply passing arguments to #content is not a feature yet, but Susy 2 seems to be able to do this. Tracking down how it's done is a bit of a rabbit hole though and I haven't figured it out yet. Perhaps someone can shed some light with a straightforward example? I want to create a custom mixin that will inherit a layout passed from susy-breakpoint() using a custom map.
Example: Defining a 4 column layout in a global Sass map, will return a width of 100% when a span of 4 is specified inside susy-breakpoint()'s #content. When a custom layout of 8 cols is passed to directly tosusy-breakpoint() via the $layout argument, the nested span() mixin picks up the new layout. But a custom nested mixin will not pick up the new layout. Why?
#import 'susy';
$susy: (
columns: 4,
);
#mixin inherit-layout($layout: 4) {
columns: $layout;
}
#include susy-breakpoint(30em) {
// nested code uses an 4-column grid from global map
.global-cols {
#include span(4);
#include inherit-layout();
}
}
#include susy-breakpoint(48em, $layout: 8) {
// nested code uses an 8-column grid from $layout
.inherited-cols {
#include span(4);
#include inherit-layout();
}
}
Compiled CSS:
#media (min-width: 30em) {
.global-cols {
width: 100%;
float: left;
margin-left: 0;
margin-right: 0;
columns: 4;
}
}
#media (min-width: 48em) {
.inherited-cols {
width: 48.71795%;
float: left;
margin-right: 2.5641%;
columns: 4;
}
}
Update:
I've discovered that making the default variable for the inherit-value() mixin the value of columns key on the existing $susy map allows the mixin to grab context. But why? And why doesn't it work with a different map or outside of susy-breakpoint()?
See here: http://sassmeister.com/gist/d86e217aca3aa8337b83
Susy doesn't pass any arguments to the #content — instead, we change the global variable at the start of the content block, and then change it back at the end:
$example: 4;
#mixin local($local) {
$old: $example;
$example: $local !global;
#content
$example: $old !global;
}
// out here, $example == 4
#include local(12) {
// in here, $example == 12
}

Using parent classes [duplicate]

This question already has an answer here:
SASS Replicating nested selector
(1 answer)
Closed 7 years ago.
Ive tried searching for an answer, but I feel like I'm asking the wrong questions.
I'm trying to create a "base parent" class that I can use to split up my rules nicely and across multiple files. The structure of the parent would be something like this:
.parent {
.child {
//some rules here
}
I then want to be able to import that parent and child class to help define further elements (using faux-syntax here)
#[custom class name]:
.parent {
//some rules
.child {
color: #000
}
Then, using my custom class name, I can specify this as the parent of another selector, like:
#[custom class name] {
.grand-child {
background-color: #fff;
}
}
This would generate out the following rule
.parent .child .grand-child {
color: #000;
background-color: #fff;
}
One way of doing this could be to create a mixin that uses the #content directive, like so:
#mixin selectors {
.parent {
.child {
#content;
}
}
}
Then, any time you want to nest something under .parent .child, you would write:
#include selectors {
.grand-child {
color: #000;
}
}
Which would result in the following CSS output:
.parent .child .grand-child {
color: #000;
}
You could always make use of the & selector.
If .grand-child is in another file, you could do something like this:
.grand-child{
.parent .child & {
color: #000;
}
}
this will compile to
.parent .child .grand-child{
color: #000;
}
Or are maybe you are also looking for the #extend possibility?
where you would add
.grand-child{
#extend .parent .child;
color: #000
}
This would get the style from .parent .child and add it to the grand-child, but only the styling, it will not change the selector above.

How to use menu items using SASS [duplicate]

This question already has an answer here:
How do i get the same object with a class in SCSS?
(1 answer)
Closed 8 years ago.
I am creating menu items with their class name as l1, l2 respectively and want to provide different background colors to each item. To get desired background color for each item in CSS file I have to write my code like this:
.menu ul li.l1 {
background: red;
}
.menu ul li.l2 {
background: green;
}
in Sass i am trying to use nesting property and write my code like this:
.menu {
some properties
ul li {
some properties
.l1 {
background: red;
}
}
}
On writing above mentioned code I am getting following CSS as output:
.menu ul li .l1 {
background: red;
}
This is not setting my desired background.
Wow can I access my menu items using SASS?
Your .l1 is not declared properly.
.menu {
ul li {
&.l1 {
background: red;
}
}
}

Resources