csssassmixins

SASS Mixin with optional and variable parameters


Is there a way to use both optional and variable elements in a sass mixin?

i try

@mixin name($className,  $centered: false, $dimension...)

but the first dimension value is assigned to $centered

switching parameters order don't compile

@mixin name($className, $dimension..., $centered: false )

the error is:

SASSInvalid CSS after "..., $dimension...": expected ")", was ", $centered: fa..."

since the mixin without the optional parameter is used in many place (over 70) i dont want yo change it all to add the new parameters, so i want to leave it optional?

Any way to change this mixin or i have to leave the original without $centered and create an ovverride with the new parameter?

for info this is the mixin body:

    @for $i from 1 through length($dimension){                              
        @if($centered) {
            .#{$className}Td#{$i}, .#{$className}Th#{$i}  { 
                width: nth($dimension, $i); 
                text-align:center;
            }
        }
        @else{
            .#{$className}Td#{$i}, .#{$className}Th#{$i} {width: nth($dimension, $i); }
        }
    }

EDIT with complete cowking example:

simply iam defining css for column width of my table in a faster way, so this

@include nome("columnsName", 40%, 30%, 30%);

is rendered in that way:

.columnsNameTd1, .columnsNameTh1{width: 40%;}

.columnsNameTd2, .columnsNameTh2{ width: 30%; }

.columnsNameTd3, .columnsNameTh3{ width: 30%;}

i want a way to text-align center all my columns, maybe can be interesting see if there is a way do to specify what column to center, making all other left by default


Solution

  • You can't do what you're asking because variable arguments (the ... syntax) absolutely must be last. You have 2 options, I recommend option #2.

    Option 1 (examine the last element to see if it is a boolean):

    @mixin name($className, $dimension...) {
        $last: nth($dimension, length($dimension));
        $centered: if(type-of($last) == bool, $last, false);
        $length: if(type-of($last) == bool, length($dimension) - 1, length($dimension));
    
        @for $i from 1 through $length {
            .#{$className}Td#{$i}, .#{$className}Th#{$i} {
                width: nth($dimension, $i);
                @if($centered) {
                    text-align: center;
                }
            }
        }
    }
    

    Option 2 (use the @content directive):

    @mixin name($className, $dimension...) {
        @for $i from 1 through length($dimension) {
            .#{$className}Td#{$i}, .#{$className}Th#{$i} {
                width: nth($dimension, $i);
                @content;
            }
        }
    }
    
    // usage
    @include name(rar, 10%, 20%, 30%);
    
    @include name(rar, 10%, 20%, 30%) {
        text-align: center;
    }