Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to test for the current element type from within a SASS mixin?

Tags:

sass

I have a mixin that draws a button like this:

@mixin button {
  border: 1px solid $orange;
  background: $orange;
  padding:0;
  height:27px;
  text-transform: uppercase;
  color:white;
  display:block;
  // if I'm styling an a tag padding-top:10px 10px 0 10px;
}

I want to be able to do this:

button.my_button {
  @include button;
}

a.my_button {
  @include button;
}

The second one requires some additional custom code to work nicely. Is is possible to include a conditional in the mixin that checks to see if I'm styling an a tag, or do I need write a second mixin?

like image 268
superluminary Avatar asked Aug 15 '13 11:08

superluminary


Video Answer


3 Answers

Sass 3.3 and older

Within a mixin, no. If you're open to extends, you can get pretty close:

$orange: lighten(orange, 10%);

%button {
  border: 1px solid $orange;
  background: $orange;
  padding:0;
  height:27px;
  text-transform: uppercase;
  color:white;
  display:block;
}

a%button {
    padding-top:10px 10px 0 10px;
}

button.my_button {
  @extend %button;
}

a.my_button {
  @extend %button;
}

Compiles to:

button.my_button, a.my_button {
  border: 1px solid #ffb733;
  background: #ffb733;
  padding: 0;
  height: 27px;
  text-transform: uppercase;
  color: white;
  display: block;
}

a.my_button {
  padding-top: 10px 10px 0 10px;
}

Sass 3.4 and newer

Starting with 3.4 we have the ability to examine and manipulate the selector.

$orange: lighten(orange, 10%);

@mixin button {
  border: 1px solid $orange;
  background: $orange;
  padding:0;
  height:27px;
  text-transform: uppercase;
  color:white;
  display:block;

  @if is-superselector('a', &) {
    padding-top: 10px 10px 0 10px;
  }
}

button {
  @include button;
}

b a.foo {
  @include button;
}

Output:

button {
  border: 1px solid #ffb733;
  background: #ffb733;
  padding: 0;
  height: 27px;
  text-transform: uppercase;
  color: white;
  display: block;
}

b a.foo {
  border: 1px solid #ffb733;
  background: #ffb733;
  padding: 0;
  height: 27px;
  text-transform: uppercase;
  color: white;
  display: block;
  padding-top: 10px 10px 0 10px;
}
like image 173
cimmanon Avatar answered Sep 23 '22 01:09

cimmanon


As of this writing, there's no way to inspect the context / element type in a conditional. But you can set a default in your conditional, and thus simplify the default case of the mix-in.

Here's an example:

@mixin button($type: normal) { 

  border: 1px solid orange; background: orange; color: white; display: block;

    @if $type == anchor { padding: 10px 10px 0 10px; } 
    @else { padding: 0; }

}

button.my_button {
  @include button;
}

a.my_button {
  @include button($type: anchor);
}

See it in action at http://sassmeister.com/gist/6284603.

It looks like this functionality is (maybe) planned for Sass 3.3 with the @at-root directive: https://github.com/nex3/sass/issues/774.

like image 42
KatieK Avatar answered Sep 20 '22 01:09

KatieK


Why don't you use @content directive.

$orange: #000;
@mixin button {
    border: 1px solid $orange;
    background: $orange;
    padding: 0;
    height: 27px;
    text-transform: uppercase;
    color: white;
    display: block;
    @content;
}
button.my_button {
    @include button;
}

a.my_button {
    @include button {
       padding-top:10px 10px 0 10px;
    };
}

Using this approach you will keep your mixin untouched and you will still have the functionality that you want.

like image 22
Krasimir Avatar answered Sep 19 '22 01:09

Krasimir