sass include mixin as a parameter - sass

I want to parametrize sass mixins to the extend that other mixins are passed as a parameters by name expanded inside it.
#mixin c(){color:red}
#mixin view($param){*{#include #{$param}}}
div{#include view}
The 2nd line and variations of it ive tried do not work and I haven't found any way to pass variables into the #include clause

You can try to add some conditions inside mixin:
#mixin test1(){
color: red;
}
#mixin test2(){
color: blue;
}
#mixin view($param){
.test{
#if $param == 'test1'{
#include test1();
}
#if $param == 'test2'{
#include test2();
}
}
}
div{
#include view(test1);
}

Related

Sass: Declarations may only be used within style rules

I am getting a sass error: Declarations may only be used within style rules.
╷
32 │ #{$property}: $value;
│ ^^^^^^^^^^^^^^^^^^^^
for the following file:
#mixin theme($colour, $texture: null) {
$theme: map-get-strict($themes, $colour, "theme");
#if ($texture) {
#include getTexture($texture);
}
#each $property, $value in $theme {
#{$property}: $value;
}
}
This is using dart-sass.
I think it might be a Sass test file that is causing the issue, e.g.:
#include it('outputs the light-blue theme') {
#include assert {
#include output {
#include theme(light-blue);
}
#include expect {
background-color: getColour(light-blue);
color: getColour(black);
}
}
}
Declarations may only be used within style rules.
You can only use declarations within style rules. This means if you have a mixin which contains declarations
E.g.:
#mixin foo() {
color: #000;
}
you can only include it within a style rule.
E.g.:
.bar {
#include foo();
}
This helps to ensure that the compiled CSS is free of errors.
color: #000;
.bar {
color: #000;
}

how to use variable for #include name inide #each loop SCSS

I want to replace this SCSS code with #each usage.
body{
#include us(){
#include define-breakpoint("us")
}
#include xs(){
#include define-breakpoint("xs")
}
#include sm(){
#include define-breakpoint("xs")
}
#include md(){
#include define-breakpoint("md")
}
#include lg(){
#include define-breakpoint("lg")
}
#include xl(){
#include define-breakpoint("xl")
}
}
When I use #each function compiler throws out an error - invalid css with #include #{$bp}(){...}
$list: us xs sm md lg xl;
#each $bp in $list{
body{
#include #{$bp}(){
#include define-breakpoint("#{$bp}")
}
}
}
Does everybody know how to handle this error?
Appreciate any help
The problem with this code is that interpolation can't be used to convert a variable to an identifier. The Sass compiler won't allow it. At the point where you interpolate $bp, the compiler expects an identifier. It will treat anything at that point as an identifier and not something that should be interpolated.
From your code it appears you've defined several mixins with #content passed within the block like so
#mixin us() { #content; }
#mixin sm() ( #contnet; }
which is why they are called like so
#include us(){
#include define-breakpoint("us");
}
You could refactor your code to make use of only one mixin since the only thing that's actually changing is the code in the block.
$list: us xs sm md lg xl;
#mixin screen-size() { #content; }
body {
#each $size in $list {
#include screen-size() {
#include define-breakpoint($size);
}
}
}
Another option would be to define the mixin to take a parameter instead and have the code within that block include the define-breakpoint mixin passing the parameter as an argument.
$list: us xs sm md lg xl;
#mixin screen-size($size) {
#include define-breakpoint($size);
}
body {
#each $size in $list {
#include screen-size($size);
}
}
UPDATED ANSWER
To achieve the added functionality specified in your code you can make the following adjustments to the previous answer
//list now takes media query also
$list: 'us' '(max-width: 519px)',
'xs' '(min-width: 520px) and (max-width: 767px)',
'sm' '(max-width: 768px)',
'md' '(min-width: 769px)',
'lg' '(min-width: 519px) and (max-width: 960px)',
'xl' '(min-width: 961px)';
//mixin takes media query as argument
#mixin screen-size($query) {
#media #{$query} {
#content;
}
}
body {
#each $map in $list {
#include screen-size( nth($map, 2) ) {
#include define-breakpoint( nth($map,1) );
}
}
}
Hope this solves your problem

call sass mixins from sass functions

I have a sass mixin that generates the selector name:
#mixin rocks($name){
#{$name}-rocks {
#content;
}
}
called by invoking the mixin:
#include rocks(dave){
color: red;
}
I'd like to create a custom function that calls this mixin for me, to shorten the syntax down to:
rocks(dave){
color: red;
}
Is it possible to 1. call sass #functions outside of a selector? and 2. Invoke mixins from it? Something along the lines of:
#function rocks($name){
#include #rocks($name)
}
I'd prefer custom sass functions over custom ruby functions if possible. Thanks!
No, and no. Functions in Sass can only return values, they cannot be used to create CSS. That is what mixins are for: create mixins to call other mixins.
#function class($name) {
#return $name;
}
#mixin className($classname) {
.#{class($classname)} {
#content;
}
}
#mixin concatinate($classname2) {
&.#{class($classname2)} {
#content;
}
}
#mixin parent($classname1) {
.#{class($classname1)} & {
#content;
}
}
#mixin withparent($classname1) {
#at-root .#{class($classname1)}#{&} {
#content;
}
}
#include className(red) {
color: red;
#include className(check) {
color: green;
#include concatinate(bcd) {
color: green2;
ul {
li {
color: red;
& {
color: blue;
}
#include withparent(colorwe) {
display: none;
}
}
}
#include parent(efg) {
color: green1;
}
}
}
#include className(blue) {
color: blue;
}
}
#DonaldDuck thanks for the feedback. Personally I think that there is no need to call selectors through mixins, if someone try to do that it will be solved by these mixins used.
e.g.:
//call a class
#include className(one) {
properties..
}//o/p .one { properties..}
//add another class with existing one
#include className(one) {
#include concatinate(two) {
#include className(three) {
properties...
}
}
}//o/p .one.two .three { properties...}
//add parent to hierarchy
#include className(one) {
#include parent(two) {
properties..
}
}//o/p .two .one { properties..}
//add class with top of the hierarchy
#include className(one) {
#include className(two) {
#include withparent(three) {
properties...
}
}
} o/p .one.three .two { properties..}

Is there a way to use an argument in a mixin to generate a variable name within the mixin with SASS? [duplicate]

This question already has answers here:
Creating or referencing variables dynamically in Sass
(7 answers)
Closed 7 years ago.
Regarding the question, here's an example of what I'm trying to do but I have a feeling that interpolation with SASS doesn't work in outputting variable within a mixin using an argument.
$red: #f00;
#mixin color-accent-class($color) {
.#{$color}-accent {
color: $#{$color};
}
}
#include color-accent-class(red);
Ultimately I'm trying to make the repetitive code below DRY so I'm not repeating myself all sloppy style and I'm wondering if it should be done with #function and/or #each or some other looping action with SASS. Thanks in advance for any guidance!
$blue: #2a62a7;
$red: #db0042;
$purple: #5b3b9f;
$orange: #f7911a;
$light-blue: #46aeed;
$green: #49b842;
#mixin product-accent($color-name, $hexval) {
.product-accent-#{$color-name} {
img {
border: {
left: {
style: solid;
width: 10px;
color: $hexval;
}
}
}
h3, b {
color: $hexval;
}
.button {
#extend .button.#{$color-name};
}
}
}
#include product-accent(black, #000);
#include product-accent(blue, $blue);
#include product-accent(red, $red);
#include product-accent(purple, $purple);
#include product-accent(orange, $orange);
#include product-accent(light-blue, $light-blue);
#include product-accent(green, $green);
Big thanks to #martin-turjak for help with this. Using SASS lists, nth() and a #for loop is what did the trick. Please chime in if there's a cleaner way to do this.
$color-names: black, blue, red, purple, orange, light-blue, green;
$color-hexvals: #000, $blue, $red, $purple, $orange, $light-blue, $green;
#for $i from 1 through length($color-names) {
#include product-accent(nth($color-names, $i), nth($color-hexvals, $i));
}

Sass Interpolation of Mixin, Function, and Variable names

I'm trying to loop through a list of values in Sass and use interpolation of the current key to dynamically output class names that utilize #include and #extend, respectively.
Here is a pen showing the problem, simplified. http://codepen.io/ghepting/pen/vBmLy
As you can see in the markup, I have tried including the "_" inside of the interpolated string as well as outside of it. Is there something I'm missing to work around this limitation of how Sass supports interpolation?
(Note: the OP's pen has disappeared. This is not the original code found in the pen, but a rough approximation of the problem)
$error-light: red;
$error-dark: darken(red, 10%);
$success-light: green;
$success-dark: darken(green, 10%);
$dialogs: error, success;
#each $d in $dialogs {
.#{$d} {
background: $#{$d}-light;
}
}
Interpolation doesn't work on mixins or variables at this point in time. You'll have to come up with a different way to achieve your goal.
As of Sass 3.3, you can use mappings for this purpose for variables:
$dialogs:
( error:
( light: red
, dark: darken(red, 10%)
)
, success:
( light: green
, dark: darken(green, 10%)
)
);
#each $name, $colors in $dialogs {
.#{$name} {
color: map-get($colors, dark);
}
}
And for functions:
#function green() {
#return lighten(green, 10%);
}
#function red() {
#return lighten(red, 10%);
}
#mixin my-bg($function-name) {
background: call($function-name);
}
.foo {
#include my-bg('red');
}
Alternative workaround (for a particular use case):
https://sass-lang.com/documentation/at-rules/mixin#passing-arbitrary-arguments
💡 Fun fact:
Because an argument list keeps track of both positional and keyword arguments, you use it to pass both at once to another mixin. That makes it super easy to define an alias for a mixin!
If you are interested in mixin interpolation because you have a group of mixins, like this:
//_mixins.scss
#mixin text-style-1($args...){ //sass here }
#mixin text-style-2($args...){ //sass here }
#mixin text-style-3($args...){ //sass here }
//_text.scss
.text-style-1 {
#include text-style-1;
}
.text-style-1-contrast {
#include text-style-1($contrast: true);
}
.text-style-2 {
#include text-style-2;
}
.text-style-2-contrast {
#include text-style-2($contrast: true);
}
We can take advantage of passing arbitrary arguments and use an alias for the group:
//_mixins.scss
#mixin text-style-1($args...){ //sass here }
#mixin text-style-2($args...){ //sass here }
#mixin text-style-3($args...){ //sass here }
#mixin text($mixin, $args...) {
#if $mixin == 'style-1' { #include text-style-1($args...); }
#else if $mixin == 'style-2' { #include text-style-2($args...); }
#else if $mixin == 'style-3' { #include text-style-3($args...); }
}
//_text.scss
$text-styles: 'style-1', 'style-2', 'style-3';
#each $style in $text-styles {
.text-#{$style} {
#include text($style);
}
.text-#{$style}-contrast {
#include text($style, $contrast: true);
}
}
Ran into this issue of trying to include an interpolated variable inside a mixin and was able to resolve it with placeholders:
%color-scheme-dark-bg-1 { background-color: #4e5163; }
%color-scheme-dark-color-1 { color: #4e5163 !important; }
%color-scheme-light-bg-1 { background-color: #c7c8ce; }
%color-scheme-dark-bg-2 { background-color: #fd6839; }
%color-scheme-dark-color-2 { color: #fd6839 !important; }
%color-scheme-light-bg-2 { background-color: #fecfc1; }
.card_color {
#mixin CardColorScheme($arg: 1) {
.borderPercent {
#extend %color-scheme-dark-bg-#{$arg};
}
.border {
#extend %color-scheme-light-bg-#{$arg};
}
ul li:before {
#extend %color-scheme-dark-color-#{$arg};
}
.percent {
#extend %color-scheme-dark-color-#{$arg};
}
.heading {
#extend %color-scheme-dark-color-#{$arg};
}
}
&--scheme {
&-1 {
#include CardColorScheme(1);
}
&-2 {
#include CardColorScheme(2);
}
}
}
Hat tip to: https://krasimirtsonev.com/blog/article/SASS-interpolation-in-a-name-of-variable-nest-variables-within-variables

Resources