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

Possible for component to modify a CSS selector in its own style block? #7907

Closed
janosh opened this issue Oct 3, 2022 · 5 comments
Closed

Comments

@janosh
Copy link
Contributor

janosh commented Oct 3, 2022

Describe the problem

My svelte-multiselect component uses the :where() selector to make it's default CSS recessive, i.e. easily overridable with global CSS without having to use the !important CSS flag. E.g.

:where(div.multiselect) {
  ...
}

The problem is :where() is unsupported in Edge v87 and below, meaning the component default styles are completely missing there.

Describe the proposed solution

MDN has a neat example showing how to define fall back CSS in case the similar :is() selector is unsupported:

/* This rule won't be applied in browsers which don't support :is() */
:is(ul, ol) > li {
  /* CSS applied when the :is(…) selector is supported */
}

@supports not selector(:is(a, b)) {
  /* Fallback for when :is() is unsupported */
  ul > li,
  ol > li {
    /* The above expanded for browsers which don't support :is(…) */
  }
}

The only problem with this solution is I would have to duplicate the component's entire set of default styles (~140 lines) breaking SSOT.

Is it possible to wrap all of a component's CSS selectors in :where() conditional on browser support? I.e. could I check for support in the script block and then apply some modification to the style block that wraps every selector in :where()?

Alternatives considered

Is there a way of making CSS rules easily overridable other than :where() with better browser support?

Importance

would make my life easier

@Prinzhorn
Copy link
Contributor

I don't understand how that would solve your problem, wouldn't that imply that consumers of your component would need to know about this or else their overrides would break in Edge v87? So your consumers also need to duplicate their styles (to increase specifity), making this whole dance pointless?

@janosh
Copy link
Contributor Author

janosh commented Oct 5, 2022

Yes, overrides would break in Edge v87. But missing overrides is a much smaller impact on the component's functionality (presumably none, just suboptimal appearance) compared to all default styles missing which makes the component completely unusable (see the screenshot in janosh/svelte-multiselect#117).

So your consumers also need to duplicate their styles (to increase specifity), making this whole dance pointless?

There wouldn't be a need to duplicate overrides, they'd just have to resort to !important if they know they want to support Edge 87 and earlier.

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Oct 5, 2022

I see. I don't think what you want is possible, because at runtime these styles might live in a bundled CSS file etc.

However, if you're only worried about SSOT (and not size), then you could use Sass (https://github.com/sveltejs/svelte-preprocess) instead of duplicating the styles. Something along the lines of

@mixin stuff() {
  .foo {
  	color: red;
  }
  
  .bar {
  	display: flex;
  }
}

:where(div.multiselect) {
  @include stuff();
}

@supports not selector(:where(div.multiselect)) {
  div.multiselect {
	@include stuff();
  }
}

which compiles to

:where(div.multiselect) .foo {
  color: red;
}
:where(div.multiselect) .bar {
  display: flex;
}

@supports not selector(:where(div.multiselect)) {
  div.multiselect .foo {
    color: red;
  }
  div.multiselect .bar {
    display: flex;
  }
}

@janosh
Copy link
Contributor Author

janosh commented Oct 5, 2022

@Prinzhorn Cool! I usually try to avoid preprocessors if possible but sounds like Sass might be the best solution here.

@Rich-Harris
Copy link
Member

Given that :where(...) is now very widely supported, I'm going to go ahead and close this

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

No branches or pull requests

3 participants