Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Variables from one mixin to another in LESS CSS

I have been using less for a while, mainly for basic things to make my day in and day out chores a little easier. I was messing around with less today for fun and tried to do something that I havent before. I have found questions similar to mine just not exact enough where I have been able to come to an overall conclusion.

I have 3 divs total, a containing div with 2 children. I would like to assign the total width of the container, to the sizes of both children added together. I have tried quite a few different things that seem like they would work but they dont due to undefined variable errors, no matter how I try to pass them. I read on here that variables defined within a mixin stay private and I am assuming that is my problem, but I have seen others do something similar and make it work.

Anyways, here is a visual example of what I am trying to accomplish not an actual attempt.

.divOne {
    @widthOne: 20px;
    width: @widthOne;
}

.divTwo {
    @widthTwo: 50px;
    width: @widthTwo;
}

.containgDiv {
    width: @widthOne + @widthTwo;
}

If there is a question on here that relates directly to mine, I am sorry for posting this; I just couldn't find anything too clear cut. Thanks!

like image 532
user2554813 Avatar asked Jul 05 '13 19:07

user2554813


People also ask

How do you pass variables in mixin SCSS?

Variable argument is used to pass any number of arguments to mixin. It contains keyword arguments passed to the function or mixin. Keyword arguments passed to the mixin can be accessed using keywords($args) function which return values mapped to String.

What does @mixin do in SCSS?

The @mixin directive lets you create CSS code that is to be reused throughout the website.


1 Answers

Your issue is with the variable's scope. Your two variables are defined within the containing block of .divOne and .divTwo, which makes them locally scoped to those code blocks. To resolve that, you need to either make them more globally scoped (i.e. defined outside the containing block that is to use them, but not within another containing block), or scope them locally into the .containgDiv block.

Many Options (there are probably more)

Note, of the following options, #3 is the only one that directly matches your question title of "Passing variables from one mixin to another." However, the other ways of getting the variables are given to show the flexibility of what can be done, as well as making one aware of the decisions to be made about what is important for that accessibility.

1) Full Global Scope

Any code block can access it. This is commonly used in LESS.

@widthOne: 20px;
@widthTwo: 50px;

.divOne {
    width: @widthOne;
}

.divTwo {  
    width: @widthTwo;
}

.containgDiv {
    width: @widthOne + @widthTwo;
}

2) Namespaced Scope ("Global" within the larger code block)

Any code block within the namespace can access it directly, others indirectly (see how in #3). Note, this is essentially making a large, master mixin for those items sharing the variables. It keeps the variables hidden from the rest of the code.

#someNameSpaceName() {

    @widthOne: 20px;
    @widthTwo: 50px;

    .divOne {
        width: @widthOne;
    }

    .divTwo {  
        width: @widthTwo;
    }

    .containgDiv {
        width: @widthOne + @widthTwo;
    }
}

#someNameSpaceName();

3) Use a Nested, Local Access Mixin to Set the Variable

This allows you to set and use it in the local scope of one code block (and it is hidden from all others), but still able to be accessed in other scopes (through the namespace of the code block and the doorway of the nested mixin).

.divOne {
    .setWidth() {
    @widthOne: 20px;
    }
    .setWidth();
    width: @widthOne;
}

.divTwo {
    .setWidth() {
    @widthTwo: 50px;
    }
    .setWidth();
    width: @widthTwo;
}

.containgDiv {
    .divOne > .setWidth();
    .divTwo > .setWidth();
    width: @widthOne + @widthTwo;
}

4) Use a Globally Accessible Mixin to Set the Variables for All Locally

This allows you to set the variables in one place, and keep those variables hidden from the global scope, but use them in local scopes as needed.

.setWidths() {
  @widthOne: 20px;
  @widthTwo: 50px;
}

.divOne {
  .setWidths();
  width: @widthOne;
}

.divTwo {  
  .setWidths();
  width: @widthTwo;
}

.containgDiv {
  .setWidths();
  width: @widthOne + @widthTwo;
}

Output is All the Same

It does not matter which of the above techniques are used, they will all put out the following CSS.

.divOne {
  width: 20px;
}
.divTwo {
  width: 50px;
}
.containgDiv {
  width: 70px;
}
like image 53
ScottS Avatar answered Nov 15 '22 03:11

ScottS