SASS mixin that applies some rules when we call it - css

I would like to create a SASS/LESS mixin that asks if a variable is equal to some value then apply some CSS rules.
#mixin myTest($myVar: $num) {
#if ($myVar == $num) {
/* Apply rules if $myVar is set $num - I DO NOT KNOW WHAT SHOULD BE THERE */
} #else {
/* Do nothing */
}
}
And then I would like to use my mixin this way:
$num: 1;
#include myTest(1) {
h1 {
color: blue;
background: red;
}
}
#include myTest(2) {
h1 {
color: yellow;
background: green;
}
}
So that only the rules inside parentheses of #include myTest(1) { ... } are applied.
The problem is I dont know how to do that.

myTest checks the value of $myVar variable and applies passed css rules via #content - see documentation.
#mixin myTest($myVar: $num) {
#if ($myVar= $num) {
#content;
}
}
$num: 1;
#include myTest(1) {
h1 {
color: blue;
background: red;
}
}
#include myTest(2) {
h1 {
color: yellow;
background: green;
}
}

You neeed to use #content inyour mixin to get every thing that was in your mixin to be pushed through
$num: 1;
#mixin myTest($myVar: $num) {
#if ($myVar == $num) {
/* Apply rules if $myVar is set $num - I DO NOT KNOW WHAT SHOULD BE THERE */
#content; // this is how you get it in here
} #else {
/* Do nothing */
}
}
#include myTest(1) {
h1 {
background:red;
}
}
#include myTest(2) {
h1 {
background:blue;
}
}
https://codepen.io/anon/pen/YEJKRm
hopes this helps

I'm not quite sure I've understood your question fully, but it seems like what you need to do is move your CSS rules inside your mixin:
#mixin myTest($num) {
#if $num === 1 {
color: blue;
background: red;
} #else {
color: yellow;
background: green;
}
}
$num: 1;
h1 {
#include myTest($num);
}

Related

Is there such a thing as an optional &?

Consider the following code:
#mixin bar() {
#if & {
&.bar {
display: none;
}
} #else {
.bar {
display: none;
}
}
}
#include bar();
.foo {
#include bar();
}
...which compiles to:
.bar {
display: none;
}
.foo.bar {
display: none;
}
Is there a way to write this mixin without duplicating the .bar block?
You can consider it as an argument with a default value that you can easily change:
#mixin bar($c:'.bar') {
#if & {
&#{$c} {
display: none;
}
} #else {
#{$c} {
display: none;
}
}
}

How can I pass a tag in as a scss mixin argument?

I am creating a mixin to target a child element.
Example.
Targeting all <a> tags of the parent that has a parent of section---blue
I figure that I can pass the tag as an argument as follows
But I am not getting the desired result
SCSS
#mixin themeParent ($child) {
&--blue $child {
color: getColour("theme", "bluehighlight");
}
&--green $child {
color: getColour("theme", "greenhighlight");
}
&--purple $child {
color: getColour("theme", "purplehighlight");
}
}
.section {
#include themeParent(a);
}
I would have thought that this would compile to
.section--blue a {
color: blue;
}
Can someone please explain to me why?
#mixin themeParent ($child) {
&--blue #{$child} {
color: blue;
}
}
outputs: .section--blue a { color: blue; }
If you want more specificity, just add another &:
#mixin themeParent ($child) {
&#{&}--blue #{$child} {
color: blue;
}
}
outputs: .section.section--blue a { color: blue; }
If you want more scability, just iterate over colors you want:
#mixin themeParent ($child) {
$colors: red, blue, green;
#each $color in $colors {
&#{&}--#{$color} #{$child} {
color: $color;
}
}
}
Put $child in #{$child}.
#mixin themeParent ($child) {
#{$child} {
color: #000;
}
}
.section {
#include themeParent(a)
}
Output:
.section a {
color: #000;
}
If I put this in a simple way, there is no need to pass the tag as a parameter to the mixin function instead, u should pass the color of the element.
<div className="section--blue">
<a>section blue</a>
</div>
<div className="section-green">
<a>section green</a>
</div>
mixin and css
#mixin themeParent ($color) {
color:$color;
}
.section{
&--blue {
a{
#include themeParent(blue);
}
}
--green{
a{
#include themeParent(green);
}
}
}
Hope this is useful.

Conditional SASS Variables using mixin's

I am currently using this mixin:
#mixin isMobile() {
html[data-browser*="Mobile"] & {
#content;
}
}
And I want to use this mixin to conditionally apply to a variable, like below:
$div-height: 20px;
#include isMobile() {
$div-height: 10px;
}
I know this is not the proper way of doing it, and I've also tried the following below with no success. How can I properly try this conditional? Thanks!
#if (html[data-browser*="Mobile"]) {
$div-height: 20px;
} #else {
$div-height: 10px;
};
The conditional part has to be in the mixin itself.
#mixin isMobile($type) {
$div-height: 0;
html[data-browser*="Mobile"] {
#if($type == 'A'){
$div-height: 20px;
}
#else{
$div-height: 10px;
}
height: $div-height;
#content;
}
}
#include isMobile('B'){
color:black;
}
/*Output*/
html[data-browser*="Mobile"] {
height: 10px;
color: black;
}

Does sass support to use parent selector as follows?

Problem
I mainly use the following methods. (SASS)
.person {
&.man {
.head { A }
}
&.woman {
.head { B }
}
.head { C }
}
But I want to use the following method. (SASS)
.person {
.head {
C
<parent_selector.man> {
A
}
<parent_selector.woman> {
B
}
}
}
compiled result (CSS)
.person .head { C }
.person.man .head { A }
.person.woman .head { B }
I want to know if there is such a function. Thank you.
My result
I got the idea from #falsarella's #at-root approach. It seems a bit crude, but this is also possible. (I actually used deeper selectors than the example, so it was hard to solve with at-root and #{$} alone.)
.person {
$person: &;
.head {
C
#at-root #{$person}.man .head {
A
}
#at-root #{$person}.woman .head {
B
}
}
}
Or it would be more convenient and readable(If the parent selector is not a simple selector.) to use it by naming $parent and overriding the previous $parent.
When I think about it once, the current selector is named $parent, so it is confusing. It might be better to ignore '>', ':after', ... of a parent selector and just name it as $person. (or create naming conventions.)
.earth {
$parent: &;
.person {
$parent: &;
.head {
C
#at-root #{$parent}.man .head {
A
}
#at-root #{$parent}.woman .head {
B
}
}
}
}
As a result of further Googling, postcss seems to support parent selectors I want.
There's no "parent" selector in Sass, but, in your case, you can use a tricky #{&} interpolation together with #at-root, like this:
.person {
.head {
color: white;
#at-root .man#{&} {
color: blue;
}
#at-root .woman#{&} {
color: pink;
}
}
}
Resulting in the following CSS:
.person .head {
color: white;
}
.man.person .head {
color: blue;
}
.woman.person .head {
color: pink;
}
Unfortunately, not. I think the first example that you give is the best way to achieve this. Another option might be:
.head {
.person & {
color: red;
}
.person.man & {
color: blue;
}
.person.woman & {
color: green;
}
}
It will produce the same compiled result as you desire. But beware of nesting the .head class. It will trip you up.
The following does not really uses a parent selector. Just uses a SASS #mixin to give same CSS output.
#mixin personHead($gender) {
#if $gender == man {
&.man .head{
property: A;
}
}
#if $gender == woman {
&.woman .head{
property: B;
}
}
#if $gender == "" {
.head{
property: C;
}
}
}
.person { #include personHead(man); }
.person { #include personHead(woman); }
.person { #include personHead(""); }
/* Compiled CSS Output */
.person.man .head {
property: A;
}
.person.woman .head {
property: B;
}
.person .head {
property: C;
}

Sass #extend base/default without also extending pseudo-classes?

I know I can #extend .foo:hover, but is there a way to #extend the .foobar base/default properties without also extending the definitions for pseudo-classes like :hover, :active, etc?
For example, how would I change the following such that .foobar extends only .foo's default state?
.foo {
& {
color:blue;
}
&:hover {
background-color: black;
}
}
.foobar {
#extend .foo;
&:hover {
//As is, I have to override. Any better way?
background-color: transparent;
}
}
(If there is no way to do this with Sass, is there a preferred way to achieve the same effect?)
You have to rewrite your selectors in such a way that you only extend exactly the part you want:
%foo {
color:blue;
}
.foo {
#extend %foo;
&:hover {
background-color: black;
}
}
.foobar {
#extend %foo;
&:hover {
background-color: transparent;
}
}
However, depending on how you are going to be extending/reusing your .foo class, the new #content directive might be the better way to go.
#mixin foo {
color: blue;
&:hover {
#content;
}
}
.foo {
#include foo {
background-color: black;
}
}
.foobar {
#include foo {
background-color: transparent;
}
}

Resources