Bug: @layer cascade order causes EaseMotion base styles to be overridden by other CSS frameworks
Description
When EaseMotion-css is loaded alongside other CSS frameworks (Tailwind, Bootstrap) that also use @layer, the cascade layer ordering may not prioritize EaseMotion's base/reset styles correctly. Depending on import order, EaseMotion's base layer styles can be unintentionally overridden, causing typography resets and custom properties to not apply.
Steps to Reproduce
- Create an HTML page that imports both Bootstrap 5 and EaseMotion-css:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easemotion-css/easemotion.css" />
- Create a card using EaseMotion classes:
<div class="ease-card ease-card-shadow">
<p>This text should use EaseMotion typography</p>
</div>
- Inspect the computed styles for the body and paragraph text
Expected Behavior
EaseMotion's base styles (typography, custom properties) should apply correctly regardless of what other CSS is loaded, as long as the EaseMotion stylesheet is included.
Actual Behavior
EaseMotion-css defines its cascade layers in easemotion.css:
@layer base, components, utilities;
Bootstrap 5 defines its own layers. The browser computes the final layer order based on the first occurrence of each layer name across all stylesheets. If Bootstrap is loaded first, its base layer takes priority over EaseMotion's base layer (or vice versa), depending on arbitrary import order. The result is that either Bootstrap or EaseMotion styles may win unpredictably.
Additionally, EaseMotion's @layer base { ... } wraps its CSS reset, which includes :root custom property declarations. When another framework's layer takes precedence, all --ease-* custom properties may become unavailable in subsequent layers.
Implementation Hints
The issue is in easemotion.css (or whichever entry point defines the @layer declarations):
/* Current — ambiguous layer ordering */
@layer base, components, utilities;
@layer base {
/* Reset, typography, variables */
}
@layer components {
/* Component styles */
}
The fix should use a unique layer name prefix and declare layers with explicit priority:
/* Fixed — use unique layer names to avoid cross-framework conflicts */
@layer easemotion.base, easemotion.components, easemotion.utilities;
@layer easemotion.base {
:root {
--ease-primary: #6366f1;
/* ... other variables */
}
}
/* Alternatively, avoid @layer entirely for base styles that must always apply */
/* Move :root variables and base reset outside @layer so they are unlayered */
:root {
--ease-primary: #6366f1;
/* ... */
}
/* Use @layer only for component-specific overrides */
@layer easemotion.components {
/* ... */
}
The most reliable approach is to keep :root custom property declarations outside any @layer block, since unlayered styles always beat layered styles in the cascade. Component styles can remain in layers for easier override.
/* :root variables — unlayered, always apply */
:root {
--ease-primary: #6366f1;
--ease-radius: 8px;
/* ... */
}
/* Reset — unlayered */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Component styles — layered for organized override */
@layer easemotion {
/* ... */
}
Affected Files
easemotion.css — @layer declaration and ordering, :root custom properties inside layered blocks
core/base.css — CSS reset inside @layer base
core/variables.css — custom property definitions in @layer base
Labels
type:bug, level:intermediate, GSSoC-26
Bug:
@layercascade order causes EaseMotion base styles to be overridden by other CSS frameworksDescription
When EaseMotion-css is loaded alongside other CSS frameworks (Tailwind, Bootstrap) that also use
@layer, the cascade layer ordering may not prioritize EaseMotion's base/reset styles correctly. Depending on import order, EaseMotion'sbaselayer styles can be unintentionally overridden, causing typography resets and custom properties to not apply.Steps to Reproduce
Expected Behavior
EaseMotion's base styles (typography, custom properties) should apply correctly regardless of what other CSS is loaded, as long as the EaseMotion stylesheet is included.
Actual Behavior
EaseMotion-css defines its cascade layers in
easemotion.css:Bootstrap 5 defines its own layers. The browser computes the final layer order based on the first occurrence of each layer name across all stylesheets. If Bootstrap is loaded first, its
baselayer takes priority over EaseMotion'sbaselayer (or vice versa), depending on arbitrary import order. The result is that either Bootstrap or EaseMotion styles may win unpredictably.Additionally, EaseMotion's
@layer base { ... }wraps its CSS reset, which includes:rootcustom property declarations. When another framework's layer takes precedence, all--ease-*custom properties may become unavailable in subsequent layers.Implementation Hints
The issue is in
easemotion.css(or whichever entry point defines the@layerdeclarations):The fix should use a unique layer name prefix and declare layers with explicit priority:
The most reliable approach is to keep
:rootcustom property declarations outside any@layerblock, since unlayered styles always beat layered styles in the cascade. Component styles can remain in layers for easier override.Affected Files
easemotion.css—@layerdeclaration and ordering,:rootcustom properties inside layered blockscore/base.css— CSS reset inside@layer basecore/variables.css— custom property definitions in@layer baseLabels
type:bug,level:intermediate,GSSoC-26