SASS nesting multiple classes in one element - sass

Let's say I have this HTML code:
<div class="parent">
<div class="parent__son parent__son--red"></div>
<div class="parent__son parent__son--yellow"></div>
<div class="parent__son parent__son--red parent__son--yellow" ></div>
</div>
Parent has 3 sons - first with 'red', second with 'yellow', third with both.
Now I want to do this nesting SCSS:
.parent {
width: 100%;
&__son {
width: 20%;
&--red {
background: red;
}
&--yellow {
background: yellow;
}
}
}
Now I want that son that has both red and yellow will has background orange.
How can I write this in SASS?

A little bit of Sass Ampersand magic will get you there.
The interpolation brackets #{ } are needed as two touching ampersands
are invalid Sass
.parent {
width: 100%;
&__son {
width: 20%;
&--red {
background: red;
}
&--yellow {
background: yellow;
}
&--yellow#{&}--red {
background: orange;
}
}
}
[Live Example][https://codepen.io/anon/pen/LMazWK]

Related

sass / scss - create class shortcuts

While doing some css I came up with the idea of combining multiple classes into one. The reason is, to use short class names which could probably already be in use.
Assume the following:
.f-box-cell {
flex : 1 1 auto;
// colors
&.red { background-color: red; }
&.green { background-color: green; }
...
// sizes
&.b25 { flex-basis: 25%; }
&.b50 { flex-basis: 50%; }
...
// other options
...
}
Instead of doing ...
<div class="f-box-cell">
<div class="f-box-cell red">
<div class="f-box-cell b25">
<div class="f-box-cell red b25">
... I want do have something like ...
<div class="f-box-cell">
<div class="f-box-cell-red">
<div class="f-box-cell-b25">
<div class="f-box-cell-red-b25">
... with the same effect as the normal class listings.
Obviously, the more "subclasses" are added the more combinations would exist. So I'm interessted - if possible - in creating all these combinations automatically. Completely awesome would be, if the position of the "classes" inside the "combined class" would not matter.
Therefore my 2 main questions are:
Is there a way to achieve something like this with sass / scss?
Is the idea completely stupid?
Thanks in advance
If you only want to have all your classes prefixed and don't mind adding two classes (class="f-box-cell f-box-cell-red"), then you can just use the ampersand multiple times:
.f-box-cell {
flex : 1 1 auto;
// colors
& &-red { background-color: red; }
& &-green { background-color: green; }
...
// sizes
& &-b25 { flex-basis: 25%; }
& &-b50 { flex-basis: 50%; }
...
// other options
...
}
If you only want to use the most specific class, which should inherit from the base one, you can use the #extend rule:
.f-box-cell {
flex : 1 1 auto;
// colors
&-red { #extend .f-box-cell; background-color: red; }
&-green { #extend .f-box-cell; background-color: green; }
...
// sizes
&-b25 { #extend .f-box-cell; flex-basis: 25%; }
&-b50 { #extend .f-box-cell; flex-basis: 50%; }
...
// other options
...
}
Which compiles to:
.f-box-cell,
.f-box-cell-b50,
.f-box-cell-b25,
.f-box-cell-green,
.f-box-cell-red {
flex: 1 1 auto;
}
.f-box-cell-red {
background-color: red;
}
.f-box-cell-green {
background-color: green;
}
.f-box-cell-b25 {
flex-basis: 25%;
}
.f-box-cell-b50 {
flex-basis: 50%;
}

SASS target :before tag if another class is present

I'm trying to modify a ::before tag that contains another class.
HTML
<div class="foo active">
<div>...</div>
</div>
SCSS
.foo {
&:before {
content: "";
border-top: 3px solid $grey;
width: 50%;
transform: translateY(-10px);
&:first-child {
border-top: none;
}
&.active { // attempt 1
border: 3px solid $primary;
}
}
&:before.active { // attempt 2
border: 3px solid $primary;
}
}
I'm trying to modify the :before top border only if the active class is present. What else can I try?

Is it possible to determine number of children of any container using any SASS function?

Is it possible to determine number of children of any container using any SASS function?
For example, I have a container which has 3 columns:
<div class="columns columns_3">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
For this container, I want to implement a mixin which is +columns_3
But if the container has nth number of children, mixin will be +columns_n
What you want is to know how many childs haves an element and set the right class to it.
You need Javascript to detect the number of childs, HTML and CSS.
SCSS
.element {
$width: 100%;
width: $width;
div {
height: 100px;
float: left;
border:1px solid #000;
box-sizing: border-box;
}
#for $i from 1 through 12 {
&--#{$i} div {
width: $width/$i;
}
}
}
var element = document.getElementsByClassName('element')[0];
var childs = element.childElementCount;
element.classList.add("element--"+childs);
.element {
width: 100%;
}
.element div {
height: 100px;
float: left;
border: 1px solid #000;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.element--4 div {
width: 25%;
}
<div class="element">
<!-- childs -->
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Well if you have a range, you could potentially use a for loop - depending what you need to do. For example:
$gridWidth = 100%;
#for $numItems from 1 through 12 {
.columns_#{$numItems} {
.column {
width: $gridWidth / $numItems;
}
}
}
I think you can make this :
#function number(val) { #return val };
#mixins +columns_#{number(10)} {
// Your code;
}
I'm not sure I understand what you explain.

Bubble up rules in SASS for variation / theme classes

How does one handle making "variation classes" in Sass? Example:
.bookshelf {
color: brown;
height: 100px;
.panel {
trimmed: no;
height: 10px;
}
.door {
height: 100px;
.knob {
shape: circle;
height: 10px;
}
}
}
You want to make a .bookshelf.small variation. Is there a way to write the variation code inside the main element using mixins or something that would "bubble up" the data?
.bookshelf {
color: brown;
height: 100px;
#include small-version {
height: 50px;
}
.panel {
trimmed: no;
height: 10px;
#include small-version {
height: 5px;
}
}
.door {
height: 100px;
#include small-version {
height: 50px;
}
.knob {
shape: circle;
height: 10px;
#include small-version {
height: 5px;
}
}
}
}
And the output of the mixin would be
.bookshelf.small {
height: 50px;
.panel {
height: 5px;
}
.door {
height: 50px;
.knob {
height: 5px;
}
}
Several things looked promising, such as the #at-root function and #content function, but neither would work for this scenario. I know if I write #media settings, they will bubble up. But I do not want this tied to a media query, I want this tied to a specific class (if .bookshelf also has the class small, apply these rules).
There is a small hack about it. But you should work with it really carefully. And it's not so good as you ask.
First of all, it prepends theme class to selector, so you can't use any element selectors. There is actually lot of selector helpers in docs but i didn't found any that could help with real parsing selector string.
Second it's not grouping out selectors. It inserts rules right where mixin were included. But it generates higher priority rules for your styles, so it could be a half a way solution.
You can dig for postcss parser or any other file post processing tool that could help you to separate your styles in a different files.
#mixin small-version {
#at-root .small#{&} {
#content;
}
}
.bookshelf {
color: brown;
height: 100px;
#include small-version {
height: 60px;
}
.panel {
trimmed: no;
height: 10px;
#include small-version {
height: 5px;
}
}
.door {
height: 100px;
.knob {
shape: circle;
height: 10px;
}
}
}
Gist link
You can qualify a selector by putting & to the right of the intended parent of the selector. Wrapping it in #{} allows you to place it directly beside that parent.
The #at-root rule causes everything proceeding it to be emitted at the root instead of using regular nesting.
If you use both, you can achieve what you are looking for.
.flashlight {
.light {
background: yellow;
#at-root .dead-battery#{&} {
background: transparent;
}
.daytime &{
background: transparent;
}
}
}
This would compile to:
.flashlight .light {
background: yellow;
}
.dead-battery.flashlight .light {
background: transparent;
}
.daytime .flashlight .light {
background: transparent;
}

Issue mixing variable with mixin with keyframe animation?

First time using SCSS, and testing my knowledge from the Sass-Lang.com guide. According to the guide, it is possible to both set variables and use mixins to simplify your CSS.
I was coding an animation where the div is clipped from bottom to top. I used variables to set the initial and final clip-path settings, and used them while calling a mixin. Yet I get the error, 'Invalid CSS after "...slider-initial)": expected "{", was "; }"'. What am I doing wrong?
Here is my code:
<body>
<section id='main'>
<div id='left'></div>
<div id='right'></div>
<section>
</body>
$slider-initial: inset(0 0 0 0);
$slider-final: inset(0 0 100% 0);
#mixin slider-clip($slider-state) {
-webkit-clip-path: $slider-state;
clip-path: $slider-state;
}
body {
height: 100%; width: 100%;
margin: 0 auto;
}
#main {
height: 64vh; width: 38vw;
margin: 0 auto;
margin-top: 10%;
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
border: 1vh solid black;
}
#left {
order: 1;
width: 4%;
height: 100%;
margin-left: 46%;
background: green;
}
#right {
opacity: 1;
order: 2;
width: 4%;
height: 100%;
margin: auto;
margin-left: 0;
animation-name: dropdown;
animation-duration: 4s;
background: red;
}
#keyframes dropdown {
from { #mixin slider-clip($slider-initial); }
to { #mixin slider-clip($slider-final); }
}
You called your mixin in a wrong way:
#keyframes dropdown {
from { #mixin slider-clip($slider-initial); }
to { #mixin slider-clip($slider-final); }
}
In the guide on sass-lang.com, you can see the following example of how to include a mixin:
.box { #include border-radius(10px); }
Applied to your case, your code should look like this:
#keyframes dropdown {
from { #include slider-clip($slider-inital); }
to { #include slider-clip($slider-final); }
}

Resources