Search code examples
stylus

Stylus: prevent media tag from interpreting strings


We have an interesting dilemma.

I have a PR open for the rupture project to namespace the functions it exports in order to add a no-conflict mode.

First the actors

There are two functions (or mixins) that are named landscape and portrait. The PR namespaces them to rupture-landscape and rupture-portrait. The @media mixin is used throughout.

And now the scene.

With some of the functions created by rupture, a string is assembled to be used with the media tag. The end result should be a normal css media query.

The problem lies with the stylus @media mixin. It seems to automatically attempt to interpret the string and expand any keywords that might exist in the scope.

Since both landscape and portrait are within scope when not using no-conflict-mode, when ever the @media tag is used with a composed string and orientation: portrait or orientation: landscape the result will prefix both the words portrait and landscape with rupture.

I've created a trivial example with a couple of attempts to fix the issue on codepen here.

Here is the code as well:

Stylus

$landscape = 'notlandscape'
$string = "only screen and (orientation landscape)"
$unquote = unquote($string)
$s = s($string)

.foo
  // this is the main issue
  @media $string
    color: blue
  These two are attempts to fix the issue
  @media $unquote
    color: blue
  @media $s
    color: blue

and the compiled result in CSS

@media only screen and (orientation: 'notlandscape') {
  .foo {
    color: #00f;
  }
}
@media only screen and (orientation: 'notlandscape') {
  .foo {
    color: #00f;
  }
}
@media only screen and (orientation: 'notlandscape') {
  .foo {
    color: #00f;
  }
}

The actual desired output:

@media only screen and (orientation: landscape) {
  .foo {
    color: #00f;
  }
}

Is there a way to prevent or circumvent this behavior?


Solution

  • You can try interpolation. The referenced @media page also has a section about Interpolations and variables that will provide more info and examples.

    landscape = 'notlandscape'
    $string = "only screen and (orientation landscape)"
    
    .foo
      @media ({$string})
        color: blue
    

    Live @codepen

    Parenthesis are essential here. So it's not exactly desired output but it's still valid CSS. How to avoid that (or if it's necessary) depends on use case. One idea:

    landscape = 'notlandscape'
    $string = "orientation: landscape"
    
    .foo
      @media only screen and ({$string})
        color: blue
    

    Live @codepen