DevExtreme Vue - Fluent Next Theme Customization

Fluent Next themes build on the DevExpress Design System and support multiple customization options.

DevExtreme Fluent Next themes

CSS Variables

Fluent Next themes ship with CSS variables defined in the DevExpress Design System. Refer to the following help topics for additional information about key styling principles and for a list of available CSS variables:

Variable Naming Convention

The following naming convention applies to CSS variables in Fluent Next themes:

  • --dxds-*
    Design System CSS variables that serve as public APIs. Use these variables to customize your DevExtreme-powered application.

  • --dx-*
    Internal CSS variables used by DevExtreme components. Undocumented variables may change between versions. Fluent Next themes also declare legacy --dx-* variables from other DevExtreme themes (for instance, --dx-color-primary and --dx-font-size) and map them to Design System variables. For more information, refer to the following section: Legacy Variable Migration.

  • --dx-viz-*
    CSS variables used by SVG-based components. For more information, refer to the following section: SVG-Based Component Colors.

CSS Variable Use

You can apply Design System variables to custom elements to ensure a consistent look across your application. The following example uses Design System variables for rest and hover states:

CSS
.info-card {
    /* Surface and content colors */
    background-color: var(--dxds-color-bg);
    color: var(--dxds-color-content);

    /* Spacing */
    padding: var(--dxds-spacing-240);
    margin-bottom: var(--dxds-spacing-160);

    /* Borders */
    border: var(--dxds-border-width-10) solid var(--dxds-color-border);
    border-radius: var(--dxds-border-radius-40);

    /* Typography */
    font-size: var(--dxds-font-size-base-md);
    line-height: var(--dxds-line-height-base-md);

    /* Shadow */
    box-shadow: var(--dxds-box-shadow-sm);
}

.info-card:hover {
    background-color: var(--dxds-color-bg-hovered);
    border-color: var(--dxds-color-border-hovered);
}

CSS Variable Overrides

You can override Design System variables to modify default Fluent Next styles. To override variables for an entire page, use the :root selector:

CSS
:root {
    --dxds-color-bg-primary: #b06ab3;
}
NOTE

Note the following when you define :root overrides:

  • :root overrides and Fluent Next stylesheets share the same specificity. Load your override stylesheet after the Fluent Next stylesheet to apply your overrides. Scoped overrides that use class or ID selectors are applied regardless of load order.
  • Theme mode containers redeclare variables that have different values in light and dark modes (for instance, --dxds-color-bg and --dxds-color-content-primary). :root overrides for these variables do not apply to elements within dx-theme-mode-* containers. To customize these variables within a theme mode container, define overrides for the container and include the mode class in the selector:

    CSS
    .sidebar.dx-theme-mode-dark {
        --dxds-color-bg: #1f1f1f;
    }

CSS variable overrides also allow you to modify DevExtreme component styles. You can define overrides for individual components or for a container that wraps multiple components. These overrides allow you to apply unique styles to different parts of your application. The following code snippet overrides semantic variables:

CSS
/* Using dxds variables */
.custom-colors-var {
    --dxds-color-bg: var(--dxds-color-bg-inverted);
    --dxds-color-content: var(--dxds-color-content-inverted);
    --dxds-color-border: var(--dxds-color-border-inverted);
}

/* Using custom colors */
.custom-colors-hex {
    --dxds-color-bg: #341A51;
    --dxds-color-content: #F5F0FA;
    --dxds-color-border: #532982;
}

Components that display content in overlays do not apply styles from the component element to overlay content. Use one of the following approaches to style overlay content:

  1. Use a .dx-swatch-* Component Container
    If you initialize an overlay component in a container with a dx-swatch-* class, DevExtreme nests the component's overlay wrapper in a container with the same dx-swatch-* class. Use this class in your override definitions to style the overlay content.

    jQuery
    index.html
    index.js
    <html>
        <!-- ... -->
        <body class="dx-viewport">
            <div class="dx-swatch-myswatch">
                <div id="popup"></div> <!-- Styles defined for .dx-swatch-myswatch will apply to the Popup content -->
            </div>
        </body>
    </html>
    $('#popup').dxPopup({
        // ...
    });
    Angular
    app.component.html
    app.component.ts
    <div class="dx-swatch-myswatch">
        <dx-popup></dx-popup> <!-- Styles defined for .dx-swatch-myswatch will apply to the Popup content -->
    </div>
    import { Component } from '@angular/core';
    import { DxPopupModule } from 'devextreme-angular';
    
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        imports: [DxPopupModule, /* ... */],
    })
    export class AppComponent {
        // ...
    }
    Vue
    App.vue
    <template>
        <div class="dx-swatch-myswatch">
            <DxPopup /> <!-- Styles defined for .dx-swatch-myswatch will apply to the Popup content -->
        </div>
    </template>
    
    <script setup lang="ts">
    import { DxPopup } from 'devextreme-vue/popup';
    
    </script>
    React
    App.tsx
    import { Popup } from 'devextreme-react/popup';
    
    export default function App() {
        return (
            <div className="dx-swatch-myswatch">
                <Popup /> {/* Styles defined for .dx-swatch-myswatch will apply to the Popup content */}
            </div>
        );
    }

    Note that DevExtreme does not generate .dx-swatch-* wrapper containers for components if you define their container property.

  2. Use wrapperAttr Properties
    You can define the following properties to add selector attributes to overlay wrappers:

    • wrapperAttr: Specify this property in overlay components (Popup, Popover, Toast, LoadPanel).
    • dropDownOptions.wrapperAttr: Specify this property in editors that display drop-downs (SelectBox, Lookup, DateBox, ColorBox, DropDownBox, DropDownButton, Autocomplete).
    jQuery
    index.js
    $("#popup").dxPopup({
        wrapperAttr: {
            class: "custom-colors-hex",
        },
    });
    
    $("#selectBox").dxSelectBox({
        dropDownOptions: {
            wrapperAttr: {
                class: "custom-colors-hex",
            },
        },
    });
    Angular
    app.component.html
    app.component.ts
    <dx-popup
        [wrapperAttr]="wrapperAttr"
    ></dx-popup>
    <dx-select-box>
        <dxo-select-box-drop-down-options
            [wrapperAttr]="wrapperAttr"
        ></dxo-select-box-drop-down-options>
    </dx-select-box>
    import { Component } from '@angular/core';
    import { DxPopupModule, DxSelectBoxModule } from 'devextreme-angular';
    
    @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        imports: [DxPopupModule, DxSelectBoxModule, /* ... */],
    })
    export class AppComponent {
        wrapperAttr = {
            class: 'custom-colors-hex',
        };
    }
    Vue
    App.vue
    <template>
        <DxPopup
            :wrapper-attr="wrapperAttr"
        />
        <DxSelectBox>
            <DxDropDownOptions
                :wrapper-attr="wrapperAttr"
            />
        </DxSelectBox>
    </template>
    
    <script setup lang="ts">
    import { DxPopup } from 'devextreme-vue/popup';
    import { DxSelectBox, DxDropDownOptions } from 'devextreme-vue/select-box';
    
    const wrapperAttr = {
        class: 'custom-colors-hex',
    };
    </script>
    React
    App.tsx
    import { Popup } from 'devextreme-react/popup';
    import { SelectBox, DropDownOptions } from 'devextreme-react/select-box';
    
    const wrapperAttr = {
        class: 'custom-colors-hex',
    };
    
    export default function App() {
        return (
            <>
                <Popup
                    wrapperAttr={wrapperAttr}
                />
                <SelectBox>
                    <DropDownOptions
                        wrapperAttr={wrapperAttr}
                    />
                </SelectBox>
            </>
        );
    }

You can also use CSS variable overrides to apply custom or utility palette colors to specific parts of your application:

CSS
/* Utility palette colors */
.yellow-utility {
    --dxds-color-bg: var(--dxds-color-bg-yellow-subtle);
    --dxds-color-border: var(--dxds-color-border-yellow);
}

/* Custom colors */
.yellow-custom {
    --dxds-color-bg: #F2C661;
    --dxds-color-content: #3F2900;
    --dxds-color-border: #EDAD1C;
}

SVG-Based Component Colors

SVG-based components (such as charts and gauges) use --dx-viz-* CSS variables in Fluent Next themes to paint elements. These themes ship with the Fluent Next palette, which defines the following color sets:

Color Set CSS Variables
simpleSet
  • --dx-viz-blue
  • --dx-viz-red
  • --dx-viz-green
  • --dx-viz-yellow
  • --dx-viz-pink
  • --dx-viz-purple
indicatingSet
  • --dx-viz-success
  • --dx-viz-warning
  • --dx-viz-danger
gradientSet
  • --dx-viz-blue
  • --dx-viz-green
NOTE

Accent colors in Fluent Next themes only apply to HTML-based components and to the following RangeSelector elements:

  • Selected range
  • Slider handles
  • Slider markers

You can override palette variables to change colors in all SVG-based components:

CSS
:root {
    --dx-viz-blue: #0063b1;
    --dx-viz-red: #d13438;
}

Load your override stylesheet after the Fluent Next stylesheet. Palette variables apply to all Fluent Next variations (light and dark modes, standard and compact sizes), so :root overrides also apply to components in theme mode containers. SVG-based components apply CSS variable changes immediately, and you do not need to call refreshTheme().

--dx-viz-* color overrides also apply to palette extensions. An SVG-based component automatically extends the applied palette based on an extension mode when the component needs more colors than the palette contains. The generateColors(palette, count, options) utility method also uses color overrides.

Methods that return colors (for instance, a Chart point's getColor()) return resolved colors used to render elements. These methods return opaque colors in hexadecimal format and colors with transparency in rgba() format.

Legacy Variable Migration

DevExtreme themes other than Fluent Next use internal --dx-* variables instead of Design System variables to define shared CSS values such as colors. To support migration from these themes, Fluent Next themes declare these--dx-* variables and map them to Design System variables. This section lists mapped variables and corresponding public --dxds-* variables that you should migrate to.

The following table lists color variables. Fluent Next themes declare these variables in the :root scope and on elements that use container-specific theme modes:

Legacy Variable Design System Variable
--dx-color-primary --dxds-color-content-primary
--dx-color-link --dxds-color-content-primary
--dx-color-success --dxds-color-content-success
--dx-color-warning --dxds-color-content-warning
--dx-color-danger --dxds-color-content-danger
--dx-color-text --dxds-color-content
--dx-color-icon --dxds-color-content-subtle
--dx-color-spin-icon --dxds-color-content-subtle
--dx-texteditor-color-label --dxds-color-content-subtle
--dx-color-main-bg --dxds-color-bg-canvas
--dx-component-color-bg --dxds-color-bg
--dx-datagrid-row-alternation-bg --dxds-color-bg-low
--dx-color-options-panel-bg --dxds-color-bg-inverted with --dxds-opacity-5 opacity
--dx-color-border --dxds-color-border
--dx-color-separator --dxds-color-border-subtle

The following table lists size variables for standard and compact sizes. Fluent Next themes declare these variables in the :root scope:

Legacy Variable Design System Variable (Standard Size) Design System Variable (Compact Size)
--dx-font-size --dxds-font-size-base-md --dxds-font-size-base-sm
--dx-font-size-xs --dxds-font-size-120 --dxds-font-size-120
--dx-font-size-sm --dxds-font-size-180 --dxds-font-size-140
--dx-font-size-md --dxds-font-size-200 --dxds-font-size-160
--dx-font-size-lg --dxds-font-size-280 --dxds-font-size-200
--dx-font-size-xl --dxds-spacing-340 (34px, not included in the font size scale) --dxds-font-size-240
--dx-font-size-heading-1 --dxds-font-size-headline-xl --dxds-font-size-headline-lg
--dx-font-size-heading-2 --dxds-font-size-headline-lg --dxds-font-size-headline-md
--dx-font-size-heading-3 --dxds-font-size-headline-md --dxds-font-size-headline-sm
--dx-font-size-heading-4 --dxds-font-size-headline-sm --dxds-font-size-title-md
--dx-font-size-heading-5 --dxds-font-size-title-md --dxds-font-size-title-sm
--dx-font-size-heading-6 --dxds-font-size-title-sm --dxds-font-size-title-xs
--dx-font-size-icon --dxds-spacing-200 --dxds-spacing-160
--dx-component-height --dxds-spacing-320 --dxds-spacing-240
--dx-toolbar-height --dxds-spacing-480 --dxds-spacing-360
--dx-list-item-padding-block --dxds-spacing-60 --dxds-spacing-40
--dx-list-item-padding-inline --dxds-spacing-120 --dxds-spacing-80
--dx-border-radius --dxds-border-radius-40 --dxds-border-radius-40
--dx-border-width --dxds-border-width-10 --dxds-border-width-10

The following table lists legacy variables that Fluent Next themes do not declare in the :root scope. Replace these variables with the corresponding Design System variables:

Legacy Variable Design System Variable
--dx-color-shadow --dxds-box-shadow-* (these variables define complete box-shadow values instead of only shadow colors)
--dx-texteditor-color-text --dxds-color-content
--dx-popup-toolbar-item-padding-inline --dxds-spacing-80
--dx-button-padding-inline --dxds-spacing-120 (standard size) or --dxds-spacing-80 (compact size)
NOTE
Fluent Next themes only declare --dx-button-padding-inline for elements with the dx-button or dx-dropdowneditor-button class.

Accent Colors

This section describes accent colors in Fluent Next themes.

NOTE

Accent colors only apply to HTML-based components and to the following RangeSelector elements:

  • Selected range
  • Slider handles
  • Slider markers

Other SVG-based components use palette colors that do not depend on the accent color. Refer to the following help topic for additional information: SVG-Based Components Customization - Palettes.

Predefined Accent Colors

The DevExpress Design System defines 11 primary color palettes for Fluent themes. These color palettes ship as stylesheets in the DevExtreme npm package. Import one of these accent stylesheets after a Fluent Next theme to apply an accent color:

Modular Application
Non-Modular Application
import 'devextreme/dist/css/dx.fluent-next.blue.light.css';
import 'devextreme/dist/css/accents/rose.css';
<link rel="stylesheet" href="node_modules/devextreme/dist/css/dx.fluent-next.blue.light.css">
<link rel="stylesheet" href="node_modules/devextreme/dist/css/accents/rose.css">

The following accent stylesheets are available:

Accent Color Stylesheet
Blue accents/blue.css
Cool Blue accents/cool-blue.css
Desert accents/desert.css
Mint accents/mint.css
Moss accents/moss.css
Orchid accents/orchid.css
Purple accents/purple.css
Rose accents/rose.css
Rust accents/rust.css
Steel accents/steel.css
Storm accents/storm.css
NOTE

Note the following when you apply accent stylesheets:

  • Blue is the default accent color in Fluent Next themes. You do not need to import the Blue accent stylesheet to apply this accent color.
  • Theme and accent stylesheets define colors on the same selector (:root). To ensure accent colors take effect, load your accent stylesheet after the theme stylesheet.
  • Custom accent colors override predefined accent colors regardless of stylesheet load order. Predefined accent stylesheets declare shades as fallback values for --dx-accent-color-* variables:

    CSS
    /* Shade 10 of the Blue accent stylesheet */
    --dxds-primary-10: var(--dx-accent-color-10, #f4f8fc);
  • Accent stylesheets apply to all Fluent Next variations (light and dark modes, standard and compact sizes). When you switch theme modes or sizes, you do not need to change your accent stylesheet.

Custom Accent Colors

Fluent Next stylesheets ship with a CSS rule that calculates primary shades from the --dx-accent-color variable defined in :root. Assign a color to this variable in a :root declaration block to use Fluent Next themes with a custom accent color:

CSS
:root {
    --dx-accent-color: SlateBlue;
}

You can also call the customAccentColor(color) method to change the accent color at runtime:

Modular Application
Non-Modular Application
import { customAccentColor } from 'devextreme/ui/themes';

customAccentColor('#6b4fbb');
DevExpress.ui.themes.customAccentColor('#6b4fbb');

This method defines --dx-accent-color as an inline style on the <html> element. This inline value takes priority over --dx-accent-color values in your stylesheets. To remove the custom accent color, pass null or an empty string to customAccentColor(color). Components then use the accent color from your stylesheets or the predefined accent color.

We recommend that you specify a vivid color as your custom accent to ensure your app is accessible to users with vision impairments. Use a color that has high contrast ratios with background and content colors in your chosen theme mode (light or dark). Avoid light or pastel colors, as well as grayscale colors such as white or black. Refer to the following help topic for more information about color contrast: Color Contrast - Accessibility | MDN.

NOTE

Consider the following when you specify a custom accent color:

  • Fluent Next stylesheets calculate primary shades only in the :root scope. A --dx-accent-color declaration on a descendant element does not affect component colors.
  • Fluent Next stylesheets use the oklch() CSS function to calculate primary color shades. Older browsers may not support this function and may revert to predefined accents.
  • Certain calculated primary shades may not contrast sufficiently with corresponding background or content colors. You can override these shades individually as follows:

    CSS
    :root {
        --dx-accent-color-90: #5a4bc2;
    }

    Load the stylesheet with these overrides after your Fluent Next stylesheet to ensure they take effect.

Theme Modes

Fluent Next themes ship with light and dark theme modes. Each Fluent Next stylesheet contains styles for both modes. The stylesheet you load specifies the default mode for the page. Light and dark stylesheets are available in standard and compact sizes:

  • Light:
    • dx.fluent-next.blue.light.css
    • dx.fluent-next.blue.light.compact.css
  • Dark:
    • dx.fluent-next.blue.dark.css
    • dx.fluent-next.blue.dark.compact.css

You can switch the theme mode for the entire page without loading another stylesheet. Assign the dx-theme-mode-light or dx-theme-mode-dark class to the <html> element. Refer to the following help topic for additional information: Container-Specific Theme Modes.

NOTE

The following colors apply to all Fluent Next variations (light and dark modes, standard and compact sizes):

  • Accent colors. You do not need to change your accent stylesheet or custom accent color when you switch theme modes or sizes.
  • Palette colors in SVG-based components. Theme modes change other colors in these components (such as backgrounds, text, and grid lines).

Container-Specific Theme Modes

Fluent Next themes allow you to define theme modes for specific containers in your application. You can use container-specific modes to apply dark mode styles in a light mode application and vice versa. These modes apply to HTML elements and to both HTML- and SVG-based DevExtreme components.

Use one of the following classes to specify a theme mode for a container:

  • dx-theme-mode-light: Applies light mode styles to a container and its children
  • dx-theme-mode-dark: Applies dark mode styles to a container and its children
  • dx-theme-mode-inverted: Applies the opposite theme mode relative to a container's nearest enclosing mode

Fluent Next stylesheets store current modes in the --dx-theme-mode CSS variable. Each container that uses theme modes (including the document root) defines this variable. Use the @container CSS at-rule to add mode-specific styles to your application:

CSS
@container style(--dx-theme-mode: dark) {
    .my-panel {
        background: #1d1d1d;
    }
}

Mode-specific rules apply to descendants of a theme mode container, but not to the container itself (style queries evaluate an element's ancestors).

Component overlays (for instance, popups and drop-down lists) open in the same theme mode as the component's container, even though DevExtreme renders overlays at the viewport level.

You can change container theme modes at runtime. Styles in custom elements and DevExtreme components are updated immediately. If an overlay is open when you change the mode, call refreshMode() to update overlay styles:

jQuery
index.html
index.js
<div class="dx-theme-mode-light">
    <div id="button-container"></div>
</div>
$('#button-container').dxButton({
    text: 'Change Theme Mode',
    onClick() {
        $('.dx-theme-mode-light')
            .removeClass('dx-theme-mode-light')
            .addClass('dx-theme-mode-dark');
        // Updates open overlays
        DevExpress.ui.themes.refreshMode();
    },
});
Angular
app.component.ts
import { ChangeDetectorRef, Component, inject } from "@angular/core";
import { refreshMode } from "devextreme/ui/themes";
import { DxButtonModule } from "devextreme-angular";

@Component({
    selector: 'app-root',
    imports: [DxButtonModule],
    template: `
        <div [class]="containerClass">
            <dx-button
                text="Change Theme Mode"
                (onClick)="changeThemeMode()"
            ></dx-button>
        </div>
    `,
})
export class AppComponent {
    private changeDetector = inject(ChangeDetectorRef);

    containerClass: string = 'dx-theme-mode-light';

    changeThemeMode() {
        this.containerClass = 'dx-theme-mode-dark';
        // Applies the new class to the DOM
        this.changeDetector.detectChanges();
        // Updates open overlays
        refreshMode();
    }
}
Vue
App.vue
<template>
    <div :class="containerClass">
        <DxButton
            text="Change Theme Mode"
            @click="changeThemeMode"
        />
    </div>
</template>

<script setup lang="ts">
import { nextTick, ref } from "vue";
import { refreshMode } from "devextreme/ui/themes";
import { DxButton } from 'devextreme-vue/button';

const containerClass = ref('dx-theme-mode-light');

async function changeThemeMode() {
    containerClass.value = 'dx-theme-mode-dark';
    // Waits until Vue applies the new class to the DOM
    await nextTick();
    // Updates open overlays
    refreshMode();
}
</script>
React
App.tsx
import { useCallback, useEffect, useState } from 'react';
import Button from 'devextreme-react/button';
import { refreshMode } from 'devextreme/ui/themes';

export default function App() {
    const [containerClass, setContainerClass] = useState('dx-theme-mode-light');

    useEffect(() => {
        // Updates open overlays after React applies the new class to the DOM
        refreshMode();
    }, [containerClass]);

    const changeThemeMode = useCallback(() => {
        setContainerClass('dx-theme-mode-dark');
    }, []);

    return (
        <div className={containerClass}>
            <Button
                text="Change Theme Mode"
                onClick={changeThemeMode}
            />
        </div>
    );
}

You can nest dx-theme-mode-inverted containers. The following code snippet demonstrates three nesting levels:

HTML
<!DOCTYPE html>
<html class="dx-theme-mode-dark">
    <!-- Dark mode for the entire page -->
    <head><!-- ... --></head>
    <body class="dx-viewport">
        <div class="one dx-theme-mode-inverted">
            <!-- Light mode within .one -->
            <div class="two dx-theme-mode-inverted">
                <!-- Dark mode within .two -->
                <div class="three dx-theme-mode-inverted">
                    <!-- Light mode within .three -->
                </div>
            </div>
        </div>
    </body>
</html>

In JavaScript, call the mode(element) method to get an element's calculated theme mode ("light" or "dark"). The following code snippet returns "light" for the .three element from the previous snippet:

jQuery
index.js
const calculatedMode = DevExpress.ui.themes.mode($('.three'));
Angular
app.component.ts
import { AfterViewInit } from "@angular/core";
import { mode } from "devextreme/ui/themes";

// ...
export class AppComponent implements AfterViewInit {
    calculatedMode = '';

    ngAfterViewInit() {
        this.calculatedMode = mode(document.querySelector('.three')!);
    }
}
Vue
App.vue
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { mode } from "devextreme/ui/themes";

const calculatedMode = ref('');

onMounted(() => {
    calculatedMode.value = mode(document.querySelector('.three')!);
});
</script>
React
App.tsx
import { useEffect, useState } from 'react';
import { mode } from "devextreme/ui/themes";

export default function App() {
    const [calculatedMode, setCalculatedMode] = useState('');

    useEffect(() => {
        setCalculatedMode(mode(document.querySelector('.three')!));
    }, []);
    // ...
}
NOTE
You can call mode(element) for any element, inside or outside a theme mode container. If no container declares a mode, the method reads the mode from the active Fluent Next stylesheet and always returns "light" or "dark".