- Status: Accepted (CSS naming convention superseded by ADR 0006)
- Date: 2026-02-02
- Decision makers: EDS Core Team
EDS 1.x uses styled-components for all component styling. While this worked well initially, we've encountered several issues as the ecosystem evolved:
- SSR hydration mismatches in Next.js App Router and React Server Components
- Runtime overhead from CSS-in-JS (style injection, prop interpolation)
- Bundle size impact (styled-components adds ~13KB minified + gzipped to the bundle)
- Developer experience issues with style debugging and DevTools inspection
- React 19 compatibility concerns as the React team moves away from CSS-in-JS patterns
- styled-components is in maintenance mode – In March 2025, the styled-components maintainers announced that the project has entered maintenance mode. They stated: "For new projects, I would not recommend adopting styled-components or most other css-in-js solutions" due to ecosystem shifts and React Server Components limitations.
For EDS 2.0, we need a styling approach that is future-proof and works seamlessly with modern React frameworks.
- Must support Server-Side Rendering without hydration issues
- Must work with React Server Components
- Should minimize runtime JavaScript overhead
- Should leverage our existing design token system (
@equinor/eds-tokens) - Developers must be able to customize and override styles
- Should be familiar to web developers (low learning curve)
- Must support theming (light/dark mode, density modes)
Scoped CSS with automatic class name generation.
Pros:
- Automatic scoping prevents style collisions
- Works with SSR
- Familiar CSS syntax
Cons:
- Class name hashing makes debugging harder
- Harder to override styles from consuming applications
- Less flexible for theming compared to CSS custom properties
Utility-first CSS framework.
Pros:
- Rapid development with utility classes
- Small production bundle (purged unused styles)
- Works with SSR
Cons:
- Verbose className strings reduce readability
- Adds external dependency and build complexity
- Utility classes don't align well with design token architecture
- Harder for consumers to understand component styling
Continue with current CSS-in-JS approach.
Pros:
- Team is already familiar with it
- Type-safe props-based styling
- Automatic scoping
Cons:
- SSR hydration issues with modern React frameworks
- Runtime overhead
- Uncertain future with React Server Components
- Project is now in maintenance mode with no new features planned
We will use vanilla CSS with CSS custom properties for EDS 2.0 components.
Components will:
- Import a co-located
.cssfile (e.g.,button.css) - Use CSS custom properties from
@equinor/eds-tokensfor all design values - Use
data-*attributes for variant styling (e.g.,data-variant="primary") - Use CSS
@layerfor style encapsulation and specificity control - Follow BEM-inspired naming for CSS classes (e.g.,
.eds-button,.field__label)
Example pattern:
// Button.tsx
import './button.css'
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ variant = 'primary', ...rest }, ref) => (
<button ref={ref} className="eds-button" data-variant={variant} {...rest} />
),
)/* button.css */
@layer eds-components {
.eds-button {
background: var(--eds-color-bg-fill-emphasis-default);
padding: var(--eds-selectable-space-vertical)
var(--eds-selectable-space-horizontal);
}
.eds-button[data-variant='secondary'] {
background: transparent;
border: 1px solid var(--eds-color-border-strong);
}
}- Good, because zero runtime JavaScript for styling gives better performance
- Good, because native SSR support means no hydration issues with Next.js App Router or RSC
- Good, because excellent debugging experience with browser DevTools
- Good, because CSS custom properties enable theming without re-rendering components
- Good, because it's familiar technology with lower learning curve for contributors
- Good, because it's future-proof and aligns with where the React ecosystem is heading
- Good, because smaller bundle size without CSS-in-JS runtime
- Bad, because requires discipline with naming conventions (BEM) and
@layerfor scoping - Bad, because less type-safety for style values compared to TypeScript-based CSS-in-JS
- Bad, because consumers need to ensure CSS is imported in their applications
- Bad, because it's a breaking change from EDS 1.x requiring migration effort for consumers
- Code reviews verify that new
/nextcomponents use vanilla CSS, not styled-components - All CSS files in
/nextmust use@layer eds-componentsfor encapsulation - Design token usage is validated through existing token linting