Skip to content
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

[mediaqueries-5] Introduce @size rule for defining reusable media query size values #10487

Open
brandonmcconnell opened this issue Jun 24, 2024 · 4 comments

Comments

@brandonmcconnell
Copy link

brandonmcconnell commented Jun 24, 2024

Abstract

This proposal introduces the @size rule, a new CSS at-rule, that allows authors to define variable sizes which can be referenced in @media, @custom-media, and @container queries alike. This feature offers an easier and more maintainable method to manage responsive design breakpoints across CSS files.

Related proposal: [mediaqueries-5] [css-env] Replace @custom-media with custom environment variables? #6698

☝🏼 this proposal shares a similar goal but uses a different approach

Motivation

Responsive design often involves repeatedly using the same viewport breakpoints across multiple media queries. This can lead to cumbersome, error-prone code and make global updates to breakpoints tedious. The @size rule aims to solve this by allowing developers to define and reuse named sizes that can be referenced consistently across all media queries.

The introduction of @custom-media aids in this effort as well, but it stores an entire query, where even in the definition of a @custom-media query, the use of a reusable variable value would prove useful, as pointed out by @adamwathan on X here:

It's a shame to me that the @​custom-media spec offers no way of removing the duplicate 500px value in this sort of situation like you'd expect to be able to do with a plain old variable 😕
Adam Wathan

Syntax / Example

Defining Sizes

The @size at-rule allows developers to declare named sizes using standard CSS units:

@size {
  --small: 480px;
  --medium: 768px;
  --large: 1024px;
  --extra-large: 1440px;
}

Usage in @media and @container Queries

The named sizes can be used in @media, @custom-media, @container queries:

@media (min-width: size(--small)) {
  /* Styles for small and above */
}

@media (width > size(--medium)) and (width <= size(--large)) {
  /* Styles for medium to large */
}

@custom-media --custom-medium (width > size(--medium));
@media (--custom-medium) {
  /* Styles using custom media query */
}

@container some-container (min-width: size(--small)) {
  /* Styles for small and above */
}

Specification

Grammar

The @size rule must contain a block of rules, each defining a single named size. Each named size must be a valid CSS identifier followed by a colon, a valid CSS length (e.g., px, em, rem, %) or viewport width/height (e.g., vw, vh), and a semicolon.

Semantics

  • Defining Sizes:

    • The @size at-rule must appear at the outermost level of the style sheet and cannot be nested inside other at-rules or selectors.
    • Each named size defined within the @size block is treated as a global variable that can be referenced using the size() function.
  • Referencing Sizes:

    • The size() function takes one argument: the name of the size defined via @size.
    • The argument for size() must match one of the identifiers defined within an @size rule.
    • If an undefined name is used within size(), the rule is invalid and should be ignored by the browser.

Benefits

  • Maintainability: Centralized definition of media sizes allows for easier updates and maintenance of responsive design breakpoints.
  • Readability: Named sizes improve the readability and semantics of media queries.
  • Consistency: Ensures consistent breakpoint usage across different parts of the stylesheet.

Specification Considerations

  • Specification selection: I marked this proposal as part of the [mediaqueries] spec, but it may be a better fit for a different specification. I invite anyone to offer suggestions for different specifications to label this as.

  • Alternative name: I originally considered the at-rule name @media-size but renamed it to @size to make this arbitrarily supported in @container queries as well as @media and @custom-media queries.

  • Alternative syntax: I can see an argument being made for an alternative syntax like this:

    @size --small 480px;
    @size --medium 768px;
    @size --large 1024px;
    @size --extra-large 1440px;
  • Expanded scope of usage: I could see these sizes being very useful in styles as well, so it may be worth considering allowing the size() function to be used within property values, enabling styles to reference the defined sizes directly. This would provide a consistent way to use the named sizes across both queries and properties (e.g. width: size(--medium);).

Implementation Considerations

  • Browser Compatibility: A new at-rule and function needs to be implemented across all browsers; feature detection should be considered.
  • Tools and Validators: CSS authoring tools and validators will need to be updated to support and recognize the new @size rule and the size() function.

Conclusion

The @size rule introduces a method for defining reusable responsive design breakpoints. By enabling the reuse of named sizes across @media, @custom-media, and @container queries, this proposal aims to simplify the process of maintaining consistent, flexible, and readable responsive styles.

@brandonmcconnell
Copy link
Author

Another approach could be to add support for any @property-defined values inside queries. That would require next to no new actual language changes, but it comes with the caveat that queries would not inherit any changes to those values and could only use their initial values, which may be more confusing to users.

In that case, such @property values would need to somehow be definable constant to be meaningful and able to be used in different places meaning the same thing.

Because of this point, an alternative to @property like @size may be best after all.

@tabatkins
Copy link
Member

The problem you're solving is just getting a variable that's useful in a "global" sense, yeah? There doesn't appear to be anything size-specific in this proposal; it's just doing substitution, and you happen to only be using that substitution in places that expect a size, but the same functionality could be used for any value.

So this is a dupe of #2627 I think.

@brandonmcconnell
Copy link
Author

@tabatkins The idea here was to make these variables size-specific and limited to lengths, but custom environment variables would take it one step further. I'm definitely a fan of #2627 if that passes. 💯

@Crissov
Copy link
Contributor

Crissov commented Jun 26, 2024

While size usually consists of width and height, the proposal currently only considers the former.

There is plenty of preexisting content that would allow to identify commonly used terms for breakpoints (as in the example above), so you would not need custom idents but could introduce keywords that authors could set to individual values then, without a need for size():

@size {
  small: 480px 640px; /* 2:3 */
  medium: 768px 576px; /* 4:3 */
  large: 1152px 720px; /* 8:5 */
  extra-large: 1920px 1080px; /* 16:9 */
}

@media (min-width: small) {
  /* Styles for small and above */
}

@media (width > medium) and (height < large) {
  /* Styles for medium to large */
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants