Skip to content

[css-nesting] support nesting at-rules #2891

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
jonathantneal opened this issue Jul 6, 2018 · 4 comments
Closed

[css-nesting] support nesting at-rules #2891

jonathantneal opened this issue Jul 6, 2018 · 4 comments
Labels
Closed Accepted by Editor Discretion Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-nesting-1 Current Work

Comments

@jonathantneal
Copy link
Contributor

There are situations when nesting at-rules is more intuitive than spreading rule selectors.

Consider the following CSS for a typical website ”top bar”:

.topbar {
  inset: 0 0 auto;
  position: fixed;
}

.topbar-link {
  padding: 15px;
}

@media (width < 1024px) {
  .topbar {
    position: absolute;
  }
}

@media (width < 640px) {
  .topbar {
    position: static;
  }

  .topbar-link {
    padding: 10px;
  }
}

In this example, it is easier to scan at-rules nested within style rules, rather than the other way around. The occasional side-effect of brevity (due to the lack of selector repetition) further improves readability:

.topbar {
  inset: 0 0 auto;
  position: fixed;

  @media (width < 1024px) {
    position: absolute;
  }

  @media (width < 640px) {
    position: static;
  }
}

.topbar-link {
  padding: 15px;

  @media (width < 640px) {
    padding: 10px;
  }
}

As at-rule nesting is such a common feature in CSS Preprocessors, is is often conceptually bundled with “nesting” in general. This is not the case in the current css-nesting proposal, which is why I’ve created this separate issue.

I’m not sure how at-rule nesting would be added to the specs. It may (only?) require updates to css-syntax and css-conditional (citation). Now seems like a good time to discuss this, as similar changes may be needed to support the @nest rule.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Jul 6, 2018

Thanks for starting this discussion as a proper issue.

I agree that it often improves readability and reduces duplication to nest media queries inside selectors. Same, too, for @supports tests.

I also agree that it makes sense to move forward with this at the same time as the rest of the nesting proposal, as most of the parsing changes that will be needed could be implemented together.

The thing that is different about nested @-rules is that the interior content of the rule changes. Instead of having full style rules with selectors inside the media query, we would only expect property declarations, because the selector would come from the outer context.

This therefore affects not only parsing, but also the CSSOM model for the conditional rules. Do we define new CSSOM models for the nested rules? Or do we keep them as CSSGroupingRules, but then make the group contents a read-only copy of the outer selector?

Of course, how this question is addressed will be tied to how the CSSOM handles the @nest rule and nesting in general, which is still an open issue on the CSS Nesting proposal.

@fantasai fantasai added the css-nesting-1 Current Work label Jul 24, 2018
@JohnAlbin
Copy link

Now that the css-nesting spec draft is listed on the w3c site, here's the updated URL for Ameila’s CSSOM comment above: https://drafts.csswg.org/css-nesting-1/#cssom

The thing that is different about nested @-rules is that the interior content of the rule changes. Instead of having full style rules with selectors inside the media query, we would only expect property declarations, because the selector would come from the outer context.

Excellent point! I've been pondering this problem for several days since I read your comment.

Section 3 of the conditional spec is the part of the spec covering what goes in @-rules:

All conditional rules are defined to take a <stylesheet> in their block, which means they can accept any rule that is normally allowed at the top-level of a stylesheet, and not otherwise restricted.

I think we can actually leave this part of the spec unchanged if we instead alter section 2 and section 4.

In section 2 of the conditional spec, we would add something like this:

A conditional group rule can also be nested inside a CSS rule. When this occurs, the entire contents of the conditional group will be treated as if it were wrapped with @nest & { <contents> }.

Example 3
For example, with this nested rule:

#navigation {
 display: block;

 @media print {
   display: none;
 }
}

the contents of the @media rule would be treated as if the author had written:

#navigation {
 display: block;

 @media print {
   @nest & {
     display: none;
   }
 }
}

which is equivalent to:

#navigation {
 display: block;
}
@media print {
 #navigation {
   display: none;
 }
}

We would also need to change section 4 of the conditional spec from:

Conditional group rules are allowed at the top-level of a style sheet, and inside other conditional group rules.

to:

Conditional group rules are allowed at the top-level of a style sheet, inside other conditional group rules, and inside the declaration block of a rule.

This still leaves a mismatch between @nest contents which are defined as <declaration-list> and @media and @supports contents which are defined as <stylesheet>. (See https://drafts.csswg.org/css-syntax-3/#declaration-rule-list for those definitions.) Does this mean we need to redefine @nest’s contents in the nesting spec to also be <stylesheet>? I'm unsure.

Or do we keep them as CSSGroupingRules, but then make the group contents a read-only copy of the outer selector?

It sounds like my verbose solution above is the same as what you are suggesting as a solution in CSSOM. Yes, we keep them as CSSConditionRule and the cssRules property would include a single CSSStyleRule where the selectorText is @nest & and the style is the <stylesheet> contents of the @-rule. Well… approximately that. The exact details would need more fleshing out.

I should point out I only just started playing with CSSOM today using this codepen I made based on this MDN article on modifying a stylesheet rule with CSSOM. However, the hands-on experience made it much easier to understand the CSSOM than by just reading; I recommend it for other new-to-CSSOM people.

@cdoublev
Copy link
Collaborator

cdoublev commented Mar 15, 2022

Conditional rules nesting is now defined, but CSSConditionalRule.style may be missing in CSSOM, or is it intentional to not define it?

Browsers currently do not support nested rules, but I hope the following exemple is syntactically correct:

.selector {
  & .child {
    color: green;
  }
  @media all {
    color: red;
  }
}
const { styleSheets: [{ cssRules: [nestedRule, mediaRule] }] } = document
console.log(nestedRule.style.color) // green
console.log(mediaRule.style) // undefined
console.log(el.style.color) // red

EDIT:

I realize just now that it is trickier than I thought.

/* top level */
@media {
  color: red; /* Ignored because invalid */
  .selector {
    color: green;
  }
}
console.log(document.styleSheets[0].cssRules[0].style) // ??

Side question

How do you know when/if a spec is ready for testing, to receive implementation experience, before moving to CR? I'm not sure that CSS Nesting is ready for testing. This is the reason why I did not create a new issue for this. If it is not ready, my comment does not matter so please forgive me for the noise.

@tabatkins tabatkins added Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. Closed Accepted by Editor Discretion labels Jan 10, 2023
@tabatkins
Copy link
Member

tabatkins commented Jan 10, 2023

Closing, since we ended up doing this (https://www.w3.org/TR/css-nesting-1/#conditionals).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Closed Accepted by Editor Discretion Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-nesting-1 Current Work
Projects
None yet
Development

No branches or pull requests

6 participants