SASS mixin : how to add class before? - css

I'm struggling with creating a mixin with sass and I can't seem to find a solution. If anyone has any ideas...
I have something like this:
.tata {
font-size: 12px;
.toto{
display: block;
.tutu {
text-align: left;
#include mixin_test{
background: red;
}
}
}
}
and I'd like to have something like this when compiled:
html .tata .toto .tutu {background:red}
I've tried this, but the result is not what I expected:
#mixin mixin_test {
html{
#content;
}
}
Does anyone have a solution?

You need to edit your mixin. Missing & after the selector:
#mixin mixin_test {
html & {
#content;
}
}
.tata {
font-size: 12px;
.toto{
display: block;
.tutu {
text-align: left;
#include mixin_test{
background: red;
}
}
}
}
On this page you can read more about parent selector: Parent Selector

Related

Merging selector #extend issue

I have a problem about "#extend" directive in SCSS.
.header {
.introduction-group {
text-align: center;
color: $white;
width: 70%;
}
.about {
&__description-group {
#extend .introduction-group;
This code block does not work. However,
.header {
&__introduction-group {
text-align: center;
color: $white;
width: 70%;
}
.about {
&__description-group {
#extend .header__introduction-group;
Second one works. Why?
Thank you.
As mentioned here nested classes won't be applied with #extend. Your second code block targets the specified class including the parent prefix. The first code block doesn't, it only targets the nested class.
I made a small codepen demo to illustrate the problem in a simple way. Make sure you checkout the Sass docs for a more comprehensive explanation!
<h1 class="wrong">Test style gone wrong</h1>
<h1 class="right">Test style gone right</h1>
.test {
.nested {
color: red;
}
&-nested {
color: red;
}
}
.wrong {
#extend .test;
#extend .nested;
}
.right {
#extend .test-nested;
}

LESS - using BEM selector with extra class on parent to deviate

I have some markup that looks about like this -
<div class="card">
<div class="card__icon">Icon</div>
<div class="card__text">Text</div>
</div>
Which I am styling with a little LESS like so -
.card {
&__icon {
font-size: 1.75em;
#media (min-width: 992px) {
font-size: 2em;
}
}
&__text {
font-size: 1em;
}
}
This works great - however the parent is getting toggled a class .current on it and I was trying to change one of the childrens styles using the same methods, but could not seem to get it working. I was trying this -
.card {
&__icon {
font-size: 1.75em;
#media (min-width: 992px) {
font-size: 2em;
}
}
&__text {
font-size: 1em;
}
&.current {
// this is not working
&__text {
color: red;
}
}
}
I can change the &__text inside the &.current to .card__text and it works fine - however I was wondering if there was a way I could keep the &__text syntax inside the &.current with using LESS. Thanks!
According to the documentation, the parent selector & expands to the whole parent nested rule, taking each nested rule parent as is and inserting it in place of `&, so in your case
.card {
&.current {
&__text {
color: red;
}
}
}
compiles to
.card.current__text {
color: red;
}
which is not what we want, because class current__text does not exist. To avoid that you may rearrange the class selectors in your less rules like so:
.card {
.current & {
&__text {
color: red;
}
}
}
which compiles to:
.current .card__text {
color: red;
}
A working example can be found in this codepen

Bootstrap classes inside a defined class

Is there a way to put made classes inside a class?
e.g.
.my-upper-class{ .hidden-md, .hidden-sm, .hidden-lg}
Not with plain CSS, but with Sass, like so—
.hidden-sm {
background: red;
}
.hidden-md {
color: blue;
}
.hidden-lg {
font-size: 1em;
}
.my-upper-class {
#extend .hidden-sm;
#extend .hidden-md;
#extend .hidden-lg;
}
which outputs the final CSS as below, which is pretty much what you are looking for.
.hidden-sm, .my-upper-class {
background: red;
}
.hidden-md, .my-upper-class {
color: blue;
}
.hidden-lg, .my-upper-class {
font-size: 1em;
}

SASS: content block mixin (or placeholder) that takes contextual selectors and appends them to selector in mixin

I want to do something like this:
#mixin context($size) {
body.#{$size} {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
& {
font-size: 5em;
}
}
}
}
To produce:
div span {
font-size: 2em;
}
body.large div span {
font-size: 5em;
}
What it ACTUALLY (predictably) produces:
div span {
font-size: 2em;
}
div span body.large {
font-size: 5em;
}
I could just replicate the selectors inside different mixins, but given that selectors could be complex that's a lot of extra junk:
#include context('large') {
div {
span {
font-size: 5em;
}
}
}
I could make the selectors into mixins so I don't have to repeat them each time, but...
Isn't there a way to use placeholders, maybe in combination with mixins, to get what I want in the first two code blocks above?
You just need to move the & to be part of the mixin:
#mixin context($size) {
body.#{$size} & {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
font-size: 5em;
}
}
}
Output:
div span {
font-size: 2em;
}
body.large div span {
font-size: 5em;
}
As of Sass 3.4, you can write this to work both inside a selector and at the root of the document:
#mixin optional-at-root-nest($sel) {
#at-root #{if(not &, $sel, selector-nest($sel, &))} {
#content;
}
}
#mixin context($size) {
#include optional-at-root-nest('body.#{$size}') {
#content
}
}
div {
span {
font-size: 2em;
#include context('large') {
font-size: 5em;
}
}
}
#include context('large') {
font-size: 2em;
}

SASS mixin for swapping images / floats on site language (change)

Currently using SASS on a website build. It is my first project using it, tried a little LESS before and liked it. I made a few basic mixins and variables with LESS, super useful stuff!
I am trying to get my head around SASS mixins, and syntax, specifically for swapping images when the page changes to a different language, be that with body ID changing or <html lang="en">. And, swapping floats around if, for example, a website changed to Chinese. So a mixin where float left is float left unless language is AR and then it becomes float right.
With LESS I think it would be something like:
.headerBg() when (#lang = en) {background-image:url(../img/hello.png);}
.headerBg() when (#lang = it) {background-image:url(../img/ciao.png);}
.header {.headerBg(); width: 200px; height:100px}
.floatleft() when (#lang = en) { float: left;}
.floatleft() when (#lang = ar) { float: right;}
.logo {.floatleft();}
It's the syntax I am having problems with.
I'd probably use the #content feature and do something like this:
#mixin headerBg {
.header {
#content
}
}
#mixin floatDir {
.logo {
#content
}
}
:lang(en) {
#include headerBg {
background-image:url(../img/hello.png);
}
#include floatDir {
float: left;
}
}
:lang(ar) {
#include headerBg {
background-image:url(../img/ciao.png);
}
#include floatDir {
float: right;
}
}
Which compiles to:
:lang(en) .header {
background-image: url(../img/hello.png); }
:lang(en) .logo {
float: left; }
:lang(ar) .header {
background-image: url(../img/ciao.png); }
:lang(ar) .logo {
float: right; }
If the background image names where based on the language, then it might make sense to use #each and do something like this:
#each $lang in en, ar {
:lang(#{$lang}) {
#if $lang == en {
.logo {
float: left;
}
} #else if $lang == ar {
.logo {
float: right;
}
}
.header {
background-image:url(../img/#{$lang}.png);
}
}
}
Which compiles to:
:lang(en) .logo {
float: left; }
:lang(en) .header {
background-image: url(../img/en.png); }
:lang(ar) .logo {
float: right; }
:lang(ar) .header {
background-image: url(../img/ar.png); }

Resources