Skip to content

Leaky Sass variables #156

Open
Open
@lolmaus

Description

@lolmaus

Problem

Sass variables defined at module root are global. They leak across files, and changing a variable in one module affects other modules (unless the variable is redefined at the top of each module).

This can lead to nasty bugs. Leaky variables are not what you expect from an addon with module in it's name.

Cause

Unfortunately, Sass does not have a !local flag that would make a variable defined at the root of a file to be local to that file.

Proposed solution

I've come up with a Sass hack to resolve this issue.

I wrap all the module's code with @at-root {}.

Such directive is meaningless: without a selector it does nothing. The resulting CSS is identical to what it used to be before wrapping with @at-root. The specificity of selectors is not affected.

But thanks to a pair of curlies, it has a side-effect: all variables defined inside are now local!

Note that you can still define/overwrite global variables using the !global flag.

Example

app/pods/components/foo-bar/styles.scss

Before:

$padding: 20px;

.header: {
  padding: $padding;
}

.footer {
  padding: $padding;
}

When I wrote the code above, I wasn't aware that a global variable $padding was already used throughout the app. I changed it's value globally.

In the best case, I would receive a compile-time error like incompatible units px and rem.

In the worst case, it would compile, and half of the app's components will end up defaced. The exact amount depends on the alphabetic order of components, I guess.

After:

@at-root {
  $padding: 20px;

  .header: {
    padding: $padding;
  }

  .footer {
    padding: $padding;
  }
}

Now the $padding variable is local to this module. Assigning a value to it does not affect other components that use a global variable with the same name.

TL/DR

We have to wrap every our module with @at-root {} by hand.

It would be nice if ember-css-modules did it automatically.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions