Zum Inhalt springen

Posts:

Reset properties and values from a scss mixin

How do you 'unset' changes that a mixin has introduced to an element?


In a recent project I had the need to reverse the effects a mixin has introduced before.

For example, the design wants all heading elements displayed in uppercase letters, and uppercase often needs some tiny adjustment of letter-spacing for better readability and looks, so I created a small mixin, "versal":

  /* in tools/_mixins.scss */
  @mixin versal($spacing:0.03em) {
    text-transform: uppercase;
    letter-spacing: $spacing;
  }

This can be used where uppercase text should be displayed, for example in the '_basics.scss' rules, as a default for heading elements and heading classes:

  /* in _basics.scss */
  ...
  h1,h2,h3,h4,h5,h6,[class$="heading"] {
    @include versal();
  }

Now somewhere in the layout of the site, a normal, mixed-case heading element should be displayed, lets say a heading in an address block in the footer. So in the '_footer.scss' maybe this rule is used:

  /* in components/_footer.scss */
  ...
  .footer-block-heading {
    padding: 0.5em;
    text-transform: none;
    letter-spacing: 0;
    ...
  }
  ...

With this approach I have to remember what properties are set in my versal mixin and overwrite them accordingly.

No big deal, as long as the mixin uses only a few properties and won't be extended or changed later on, in which case I may have to overwrite the new properies afterwards, too. This can be a maintenance nightmare in larger code bases.

It never really bothered me until I started to use a 'visually hidden' mixin for elements that should not be visible, but still be exposed to non-visual interpreters (think keyboard- or screenreader-usage).

Currently this mixin sets quite a lot of properties:

  /* in tools/_mixins.scss */
  @mixin vh(){
    /* visually hidden, not van halen */
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    border: 0;
  }

In the current project I had a case where I needed to modify an element that got hidden via this mixin before, 'unhiding' it in a later break point.

Since the best practice behind "visually hiding" content while remaining them accesible for keyboard or screenreader use had changed over the years, the vh() mixin already had changed over the projects and may be changed again in the future. Keeping track of all the properties affected by this mixin and reverting them accordingly when needed is not so easy.

The single source of truth in that case is the mixin itself - here the properties are set. So duplicating this mixin, renaming it to something like 'un-vh()' perhaps would be an option. In fact I think that is how Foundation handles it with their element-invisible / element-invisible-off mixins.

I decided to explore another option, to keep things nicely inside that one mixin, by creating a 'reset' parameter, setting it to empty as a default, and checking against it inside the mixin:

  /* in tools/_mixins.scss */
  @mixin vh($mode:''){
    @if $mode=='reset' {
      position: initial;
      width: initial;
      height: initial;
      padding: initial;
      margin: initial;
      overflow: intial;
      clip: initial;
      border: initial;
    } @else {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0,0,0,0);
      border: 0;
    }
  }

The nice thing about this is, should I need to alter the properties in the mixin, I can also directly alter their "reset" part without the need to check through my code base where theses changes have to be changed in my rules.

So now, on rules where I need to undo the mixin's work, I can use the same mixin again, but with 'reset':

  /* in components/_foo.scss */
  .hide-from-eyes {
    @include vh();
    ...
  }
  ...
  @media(...){
    .hide-from-eyes {
      @include vh('reset');
      ...
    }
  }

This seems to work pretty well. :-)

The "versal" mixin works equally well:

  /* in tools/_mixins.scss */
  @mixin versal($mode:'',$spacing:0.03em){
    @if $mode=='reset' {
      text-transform: initial;
      letter-spacing: initial;
    } @else {
      text-transform: uppercase;
      letter-spacing: $spacing;
    }
  }
 
  /* in components/_footer.scss */
  .footer-block-heading {
    @include versal('reset');
    padding: 0.5em;
    ...
  }

A potential downside is the usage with mixins that already take a lot of parameters, I am not sure how the order of parameters and which parameter is given when calling the mixin, may present a problem.

Maybe as a convention the 'reset' parameter should always be the first one, but I don't know currently how this'll behave when you leave out the 'reset' and use the second parameter as the first and so on.

There is an old article by Hugo Giraudel regarding parameters, lists, and parameterlists in scss on Site-Point, I still need to digest the differences. :-)

But for my simple use case the pattern works fine, currently. So maybe it works for you, as well.

Let me know what you think.

Photo by Maik Jonietz on Unsplash

Herbst

Hecke mit roten Weinblättern, ein abgestorbener Baum, vor blauem Himmel

Machs gut und Danke für alles, liebe SPEX

Die Nachricht kam für mich heute relativ überraschend: Die SPEX Redaktion wirft das Handtuch und das Heft wird nach 38 Jahren eingestellt.

Ich habe ein SPEX Abo seit Ende der 80er Jahre, und oft wurde ich deshalb von meinen eher rock-orientierten Mitmusikern und Bekannten dafür belächelt. Ja, die SPEX Autorinnen konnten schon immer prächtig herumschwurbeln und oft hatte man das ...

Brant Bjork – Chocolatize

youtube direct gestonere

Und der Stoner-God sah, dass es gut war, und deshalb klingen neue Brant Bjork Songs wie alte Brant Bjork Songs, weil was gut ist wird durch verbessern nicht immer besser.
Schönes Wochenende, y'all.

Brutalism, made in Offenbach

Ob es schön ist, darüber kann man trefflich streiten, aber sehenswert ist das Rathaus in Offenbach auf jeden Fall. Nachdem das technische Rathaus in Frankfurt und der "Turm" der alten Uni abgerissen bzw gesprengt wurden, ...

Septemeer 2018 – Kutter

Spacekutter

Septemeer 2018 – Fischbrötchen

Taucher greift nach Fischbrötchen, das ist aber ein Teil eines versteckten großen Fischs mit vielen Zähnen

Septemeer 2018 – Krabbe(n)

Typ versucht mit Krabbe in der Hand, Äpfel zu kaufen. Im Hintergrund Berge und eine Schweizer Flagge

Septemeer 2018 – Meereskönig

Dicker Hintern ist dick, auch wenns der Königshintern ist