Skip to content

CSS Styles#

To ensure flexibility and the possibility of theming, the DNB CSS Styles are built in a bottom-up manner.

The styles are decoupled from the functional components. There are several packages you can use and combine.

Main Packages#

  • dnb-ui-core: includes the DNB Main Styles like helper classes, HTML and body reset (normalize).
    • We have an alternative package, dnb-ui-basis, that can be used if your page has other CSS that conflicts with Eufemia. It does the same but adds resets to the .dnb-core-style class instead of the body element, so Eufemia styling can be scoped to just a part of your page. NB: requires a .dnb-core-style wrapper class.

For print pagination, import the optional print styles after your core and brand styles and apply .dnb-print to light-themed printable content. This does not make an entire app print-ready or switch dark mode off. Add the separate document styles with .dnb-document when you also need document typography and spacing.

Theme Packages#

Additional Theme Packages#

  • ui-theme-properties: includes only the CSS Custom Properties. You can find this package inside /style/themes/ui/.
  • ui-theme-extensions: includes all the styles (and themes) for extensions (not shown in the Diagram).

All the CSS packages are ready to use, minified CSS files. You will find the main style here: @dnb/eufemia/style/dnb-ui-core.min.css

Individual styles#

Additionally, it is also possible to import a style and theme for every single component separately. You can find the styles here: @dnb/eufemia/components/{button}/style/dnb-{button}.min.css. Read more about how to import a single-component style.

CSS Structure Diagram#

The following Diagram gives an overall overview how the packages are structured.

CSS Structure Diagram

How to deal with existing styles#

The dnb-ui-core package includes some styles that affect the global scope (<body> reset). To avoid interference with existing styles, such as a header or menu, you could use only the dnb-ui-basis package in combination with other packages like ui-theme-basis and ui-theme-components.

Example import#

// NB: needs a wrapper class: ".dnb-core-style"
import '@dnb/eufemia/style/basis'
import '@dnb/eufemia/style/themes/ui'
// instead of all together
/* import '@dnb/eufemia/style' */

Core Style#

To have the Eufemia Core styles inside a wrapper anyway, simply use the following helper class: .dnb-core-style:

<body>
<p>I'm not Eufemia</p>
<!-- Wrapper to have correct Eufemia css reset and styles -->
<div id="app" class="dnb-core-style">
<h1 class="dnb-h--xx-large">I have an Eufemia Style</h1>
<p class="dnb-p">👉 Me as well</p>
</div>
</body>

CSS Specificity#

Element resets use :where(.dnb-core-style) for their wrapper selector. A component class can override defaults such as font size, line height, and margins without adding .dnb-core-style to its selector.

Some typography and spacing rules still include .dnb-core-style in their selectors. When overriding those rules, you may need to include it to match their specificity.

For Styled Components you do it this way:

import { P } from '@dnb/eufemia'
const MyElement = styled(P)`
.dnb-core-style & {
margin-top: 3rem;
}
color: var(--color-sky-blue);
`

In CSS you simply do it this way:

.dnb-core-style .my-element {
margin-top: 3rem;
color: var(--color-sky-blue);
}

Spacing for Articles#

To ensure more flexibility in styling, all margins/spacings are reset to zero. However, we often need default spacing defined, such as margin on HTML elements like headings or paragraphs.

To use the default DNB spacings, define a CSS class called .dnb-spacing. HTML elements inside this container will then have default spacing. This is especially helpful for article-like pages.

<article class="dnb-spacing">
<!-- DNB spacings -->
<h1 class="dnb-h--xx-large">
e.g., I now have Eufemia spacing (margin)
</h1>
<p class="dnb-p">👉 Me as well</p>
</article>

The styles for .dnb-spacing are included in the package: ui-theme-basis. For more details, check out the source file: spacing.scss.

A list of all CSS properties (variables)#

Beside the portal documentation with related tables and additional information, you may have a look at the CSS file containing the custom properties (CSS variables), as well as a JavaScript file that is auto-generated from the CSS data.

The UI theme's properties.scss keeps concrete rem values synced from the Figma export and can be imported on its own. Each theme loads its generated typography values through theme-mapping.scss. The generated properties.js files include the values for each brand. Font sizes and line heights do not change in dark mode. None of these imports requires a separate token stylesheet.

Access CSS properties (variables) in JavaScript#

import properties from '@dnb/eufemia/style/themes/ui/properties.js'
const seaGreenColor = properties['--color-sea-green']
const basisFontSize = properties['--font-size-basis']

Using Tailwind with Eufemia#

Tailwind can act as a utility layer on top of (or beside) Eufemia. Keep Eufemia as the single source of tokens, colors, spacing, typography, CSS reset, etc.

Guidelines:

  • Keep Eufemia resets: use either @dnb/eufemia/style (global) or the scoped combo basis + themes.
  • Disable Tailwind's preflight (its reset) to avoid collisions.
  • Let Tailwind generate utilities and its theme layer.

You can import the pre-generated properties-tailwind.css files that contain all Eufemia CSS custom properties in Tailwind-compatible format:

/* Import Tailwind layers */
@layer eufemia, theme, utilities;
/* Import Eufemia styles */
@import '@dnb/eufemia/style/dnb-ui-core.min.css' layer(eufemia);
@import '@dnb/eufemia/style/themes/ui/ui-theme-components.min.css'
layer(eufemia);
@import '@dnb/eufemia/style/themes/ui/ui-theme-basis.min.css'
layer(eufemia);
/* Import Tailwind base, theme and utilities layers */
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/utilities.css' layer(utilities);
/* Import Eufemia properties in Tailwind format */
@import '@dnb/eufemia/style/themes/ui/properties-tailwind.css'
layer(utilities);
/* Import Eufemia design tokens in Tailwind format */
@import '@dnb/eufemia/style/themes/ui/tokens-tailwind.css' layer(utilities);

Tailwind-Compatible CSS Variables#

The properties-tailwind.css files contain Eufemia's CSS custom properties transformed to be compatible with Tailwind CSS. This transformation makes Eufemia properties available as Tailwind theme variables.

Available Namespaces#

The following CSS variable namespaces are available in Tailwind-compatible format:

  • --color-* - Color variables (e.g., --color-black, --color-sea-green, --color-sky-blue)
  • --font-* - Font family variables (e.g., --font-default, --font-heading) - converted from --font-family-*
  • --font-weight-* - Font weight variables (e.g., --font-weight-default, --font-weight-medium)
  • --text-* - Font size variables (e.g., --text-small, --text-large) - converted from --font-size-*
  • --leading-* - Line height variables (e.g., --leading-small, --leading-medium) - converted from --line-height-*
  • --spacing-* - Spacing variables (e.g., --spacing-small, --spacing-large)
  • --shadow-* - Box shadow variables (e.g., --shadow-default, --shadow-sharp)
  • --ease-* - Transition timing function variables (e.g., --ease-default) - converted from --easing-*
  • --breakpoint-* - Responsive breakpoint variables (e.g., --breakpoint-small, --breakpoint-large) - converted from --layout-*

Brand-Specific Variables#

For brand-specific properties, variables are transformed to include the brand identifier after the namespace.

For Sbanken, the following namespaces are available:

  • --color-sb-* - (e.g., --color-sb-purple, --color-sb-green)
  • --font-weight-sb-* - (e.g., --font-weight-sb-default, --font-weight-sb-medium)
  • --text-sb-* - (e.g., --text-sb-small, --text-sb-large)
  • --spacing-sb-* - (e.g., --spacing-sb-small, --spacing-sb-large)
  • --shadow-sb-* - (e.g., --shadow-sb-small, --shadow-sb-medium)
  • --ease-sb-* - (e.g., --ease-sb-default)
  • --breakpoint-sb-* - (e.g., --breakpoint-sb-small, --breakpoint-sb-large)

This makes Eufemia properties directly usable with Tailwind's utility classes while maintaining brand-specific variants.

Semantic Design Tokens#

In addition to the theme properties above, Eufemia provides design tokens via tokens-tailwind.css. Color tokens express semantic roles (e.g., "background for an action element") and reference foundation colors. Radius tokens provide brand values.

The --token- prefix from tokens.scss is stripped. Color tokens map to Tailwind's --color-* namespace:

  • --color-background-* - Background colors (e.g., --color-background-action, --color-background-error-subtle)
  • --color-text-* - Text colors (e.g., --color-text-neutral, --color-text-action)
  • --color-icon-* - Icon colors (e.g., --color-icon-neutral, --color-icon-action)
  • --color-stroke-* - Border/stroke colors (e.g., --color-stroke-action, --color-stroke-error)
  • --color-decorative-* - Decorative colors (e.g., --color-decorative-first-base, --color-decorative-second-muted)
  • --color-component-* - Component-specific tokens (e.g., --color-component-button-background-action)

This allows usage like:

<div class="bg-background-action text-text-neutral border-stroke-action">
Styled with semantic tokens
</div>

The tokens-tailwind.css files are available for all themes: ui, sbanken, and carnegie.

For Tailwind font-size and line-height utilities, use the --text-* and --leading-* values from properties-tailwind.css. For example, leading-basis uses --leading-basis, the Tailwind equivalent of --line-height-basis.

Z-Index Scale#

Eufemia defines a centralized z-index scale using CSS Custom Properties. This ensures consistent layering across all components and makes the stacking order discoverable and adjustable from a single place.

The following tokens are defined on :root and control the stacking order of Eufemia components:

TokenDefault valueUsage
--z-index-section1Content sections
--z-index-dropdown100Inline dropdowns, drawer-lists
--z-index-popover1000Popovers, floating elements
--z-index-tooltip1100Tooltips (always above popovers)
--z-index-modal3000Dialogs, drawers, full overlays

Each component also exposes its own CSS Custom Property that references the centralized token. This preserves backward compatibility for consumers who override the component-level property directly.

ComponentComponent propertyReferences
Section--section-z-indexvar(--z-index-section)
Popover--popover-z-indexvar(--z-index-popover)
Tooltip--tooltip-z-indexvar(--z-index-tooltip)
Modal--modal-z-indexvar(--z-index-modal)

You can override the global z-index scale to adjust the layering for your application:

:root {
--z-index-modal: 9999;
}

Or override a single component's z-index:

:root {
--modal-z-index: 5000;
}

Known styling and CSS issues#

  • Safari, both on mobile and desktop, has a problem where we combine border-radius with the usage of inset in a box-shadow. The solution for now is to not use inset, which results in an outer border. This is not ideal as we don't follow the UX guidelines for these browsers. We have an SCSS mixin handling this for us: @mixin fakeBorder.
Suggest an edit