Skip to content

## Bug: @layer cascade order causes EaseMotion base styles to be overridden by other CSS frameworks #1375

@Pcmhacker-piro

Description

@Pcmhacker-piro

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

  1. 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" />
  2. Create a card using EaseMotion classes:
    <div class="ease-card ease-card-shadow">
      <p>This text should use EaseMotion typography</p>
    </div>
  3. 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

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions