Using @supports selector() despite Sass not supporting it
Asked Answered
R

1

8

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?

Roy answered 30/6, 2020 at 20:1 Comment(0)
M
8

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

Monochromatism answered 30/6, 2020 at 21:5 Comment(4)
Sadly, I don't think this will do. It compiles because it interprets * as a property, and focus-visible as a value. It doesn't check whether the actual selector is supported. Here is a CodePen that demonstrates how that query doesn't fulfill its purpose: codepen.io/arianeb/pen/MWKOqZK :: Note that for this to work, you need to use Chrome and activate the #enable-experimental-web-platform-features flag in chrome://flags.Roy
Updated my answer to include selectorMonochromatism
You're a genius. Thank you very much.Roy
Little note, if you don't need the * selector you can opt out of some of the syntax there: @supports #{'selector(:focus-visible)'} {...}Hundredfold

© 2022 - 2024 — McMap. All rights reserved.