@extend should unify parent selectors that share a simple selector
See original GitHub issueHi! Sorry to (maybe) resurrect a long-dead issue, but I’m having the same problem as #1428, #1052 and others. I am attempting to do the same thing as the OP of #1052: create a system where styles are abstracted from selectors, so we can:
- use the same styles everywhere
- style differently-structured across projects—markup we can’t necessarily change
Placeholders for the styles—@extend
ed in a layer of selectors—was working well until I ran into the issue with how it combines multiple descendant selectors. (For example: output I like \ output I don’t like ) I’ve tried using descendants in the placeholder layer and using them in the selector layer, but the result is the same: at some point, I (usually inadvertently) make it so the relationship between the placeholders doesn’t match with the selectors’, and I start to get selectors like .thing.state .thing.other-state .part
when I need .thing.state.other-state .part
.
I already know that I can work around this by creating a flat structure of placeholders/mixins with every permutation of states/styles encoded into their names, but I’m reluctant to settle for that—especially when my setup with placeholders for each style/state almost works. (I’d really like to avoid forcing my teammates to remember/reproduce long names of states, parts, and/or variants in the correct order, e.g.
%button-small-focus-active-background
.)
The team’s responses to other issues in this vein make me think it’d be fruitless to ask for a change to placeholders or @extend
, since our mental models about what those things should be don’t match up. Maybe some kind of Sass-specific combinator could solve the problem, or a flag on @extend
that makes it…dumber?
Hopefully at the very least, you can see what I’m looking to solve for. Let me know if I need to clarify. Thanks!
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (2 by maintainers)
Top GitHub Comments
You’re actually running into a different problem than the issues you cite. Those issues are about Sass generating too many selectors, which it has to do because it’s unaware of how the HTML that’s being styled is structured. Your issue is that it’s not generating enough selectors; specifically, it’s not generating
.thing.state.other-state .part
.The reason for this in general is that Sass trims selectors it judges unlikely to match real-world HTML, in order to avoid bloating the CSS and annoying even more people than those who filed the issues you linked. For example, the most theoretically-safe way to expand the selectors for
would be
but Sass assumes that you probably aren’t going to be putting
class="a c"
on the same element, and uses that to generate less CSS. (Users like those who filed #1428 and #1052 wish it would go even further and only generate one of.a .c .d
and.c .a .d
, but there’s no way for it to know which one to choose.)In your specific case, though,
.a
is.custom-text-field:focus-within
and.b
is.custom-text-field.invalid
. These two compound selectors share the simple selector.custom-text-field
, which is a good reason to believe that they’ll apply to the same element, so Sass’s heuristic to delete the unified selector fails.I think this is worth tweaking the extension algorithm for. Specifically, I think we should generate the unified parent selector if and only if the two selectors being unified share at least one simple selector. For backwards compatibility, it should be generated in addition to the un-unified versions.
Sorry for the long delay before circling back on this, haven’t had time to try and dig into editing the spec but we also don’t need/want this as urgently as 6 months ago; ran into performance/filesize problems after all, so our approach has changed and doesn’t rely on
@extend
anymore.