Search code examples
csssassmedia-queriesprogressive-enhancement

Using @supports selector() despite Sass not supporting it


I want to use the new CSS feature queries by selector, like so:

:root { --focus-shadow: 0 0 0 2.4px rgba(130, 138, 145, 0.5); }

/* Focus styles even for mouse selection in old browsers */
*:focus { outline: none; box-shadow: var(--focus-shadow); }

/* Newer browsers: Only add focus styles if e.g. navigating with the keyboard */
@supports selector(*:focus-visible) {
  *:focus { box-shadow: none; }
  *:focus-visible { box-shadow: var(--focus-shadow); }
<a href="#">Focus me</a>

The above is valid CSS (although poorly supported as of June 2020), but Sass doesn't support it in either of its two implementations yet. It's in the works, but it looks like it'll take a while to implement it. Trying to compile the above through Sass throws an error (varies between Sass implementations; see these issues for details on the errors).

In the mean time, I want to trick Sass into compiling my support query as is, without trying to understand it. I tried a few things unsuccessfully. Using unquote(), this is the most promising attempt:

@mixin supports-selector( $selector ) {
   $query-str: #{ unquote( '@supports selector(' ) }#{ unquote( $selector ) }#{ ')' };

   #{ unquote( $query-str ) }#{ unquote( '{' ) }
      @content;
   #{ unquote( '}' ) }
}

:root { --focus-shadow: 0 0 0 2.4px rgba(130, 138, 145, 0.5); }

*:focus { outline: none; box-shadow: var(--focus-shadow); }

@include supports-selector( '*:focus-visible' ) {
    *:focus { box-shadow: none; }
    *:focus-visible { box-shadow: var(--focus-shadow); }
}

This still throws an error though, as Sass expects an arbitrary string to be a property followed by a colon:

property "#{ unquote( $query-str ) }#{ unquote( '{' ) }" must be followed by a ':'

Not unquoting the @supports part results in error to the effect that selector(whatever) is not a valid @supports condition.

I don't know what else to try.

How can I trick Sass into not compiling my mixin?


Solution

  • This might work for you - by just escaping the characters, it will still compile to CSS.

    The SASS/SCSS processor was getting hung up not on the @supports, but rather the *:focus-visible:

    :root { --focus-shadow: 0 0 0 2.4px rgba(130, 138, 145, 0.5); }
    
    /* Focus styles even for mouse selection in old browsers */
    *:focus { outline: none; box-shadow: var(--focus-shadow); }
    
    /* Newer browsers: Only add focus styles if e.g. navigating with the keyboard */
    @supports #{'\(*:focus-visible)'} {
      *:focus { box-shadow: none; }
      *:focus-visible { box-shadow: var(--focus-shadow); }
    }
    

    Compiles to this:

    :root {
      --focus-shadow: 0 0 0 2.4px rgba(130, 138, 145, 0.5);
    }
    
    /* Focus styles even for mouse selection in old browsers */
    *:focus {
      outline: none;
      box-shadow: var(--focus-shadow);
    }
    
    /* Newer browsers: Only add focus styles if e.g. navigating with the keyboard */
    @supports (*:focus-visible) {
      *:focus {
        box-shadow: none;
      }
    
      *:focus-visible {
        box-shadow: var(--focus-shadow);
      }
    }
    

    SASSMEISTER Link to play with.

    Edit: based on your comment, you can still add the selector:

    @supports  #{'\selector(*:focus-visible)'}  {
      *:focus { box-shadow: none; }
      *:focus-visible { box-shadow: var(--focus-shadow); }
    }
    

    Updated SASSMeister