> Markdown version of [Application Theme](https://vaadin.com/docs/v24/styling/application-theme). Section index: [llms.txt](https://vaadin.com/docs/v24/styling/llms.txt)

# Application Theme

It’s best to put CSS stylesheets for styling Vaadin components and other UI elements in an application theme folder. Themes organization this way are loaded on top of the default [Lumo theme](https://vaadin.com/docs/v24/styling/lumo.md).

For use in a single application, place your theme folder in the `frontend/themes` directory. Vaadin application projects generated with [Vaadin Start](https://start.vaadin.com) have a pre-defined theme folder with the same name as the project.

Theme Folder Example

```
frontend
└── themes
    └── my-theme        /* <1> */
        ├── styles.css  /* <2> */
        └── theme.json  /* <3> */
```

The theme folder (1) must contain a [master stylesheet](#master-stylesheet) called, `styles.css` (2). A [theme configuration file](#theme-configuration) called, `theme.json` (3) is optional.

Themes built this way can be [packaged as JAR files](https://vaadin.com/docs/v24/styling/advanced/multi-app-themes.md) to be shared by multiple applications.

> **Note: Flow @CssImport Annotation**
>
> In older versions of Vaadin, stylesheets were loaded using `@CssImport` and `@Stylesheet` annotations. In much older versions, they were loaded using the `@HtmlImport` annotation. Although `@CssImport` and `@Stylesheet` still work, they’re recommended only for loading stylesheets into custom standalone components — not as the primary way to load application styles.

## <a id="applying-a-theme"></a>Applying a Theme

The theme contained in the folder is applied to the UI using the `@Theme` annotation, with the name of the theme folder as a parameter. The `@Theme` annotation must be placed on the class that implements the [`AppShellConfigurator`](https://vaadin.com/docs/v24/flow/advanced/modifying-the-bootstrap-page.md#application-shell-configurator) interface. This interface is used for configuring various application features. For projects generated with Vaadin Start, that would be the `Application` class.

```java
@Theme("my-theme")
public class Application implements AppShellConfigurator {
  ...
}
```

To apply a custom theme on top of the Dark variant of Lumo, the variant is provided as an additional parameter, the annotation:

```java
@Theme(value="my-theme", variant=Lumo.DARK)
public class Application implements AppShellConfigurator {
  ...
}
```

> **Note: Themes Cannot be Switched at Run-Time**
>
> Although a project may contain multiple theme folders, only one can be applied to the UI. There’s no way dynamically to switch theme folders at run-time. However, there are ways to [switch between variants](https://vaadin.com/docs/v24/styling/advanced/runtime-theme-switching.md) of the same theme, [load dynamically additional styles](https://vaadin.com/docs/v24/styling/advanced/loading-styles-dynamically.md) on top of the theme, and to create [base-themes inherited by sub-themes](https://vaadin.com/docs/v24/styling/advanced/parent-and-sub-themes.md).

## <a id="master-stylesheet"></a>Master Stylesheet

The master stylesheet, `styles.css` is loaded automatically into the UI. All CSS, including Lumo style property values and custom component styles, can be added there.

To apply Lumo style property modifications globally (i.e., in the whole application), they should be placed in a style block targeting the `html` root element selector like so:

styles.css

```css
html {
  --lumo-primary-color: green;
  --lumo-font-family: Times;
}
```

The master stylesheet is also a good place to define [your own global style properties](https://vaadin.com/docs/v24/styling/advanced/custom-style-properties.md).

## <a id="additional-stylesheets"></a>Additional Stylesheets

It can be useful to split CSS into multiple stylesheets, to avoid creating a mess in the master stylesheet. Additional stylesheets are loaded through `@import` directives at the top of the master stylesheet. They can be placed in sub-folders.

styles.css

```css
@import 'colors.css';
@import 'views/admin-view.css';
@import 'input-fields/textfield.css';

html, :host() {
  …
}
```

It’s also possible to load stylesheets via external URLs, and from [JAR dependencies](https://vaadin.com/docs/v24/styling/advanced/multi-app-themes.md) and [npm packages](https://vaadin.com/docs/v24/styling/advanced/npm-packages.md).

### <a id="external-stylesheets"></a>External Stylesheets

Stylesheets can be loaded from outside the application by a URL using the same `@import` directive. This can be used, for example, to load font-face declarations or color palettes from outside the application.

styles.css

```css
@import url('https://example.com/some-external-styles.css');

html, :host() {
  …
}
```

### <a id="components-sub-folder-legacy-feature"></a>Components Sub-Folder (Legacy Feature)

Stylesheets placed in a sub-folder called `components` in the application theme are loaded by default into the Shadow DOM of Vaadin components — if their file names match the root element name of a component.

This is a legacy feature from earlier versions of Vaadin, in which Vaadin components were styled primarily through [Shadow DOM CSS injection](https://vaadin.com/docs/v24/styling/advanced/shadow-dom-styling.md). Although this approach to component styling is no longer recommended, the injection mechanism is still supported and enabled by default. This is to ease migration from earlier versions.

> **Note: Disable Pre-Compiled Frontend Bundle**
>
> The loading of shadow DOM stylesheets from the `components` sub-folder is not compatible with the [pre-compiled frontend bundle](https://vaadin.com/docs/v24/flow/configuration/development-mode.md#precompiled-bundle). In order to use this mechanism for loading shadow DOM styles, the pre-compiled bundle must be [disabled](https://vaadin.com/docs/v24/flow/configuration/development-mode.md#disable-precompiled-bundle).

This legacy feature, though, may cause problems in application themes based on the [current recommended approach to component styling](https://vaadin.com/docs/v24/styling/styling-components.md), if a sub-folder called, `components` is used. The feature can, however, be disabled by setting the `autoInjectComponents` flag in the theme configuration file to `false`:

theme.json

```json
{
  "lumoImports" : [ "typography", "color", "spacing", "badge", "utility" ],
  "autoInjectComponents" : "false"
}
```

## <a id="images-fonts"></a>Images & Fonts

You can include font files and images in your theme folder. Create sub folders for them (i.e., `images` and `fonts`). You’ll need to use the [`@font-face`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face) CSS rule to load font files, like the `roboto.woff` file located in `my-theme/fonts/` in the example below:

styles.css

```css
@font-face {
  font-family: "Roboto";
  src: url("./fonts/roboto.woff") format("woff");
}

.application-logo {
  background-image: url("./img/logo.png");
}
```

It’s also possible to load images and fonts via [external URLs](https://developer.mozilla.org/en-US/docs/Web/CSS/url), and from [npm packages](https://vaadin.com/docs/v24/styling/advanced/npm-packages.md).

> **Note: Embedded Components**
>
> If a theme is to be used with [embedded Flow applications or components](https://vaadin.com/docs/v24/flow/integrations/embedding.md), such as for use with [Design System Publisher](https://vaadin.com/docs/v24/tools/dspublisher.md), `@font-face` declarations must be placed in a special stylesheet called, `document.css` to ensure that they’re loaded in the page root rather than in a shadow root.

Images stored in the theme folder can also be used with Flow’s [Image class](https://vaadin.com/docs/v24/flow/application/resources.md#the-image-component) using the path `themes/[theme-name]/filename.png`. The example below loads an image file from a theme folder called, `my-theme`:

```java
Image logo = new Image("themes/my-theme/images/logo.png", "Logo");
```

## <a id="theme-folder-structure-example"></a>Theme Folder Structure Example

Below is an example of how a theme folder with images, fonts, and multiple stylesheets and sub-folders can look:

Theme Folder Example

```
frontend
└── themes
    └── my-theme
        ├── component-styles
        │   ├── input-fields.css
        │   └── buttons.css
        ├── fonts
        │   └── roboto.woff
        ├── images
        │   ├── logo.png
        │   └── login-background.png
        ├── colors.css
        ├── fonts.css
        ├── styles.css
        └── theme.json
```

## <a id="theme-configuration"></a>Theme Configuration

The theme configuration file, `theme.json` can be used to configure various theme-related features. The most common of these is the `lumoImports` property, used to define which modules of the built-in Lumo theme are to be loaded.

```json
{
  "lumoImports" : [ "typography", "color", "spacing", "badge", "utility" ]
}
```

The most common usage of this property is to enable [Badge](https://vaadin.com/docs/v24/components/badge.md) styles and the [Lumo Utility Classes](https://vaadin.com/docs/v24/styling/lumo/utility-classes.md). If undefined, the following modules are loaded by default:

- `typography`

- `color`

- `sizing`

- `spacing`

Other theme configuration features are covered in the [Advanced Styling Topics](https://vaadin.com/docs/v24/styling/advanced.md) section:

- [Loading stylesheets from npm packages](https://vaadin.com/docs/v24/styling/advanced/npm-packages.md#styles-from-npm);

- [Loading other theme assets from npm packages](https://vaadin.com/docs/v24/styling/advanced/npm-packages.md#fonts-and-images-from-npm); and

- [Loading a parent theme as a basis for the current theme](https://vaadin.com/docs/v24/styling/advanced/parent-and-sub-themes.md).

Embedded application theming is covered in [Theming Embedded Applications](https://vaadin.com/docs/v24/flow/integrations/embedding/theming.md).

You can find an example project that demonstrates the application theme in action at [GitHub](https://github.com/vaadin/custom-theme-demo).

`e5e984e4-6a4f-40ab-a6fc-665166a2d8c5`
