SASS variables and inheritance

2019-02-15 14:42发布

Suppose I have two virtually identical HTML structures, but with different class names. They only differ by a few variables, like width and height. By using SASS/SCSS variables I thought I could do something like this:

.widget-a {
    $width: 50px;
}

.widget-b {
    $width: 100px;
}

.widget-a,
.widget-b {
    button {
        background: red;
        width: $width;
    }
}

This would let me write a single piece of SASS nested code for both widgets a and b. However, variables are only visible inside a nested scope, so SASS returns 'variable undefined' errors. Of course I could rewrite it by simply doing something like:

.widget-a,
.widget-b {
    button {
        background: red;
    }
}

.widget-a {
    button {
        width: 50px;
    }
}

.widget-b {
    button {
        width: 100px;
    }
}

But that seems pretty cumbersome. Is there any other method of making this work?

标签: css sass nested
4条回答
祖国的老花朵
2楼-- · 2019-02-15 14:52

Ran into the same problem, this is how I'm going to try to solve it... (this works)

@mixin foo($type:"default")
  .mClass
    $bg: inherit
    @if $type == "banana"
      $bg: yellow

    background: $bg

.firstClass
  @include foo
.secondClass
  @include foo("banana")
查看更多
孤傲高冷的网名
3楼-- · 2019-02-15 14:55

Variables in SASS are only scoped to the block they appear in. Your first .widget-a declaration and the one declaring both A and B are two separate scopes. You'll have to do something like this (assuming you need to use the widths more than once):

$wbackground: red;

.widget-a {
    $wawidth: 50px; /* widget A width */
    button {
        background: $wbackground;
        width: $wawidth;
    }
}

.widget-b {
    $wbwidth: 100px; /* widget B width */
    button {
        background: $wbackground;
        width: $wbwidth;
    }
}
查看更多
爷、活的狠高调
4楼-- · 2019-02-15 15:04

Your problem can be solved by using a mixin.

@mixin button($width){
  button{
    background:red;
    width:$width;
  }
}

.widget-a{ @include button(50px);  }

.widget-b{ @include button(100px); }
查看更多
Rolldiameter
5楼-- · 2019-02-15 15:07

I don't see the advantage of creating a mixin only for this specific situation, it is hardly useful on a couple of occasions, but it is just my opinion.

Anyway, I've created a mixin, just for fun. I think that it can help you to deal with this specific situation. Here is the mixin and I'm going to try to explain how it works:

@include button($selectors, $property, $values, $child: false) {
  // Common properties that are included in all $selectors  
}

This mixin takes four parameters:

  • $selectors: List of selectors, in your case, .widget-a and .widget-b, they should be enclosed in quotes.

  • $property: Here you should enter the name of the property, in your case width

  • $values: Values ​​are, as the name implies , the values of the property for each selector

  • $child: Here you can enter the name of a child, this is optional.

  • Into the brackets {} you should write all the properties that you want to include in all $parameters

  • The order of each selector must match the order of their corresponding value

So, here's an example using this mixin to solve your problem. This is the @include:

@include (".widget-a" ".widget-b", width, 50px 100px, button) {
  background: red;
}

And this, the code that returns:

.widget-a button, .widget-b button {
  background: red; }

.widget-a button {
  width: 50px; }

.widget-b button {
  width: 100px; }

This is another way to achieve the same result:

@include button(".widget-a .button" ".widget-b .button", width, 50px 100px)  {
  background: red;
}

Download the mixin here

查看更多
登录 后发表回答