-
Notifications
You must be signed in to change notification settings - Fork 185
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
fix!: reduce specificity of generated stylesheets to 0 #1930
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I didn’t know about :where
. I can see this being useful. My consideration now is compatibility, including backwards compatibility. It looks like :where
is fairly widely supported, but it’s only since 2021 that it’s been implemented in browsers. Can you speak a little more to the use case that this solved for you? Is there an example where you tried to override Plot’s default styles, and were surprised or stymied by the specificity of those styles?
These are great questions @mbostock – thank you so much for reviewing! The compatibility concern is of course very relevant, and I must admit I have not done due diligence here – my apologies! I have the luxury of not really having to target legacy environments very often, and have been using this selector for some time with great success. It would be possible of course to use something like In any event, to your questions. We've been working with Plot the past week to put together some dead simple time series charts, and when we were happy with the functionality and configuration I got to work trying to style these. In our application we make heavy use of CSS modules for locally scoped class selectors. The specificity of these are When applying this to Plot, I noticed that my styles for the legend didn't seem to take, at all. It turns out, while setting So I did this, and some of the styles took, but not all. For example, I tried setting Of course, it's possible to override these styles by increasing the specificity. Using something like That's why many reusable libraries that ship styles these days make heavy use of the It may be best to actually implement a new test case for this, and my apologies for not doing this – time permitting I will look into it over the weekend. It really shouldn't be particularly difficult. Maybe that will be a better answer to your questions? |
@mbostock I implemented a very basic test case in e325399. These changes are wider than just categorical legends of course, but before I spend more effort in developing further test cases I'd like to just check that this:
Verifying that these changes actually do what they say on the tin is very simple, just revert 755954e. I've recorded a brief session of me doing just this, to show you how reverting the changes makes the second legend ignore the styles we're trying to set by specifying I hope this is a sufficiently small and good example of the use case I'm trying to solve with these changes – many thanks for your review! (Edit: updated SHAs post rebase) |
If anyone else comes across this PR and wonders about a workaround that doesn't require you to write more specific CSS selectors, this hack should do the trick: let css = style.innerHTML
for (const { selectorText } of style.sheet.rules) {
css = css.replace(
selectorText,
`:where(${selectorText})`,
)
}
style.innerHTML = css In the above code, By no means a great solution, but it does seem to work in the short term. |
By reducing the specificity of selectors in the generated stylesheets to 0, consumers of Plot can much more easily override these styles using their own stylesheets while still enjoying the default styling of Plot.
Because the change in selector specificity affects every chart, all snapshots will need regenerating. The rendered output should yield no differences however.
This test renders two categorical legends, one using default Plot styles and the other using styles by setting the `className` option. The styles being overridden have the same selector specificity as those set by Plot, would it not be for the `:where()` selector resetting Plot's specificity to 0. This is easily verified by reverting b2ff68e.
@mbostock / @Fil – appreciating you have other things to do and this PR may not be a priority – I'm wondering if you think the proposed changes are at all relevant to this project? If so if I should implement more tests or have any thoughts on other changes before this can be brought to |
Sorry for the delay on this. We’ll get this merged. I should have included it in 0.6.12 but I’ll take it from here. Thank you! |
Thank you @mbostock – much obliged! If you'd like me to look into expanding the test suite or such related to this, please do feel free to let me know. Happy to contribute! |
What is this, and why is it necessary?
By reducing the specificity of selectors in the generated stylesheets to 0, consumers of Plot can much more easily override these styles using their own stylesheets while still enjoying the default styling of Plot.
Without this, consumers of Plot must resort to increasing the specificity of selectors or individual styles, which can be both awkward and hard to do.
A breaking change, technically
While this change is meant to be safe, it is technically a breaking change. Any consumer of Plot that is trying to override css, but failing due to lower specificity, should start seeing those styles applied. While that may actually fix a few bugs out there, it could also cause some others, where those consumers have simply missed that those styles aren't being applied on top of the defaults.
Why so many snapshot updates?
Because the change in selector specificity affects every chart, all snapshots will need regenerating. The rendered output should yield no differences however. If it does, that's a bug.
Alas – this many snapshot updates seem to make GitHubs UI practically worthless for reviewing the code however. My apologies, I don't have a good answer for how to fix that. I did however split the changes into two commits for this reason:
b2ff68e755954e (Edit: updated SHA post rebase)300c400fbcfa1f (Edit: updated SHA post rebase)I hope this helps.
Related resources
:where
: https://developer.mozilla.org/en-US/docs/Web/CSS/:where