Can I use psuedo elements as an argument to a scss mixin? - sass

I have a mixin that I'm referencing an "element" as the argument.
#mixin themeParent ($child) {
&--blue #{$child} {
color: getColour("theme", "bluehighlight");
}
&--green #{$child} {
color: getColour("theme", "greenhighlight");
}
&--purple #{$child} {
color: getColour("theme", "purplehighlight");
}
&--gossamer #{$child} {
color: getColour("theme", "gossamerhighlight");
}
&--black #{$child} {
color: getColour("theme", "black");
}
}
This works fine if I am referencing an a or a p for example
HTML
<div class="div--blue">
<a>blue link</a>
</div>
SCSS
div {
#include themeParent(a);
}
But I want also use the mixin for psuedo elements eg.
div {
#include themeParent(a:hover);
}
or
div {
#include themeParent(>a:hover);
}
div {
#include themeParent(&:first-child);
}
is this possible?
Why is what I'm doing making SCSS not happy :-(

You just need to put your argument in a string.
DEMO
#mixin themeParent($child) {
&--blue #{$child} {
color: blue;
}
}
.cool {
#include themeParent('a:hover');
#include themeParent('&:first-child');
}

Related

scss: check parent selector name in mixin

Is there a way to check what & refers in mixin?
body {
#import x
}
button {
#import x
}
Inside #mixin x() I want a special case when it's called with body as &.
You can check the value of & in your mixin using #if {} #else {}:
#mixin test {
$root: #{&};
$parentTagIsBody: $root == 'body';
#if $parentTagIsBody {
color: red;
} #else {
color: black;
}
}
button {
#include test;
}
body {
#include test;
}
will compile to:
button {
color: black;
}
body {
color: red;
}

If mixins in empty show default

Is it possible to have a mixin that can override a current code block? I want to have it so that if the #mixin is empty the background for the box would be empty and then show in orange, but when I remove the #mixin it does not change to orange? What am I doing wrong?
#mixin box {
background: red;
}
.box {
#if box {
#include box;
} #else {
background: orange;
}
}
The $color: null is just for setting a value if you didn't pass a value for your #mixin. after that you can check easily inside your #mixin using #if #else.
Sass
#mixin background-color($color: null) {
#if($color) {
background-color: $color;
} #else {
background-color: orange;
}
};
h1 {
#include background-color(red);
}
h2 {
#include background-color(green);
}
h3 {
#include background-color();
}
h4{
#include background-color(blue)
}
Html
<h1>color</h1>
<h2>color 2</h2>

Not last child mixin SASS

Is it possible to turn this:
.redstripe p:not(last-child) {
border-bottom:1px solid red;
}
Into a mixin so that I can apply it to any element and assign a child tag to it like:
#mixin redstripe (this.$children):not(last-child) {
border-bottom:1px solid red;
}
And then apply:
div {
#include redstripe(p);
}
What is the correct way to implement this?
Here's a general purpose mixin like you've described.
DEMO
#mixin not-last-child($selector) {
& #{$selector}:not(:last-child) {
#content;
}
}
We can pass it a selector string to use.
SCSS:
.thing {
#include not-last-child('p') {
color: red;
}
}
CSS:
.thing p:not(:last-child) {
color: red;
}
Sass Documentation

Finding if a string is in string in sass

I want an if statement to show if a string is inside another string in sass.
How do i do this in a mixin?
#mixin hello($mystring) {
}
You can use str-index to achieve this.
SCSS
#mixin hello($mystring) {
#if (str-index("Hello World", $mystring)) {
background-color: green;
}
#else {
background-color: blue;
}
}
.test {
#include hello("World");
}
CSS Output
.test {
background-color: green;
}

aggregation of selectors created by mixin possible?

I try to get a mixin "remebering" the selectors it was generating so I can make a bulk-selector at the end.
To illustrate what I am trying to do – My mixin looks like so:
#mixin fontcustom($name) {
#if $name == "heart" {
$glyph: '\2764'; // a special character in my own font -> ❤
}
#else if $name == "foo" { ... }
#else if $name == "bar" { ... }
#else if $name == "baz" { ... }
// ... much much more characters ...
&:before {
content:"#{$glyph}";
}
/* aggreagation of selectors ? */
}
#function selectorsUsingFontcustom() {
/* this should somehow result in a list of selectors, see above */
font-family: fontcustom;
color: red;
/* ... */
}
Obviously there are some more style declarations needed, for example font-family, colors and so on.
I want to avoid repetive declarations so my question is: is there a way to make the mixin "remember" the selectors which resulted in applying it and genarate a comma-separated list of them, which results in something like the following?
SCSS:
#my-fancy-selector [data-is-liked] {
#include fontcustom("heart");
}
.another>.fancy+.foo-selector {
#include fontcustom("foo");
}
.another>.fancy+.baz-selector {
#include fontcustom("baz");
}
/* no clue about the following: */
selectorsUsingFontcustom();
CSS:
#my-fancy-selector [data-is-liked]:before {
content:"\2764";
}
.another>.fancy+.foo-selector:before {
content:"\2765";
}
.another>.fancy+.baz-selector:before {
content:"\2767";
}
/* selectorsUsingFontcustom() should return sth like the following then: */
#my-fancy-selector [data-is-liked]:before,
.another>.fancy+.foo-selector:before,
.another>.fancy+.baz-selector:before {
font-family: fontcustom;
color: red;
/* ... */
}
Any ideas?
Use #extend with placeholder selectors like this:
%heart {
color: red;
}
h1 {
#extend %heart;
font-size: 3em;
}
h2 {
#extend %heart;
font-size: 2em;
}
li {
#extend %heart;
text-decoration: strikethrough;
}
Output:
h1, h2, li {
color: red;
}
h1 {
font-size: 3em;
}
h2 {
font-size: 2em;
}
li {
text-decoration: strikethrough;
}

Resources