Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unbound variable inside mixin is looked up in global scope; should be local scope #1474

Closed
Quuxplusone opened this issue Oct 15, 2014 · 3 comments

Comments

@Quuxplusone
Copy link

In Sass 3.4.5 (Selective Steve) on Mac OS X, the following code:

@mixin foo() { bar: $bar; }

$bar: 1;
a {
  $bar: 2;
  @include foo();
  baz: $bar;
}

compiles to a { bar: 1; baz: 2; }.

The current version of Gabriele Cirulli's 2048 expects it to produce a { bar: 2; baz: 2; } — and that seems like the most reasonable behavior to me as well.

I don't know which version of Sass Cirulli was using to compile his original "main.scss", but you can easily verify that re-compiling "main.scss" with 3.4.5 produces a bunch of unwanted git diffs. I infer that this is a bug in Sass 3.4.5 that was introduced recently.

@nex3
Copy link
Contributor

nex3 commented Oct 17, 2014

This isn't about how the variable is looked up, it's about how it's assigned. Sass 3.4 changed the variable semantics so that any variable declared in a nested scope (here within a CSS rule) shadows the global variable with the same name rather than assigning to it. This is so that $bar: 2 does the same thing no matter what global variables have been defined in other files that have been imported.

To assign to the global variable, all you have to do is explicitly use the !global flag. For example:

@mixin foo() { bar: $bar; }

$bar: 1;
a {
  $bar: 2 !global;
  @include foo();
  baz: $bar;
}

This compiles to a {bar: 2; bar: 2}.

@nex3 nex3 closed this as completed Oct 17, 2014
@Quuxplusone
Copy link
Author

Aha. Makes sense; thank you. Is there a simple way to write the code that would work with Sass 3.3 and with 3.4, other than refactoring the mixin to take $bar as a parameter?

@nex3
Copy link
Contributor

nex3 commented Oct 17, 2014

Sass 3.3 is able to parse the !global flag, so the code above should work with it.

Quuxplusone added a commit to Quuxplusone/2048 that referenced this issue Oct 17, 2014
Two bugs here, relative to Sass 3.4.5 (Selective Steve).
The first bug, reported at
dsociative@80258ad
is that Sass apparently requires interpolation braces #{} around
a mixin parameter used on the left side of a colon.

The second bug, visible at that same commit, is that when you
refer to an unbound variable inside a mixin, Sass looks it up
in the global scope rather than in the local scope of the "caller"
of the mixin. For example,

    @mixin foo() { bar: $bar; }

    $bar: 1;
    a {
      $bar: 2;
      @include foo();
      baz: $bar;
    }

gives `a { bar: 1; baz: 2; }`.

According to the Sass maintainers, this is by design. The fix is to
explicitly mutate that global variable via `!global` rather than
trying to get the mixin to use a local variable.
sass/sass#1474
cazzerson added a commit to cazzerson/breakpoint that referenced this issue Nov 10, 2014
Due to sass/sass#1474, functions such as fluid() fail, returning NaN or Infinity because the global $current-bp var is not set.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants