Skip to content

[css-nesting] simpler embedding of media queries #5805

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

Closed
bradkemper opened this issue Dec 18, 2020 · 7 comments · Fixed by #6483
Closed

[css-nesting] simpler embedding of media queries #5805

bradkemper opened this issue Dec 18, 2020 · 7 comments · Fixed by #6483
Labels
css-nesting-1 Current Work

Comments

@bradkemper
Copy link
Contributor

The spec has this for how to embed a MQ in a rule:

.foo {
  display: grid;

  @media (orientation: landscape) {
    & { 
      grid-auto-flow: column; 
    }
  }
}

But the unadorned ampersand and extra set of braces seems extraneous. It is incredibly useful, and much simpler, in SCSS to just write it like this for the commonest uses:

.foo {
  display: grid;

  @media (orientation: landscape) {
      grid-auto-flow: column; 
  }
}

In fact, embedded the MQ in the rule like that, without extra braces, is one of my favorite things about writing in SCSS. It just feels natural and familiar. Even in old vanilla CSS, I can't tell you the number of times I've forgotten to include the selector inside the MQ, when it was just an MQ for a single rule, written right after the bare rule. When the MQ is inside the rule, instead for the other was around, it is a joy to not have to write another selector and braces inside it.

You don't have the garden path problem here. If the first non-white-space character after the opening brace of the nested MQ (or after a closing brace of a nested rule within that MQ) is not an ampersand or @ sign, then it is the beginning of a property for a declaration.

I think there is nothing ambiguous about the following, and it is easier to write and read:

.btn {
  text-decoration: none;

  @media (max-width: 768px) {
      display: block; 

      &:hover { 
          box-shadow: 0 0 2px black inset;
      }
  }
}

So basically, the & { and } parts are assumed, as a shortcut for when you don't need any more than that, when you already have the braces from the nested @ rule. This should hold true for other nested @ rules too, such as @supports, etc.

@SebastianZ
Copy link
Contributor

Syntactically speaking, the suggested idea means that

  1. property declarations may appear directly within a media query, but only if they are nested within a style rule.
  2. within a media query, property declarations must come before any rule declarations.

Sebastian

@bradkemper
Copy link
Contributor Author

Syntactically speaking, the suggested idea means tha

  1. property declarations may appear directly within a media query, but only if they are nested within a style rule.

  2. within a media query, property declarations must come before any rule declarations.

#1 is true, and intended, but I don't think #2 would follow. The closing brace of a media query or a rule within a rule tells the parser that it can start looking for property declarations (or ampersands or @ signs) again.

So, this is also not ambiguous as to whether to parse as property or rule:

.btn {
  margin: 5px;

  @media (max-width: 768px) {
      display: block; 

      &:hover { 
          box-shadow: 0 0 2px black inset;
      }

      margin: 5px 0;
  }

  border: 1px solid;
}

@SebastianZ
Copy link
Contributor

Syntactically speaking, the suggested idea means tha

  1. property declarations may appear directly within a media query, but only if they are nested within a style rule.
  2. within a media query, property declarations must come before any rule declarations.

#1 is true, and intended, but I don't think #2 would follow. The closing brace of a media query or a rule within a rule tells the parser that it can start looking for property declarations (or ampersands or @ signs) again.

Note that I extracted the second point from your statement:

If the first non-white-space character after the opening brace of the nested MQ (or after a closing brace of a nested rule within that MQ) is not an ampersand or @ sign, then it is the beginning of a property for a declaration.

Whether or not to allow property definitions anywhere within the @media-rule needs to be discussed.

Sebastian

@fantasai fantasai added the css-nesting-1 Current Work label Jan 7, 2021
@bradkemper
Copy link
Contributor Author

Perhaps I left something out of my parsing description, but #2 was not intended.

@tabatkins
Copy link
Member

Hm, yes this should be possible. It's the exact same parsing context as the interior of the style rule itself.

@argyleink
Copy link
Contributor

Nice, I've been doing this but it'd be nice not to have to 👍🏻

a {
  ...
  @media (prefers-reduced-motion: no-preference) { & {
    transition: outline-offset .25s ease;
  }}
}

vs

a {
  ...
  @media (prefers-reduced-motion: no-preference) {
    transition: outline-offset .25s ease;
  }
}

@johannesodland
Copy link

The PostCSS preprocessor has also allowed this simpler syntax for a long time through the PostCSS Nesting plugin. It is automatically enabled using PostCSS Preset Env.

This syntax is familiar to many developers already. It's more readable and feels more natural than having the extra ampersand and braces.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-nesting-1 Current Work
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants