Problem to solve
The current Vuetify CSS layer architecture uses a monolithic, single-top-level layer. While this provides excellent encapsulation, it creates significant conflict and inflexibility when integrating with other layered CSS frameworks (e.g. Tailwind).
The core problem is that the entire vuetify layer is treated as a single priority block. A typical integration requires certain framework elements (like base styles and components) to have a low priority (allowing utilities to win), while other critical elements (like transition states or necessary accessibility overrides) must have a high priority (trumping utilities).
If a consumer defines the cascade as @layer tailwind, vuetify, all Vuetify styles win, breaking utility-first overrides. If defined as @layer vuetify, vuetify, all Vuetify styles lose, causing critical state styles to be overridden by generic utilities (e.g., a transition state's opacity: 0 is beaten by a utility's opacity: 0.9).
The goal is to allow consumers to interleave Vuetify's styles with a third-party framework's styles by splitting the Vuetify output into multiple top-level layers, providing fine-grained control over the cascade priority.
The existing layer definition is:
@layer vuetify {
@layer reset, base, components, transitions;
@layer overrides;
@layer theme.background, theme.foreground, utilities;
@layer trumps;
@layer custom;
}
Proposed solution
A: Keep the Current Nested Structure
Maintain the existing single top-level layer (@layer vuetify). All internal layers remain nested beneath this single identifier.
Pros:
- Simplest implementation.
- Zero risk of global namespace collisions with other layer names (e.g., a consumer's components layer).
- Consumer only has to define one layer.
- Impossible to break styles by accidentally changing the order of sub-layers.
Cons:
- Breaks interoperability. Consumers are forced to choose between "Vuetify always wins" or "Vuetify always loses".
- Interleaving is only possible by also nesting other layers under
@layer vuetify.
- Developers may resort to using !important, defeating the purpose of layers.
B: Fully Flat Namespace
Eliminate the single top-level vuetify wrapper. All current nested layers are promoted to top-level vendor-prefixed layers.
@layer vuetify-reset, vuetify-base, vuetify-components, vuetify-overrides, vuetify-theme, vuetify-utilities, vuetify-transitions, vuetify-trumps;
Pros:
- Maximum flexibility. Consumers can place any Vuetify layer anywhere in their global cascade for precise control, e.g.
@layer vuetify-overrides, application, vuetify-utilities, tailwind.
Cons:
- Higher burden on the consumer, they must define 8 layers in their global cascade order in order to customise anything.
- Very vulnerable to incorrect layer ordering.
- If we ever need to add a new layer for some reason that would be a breaking change.
C: Partial Split
Split the Vuetify layer into three top-level layers based on priority requirements. All existing internal nesting is maintained within these new layers.
@layer vuetify-core {
@layer reset, base, components, overrides;
}
@layer vuetify-utilities {
@layer theme.background, theme.foreground;
/* The rest of the utility classes can go here,
will have higher priority than theme */
}
@layer vuetify-final {
@layer transitions;
@layer trumps;
}
Customisation would look like this:
@layer vuetify-core;
@layer vuetify-utilities;
@layer tailwind;
@layer vuetify-final;
Pros:
- Allows consumers to somewhat interleave their layers with ours.
- The consumer only needs to manage two additional top-level layers in their global cascade.
- Internal layers (reset, components, etc.) remain nested, reducing global namespace pollution and complexity.
Cons:
- Still possible for Vuetify layers to end up in the incorrect order, although this is mostly mitigated by at least keeping components and overrides together.
Problem to solve
The current Vuetify CSS layer architecture uses a monolithic, single-top-level layer. While this provides excellent encapsulation, it creates significant conflict and inflexibility when integrating with other layered CSS frameworks (e.g. Tailwind).
The core problem is that the entire vuetify layer is treated as a single priority block. A typical integration requires certain framework elements (like base styles and components) to have a low priority (allowing utilities to win), while other critical elements (like transition states or necessary accessibility overrides) must have a high priority (trumping utilities).
If a consumer defines the cascade as
@layer tailwind, vuetify, all Vuetify styles win, breaking utility-first overrides. If defined as@layer vuetify, vuetify, all Vuetify styles lose, causing critical state styles to be overridden by generic utilities (e.g., a transition state'sopacity: 0is beaten by a utility'sopacity: 0.9).The goal is to allow consumers to interleave Vuetify's styles with a third-party framework's styles by splitting the Vuetify output into multiple top-level layers, providing fine-grained control over the cascade priority.
The existing layer definition is:
Proposed solution
A: Keep the Current Nested Structure
Maintain the existing single top-level layer (
@layer vuetify). All internal layers remain nested beneath this single identifier.Pros:
Cons:
@layer vuetify.B: Fully Flat Namespace
Eliminate the single top-level vuetify wrapper. All current nested layers are promoted to top-level vendor-prefixed layers.
Pros:
@layer vuetify-overrides, application, vuetify-utilities, tailwind.Cons:
C: Partial Split
Split the Vuetify layer into three top-level layers based on priority requirements. All existing internal nesting is maintained within these new layers.
Customisation would look like this:
Pros:
Cons: