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

Composing class names inside media queries #4040

Open
OliverJAsh opened this issue Jun 18, 2019 · 5 comments
Open

Composing class names inside media queries #4040

OliverJAsh opened this issue Jun 18, 2019 · 5 comments

Comments

@OliverJAsh
Copy link

I have some styles inside a class which can be used standalone, but I would also like to apply these styles to another class when a media query condition is met.

The only way to achieve this today (IIUC) is by either duplicating the styles for my classes, or moving the media queries into JavaScript and conditionally applying the classes there. Both of these are significant trade offs, so I believe there should be some way of achieving this in CSS, natively.

Below is an example.

I have two classes: light and dark.

.light {
  border: 1px solid;
  background-color: white;
}

.dark {
  border: 1px solid black;
  background-color: black;
  color: white;
}
<h2>light</h2>
<div class="light">foo</div>
<h2>dark</h2>
<div class="dark">foo</div>

Now I want to compose these class names to create a new version: light on mobile (i.e. narrow screens), dark on desktop (i.e. wide screens).

The only way I'm aware of doing this is by duplicating my styles:

@media (max-width: 499px) {
  .lightOnMobileAndDarkOnDesktop {
    border: 1px solid;
    background-color: white;
  }
}

@media (min-width: 500px) {
  .lightOnMobileAndDarkOnDesktop {
    border: 1px solid black;
    background-color: black;
    color: white;
  }
}
<h2>light on mobile, dark on desktop</h2>
<div class="lightOnMobileAndDarkOnDesktop">foo</div>

However I would like to achieve this without duplicating the styles for my classes, and without JavaScript.

Here is some pseudo code which illustrates what I would like to achieve:

@media (max-width: 499px) {
  .lightOnMobileAndDarkOnDesktop {
    @extend .light;
  }
}

@media (min-width: 500px) {
  .lightOnMobileAndDarkOnDesktop {
    @extend .dark;
  }
}

Are there any proposals for CSS that would allow me to achieve this in the future?

Proposals I'm aware of which could help:

  • @extend, but this seems inactive. Last updated in 2015? What's the status of this now?
  • @apply, but this was abandoned.

(Originally posted to https://stackoverflow.com/questions/56628123/css-composing-class-names-inside-media-queries.)

@OliverJAsh
Copy link
Author

Hi @jonjohnjohnson, do those proposals provide solutions to my example? I don't immediately see how nesting or else conditions will help. 🤔

@jonjohnjohnson
Copy link

Combinable queries seem pretty useful. The current W3C style sheet is doing a conditional against both selectors and @media, which is involving a fair bit of code duplication atm...
@fantasai - #112 (comment)

A lot of discussion in those links can shed some light on how your request relates to the broader landscape. And some of those might be aided by and even encapsulate your specific use case.

@OliverJAsh
Copy link
Author

Judging by #112 (comment), the idea would be to achieve something like this?

@when selector(.light) or (media(max-width: 499px) and selector(.lightOnMobileAndDarkOnDesktop)) {
  /* styles for light */
}

@when selector(.dark) or (media(min-width: 500px) and selector(.lightOnMobileAndDarkOnDesktop)) {
  /* styles for dark */
}

IIUC, that would be very nice. However one downside is it forces you to declare things at the same time, in this case light/dark must be defined along with lightOnMobileAndDarkOnDesktop. I would prefer to keep the selectors separate. /cc @tabatkins

.light {}
.dark {}
.lightOnMobileAndDarkOnDesktop {
  /* compose classes inside here */
}

@AmeliaBR
Copy link
Contributor

One solution for your use case might be custom environment variables (see proposal/discussion in #2627). Since environment variables are associated with the document as a whole, they could be defined to be used inside selectors and other places where a var(--custom-property) is invalid (see the inline issues on that spec).

Possible syntax for your case, you would use the light-or-dark class in your markup:

/* default values for narrow screens */
@environment --light-selector = .light, .light-or-dark;
@environment --dark-selector = .dark;

@media (min-width: 500px) { /* wider-screen values */
  @environment --light-selector = .light;
  @environment --dark-selector = .dark, .light-or-dark;
}

env(--light-selector) {
    border: 1px solid;
    background-color: white;
}
env(--dark-selector) {
    border: 1px solid black;
    background-color: black;
    color: white;
}

Again, this is just a proposal: the details & syntax are not confirmed.

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