Roma’s Unpolished Posts

Layer Overrides Update

Published on:
Categories:
CSS Layers 3, CSS Overrides 4, CSSWG 2, CSS 37
Current drink:
Camomile tea

Two days ago, I wrote an Unlayered Styles Issue post, where I shared a link to my comment in a GitHub issue about unlayered styles.

Since then, there was a brief discussion, after which the issue was reopened — yay!

Now, the question is: what should be the direction the issue would move towards. There were a few different proposals over how to allow putting styles after the unlayered ones, the best one was first proposed by François REMY:

Another possibility is to add another layer that is not the unstyled layers but is one just after it. Then confusion drops a lot I guess, especially if we give it a better name.

Something like @layer !important.xyz { ... } where the !important layer is a special layer that is above the unstyled styles.

I did not first see this proposal, but after some thinking did propose essentially the same in my most recent comment there:

After some thoughts, my idea: what if we’d have a single, system layer which could be used to place other layers after the unlayered styles?

Let’s say this system layer would be named !overrides. Then, let’s say it places nested styles after the unlayered styles only within the same parent layer (if any).

What this would mean:

  1. We cannot create an arms race, as we have only one entry point for every layer that can be used to put styles into an “overrides” part.
  2. As we can put other layers inside this layer, we could continue to write our new styles using layers in any way.
  3. We don’t need to handle any specific syntax or complexity outside adding this one specific named layer.

See — basically a repeat of what François wrote.

I really think this is the best out of all proposals there. And, I think I could even use it inside the other layered styles I could write, as a way to first write some unlayered defaults:

@layer my-component {
	.my-component {
		/* some styles */

		&:is(:hover, :focus-visible) {}
		& + & {}
		/* some other styles with any specificity */
	}
}

Then, if I would want to add some modifiers to this component (let’s put aside if we actually want to have a layer per component), but would like these modifiers to go over the component’s styles, I could do this:

@layer my-component {
	.my-component {
		/* some styles */

		&:is(:hover, :focus-visible) {}
		& + & {}
		/* some other styles with any specificity */

		@layer !overrides {
			&:disabled {
				/* Some styles, now guaranteed over any
				   default styles. */
			}
		}
	}
}

If I wanted to add multiple different layers as overrides, then I could either use the same dot notation to make each of them @layer !overrides.disabled etc., or I could nest (or import!) these as their layers inside our overrides:

@layer my-component {
	.my-component {
		/* some styles */

		&:is(:hover, :focus-visible) {}
		& + & {}
		/* some other styles with any specificity */

		@layer !overrides {
			@layer disabled {
				&:disabled {
					/* Some styles, now guaranteed over any
					   default styles. */
				}
			}

			@layer something-else {}
		}
	}
}

But, of course, the main profit would come from an ability to add any styles after unlayered styles in the topmost unlayered context, where there is no a single parent layer surrounding our content. All these cases would become possible:

There are so many cases where I would already start using CSS layers, but can’t because there are some unlayered styles getting in the way. I really hope we would get the ability to do something about this sooner rather than later.

Please share your thoughts about this on Mastodon!