Customizing & Theming

You can customize the look and feel of Web Awesome at a high level with themes. For an overview of how the theming system works — themes, palettes, variants, and dark mode — see Theming. For more advanced customizations, you can make use of CSS parts and custom properties to target individual components.

Themes

Link to This Section

Web Awesome uses themes to apply a cohesive look and feel across the entire library. Themes are built with a collection of predefined CSS custom properties, which we call design tokens, and there are many pre-built themes to choose from.

Use a Pre-Built Theme

Link to This Section

Sign up or log in to create a project, then follow the steps below.

Theme Builder

Link to This Section

The Theme Builder is a visual editor for Pro workspace projects that lets you customize your project's theme, color palette, variant colors, fonts, roundness, spacing, and icons — with a live preview as you go. Saves apply instantly anywhere you're using your project.

You can launch the Theme Builder from your project's Settings by pressing Edit Your Theme.

Light and Dark Mode

Link to This Section

Every theme is designed to adapt to light and dark mode. Light mode styles are applied by default, but you can apply a specific color scheme to an entire page or just a section with class="wa-light" or class="wa-dark".

Inverting the Color Scheme

Link to This Section

You can force a section to behave like .wa-dark in light mode and like .wa-light in dark mode by using class="wa-invert".

This card will always use the opposite of the color scheme applied to the docs.

Detecting Color Scheme Preference

Link to This Section

While both light and dark mode styles are built-in to all themes, Web Awesome doesn't automatically detect the user's color scheme preference. We recommend doing this at the application level.

Follow these best practices for supporting both light and dark mode:

Let's assume you have a button with id="color-scheme-button" that simply toggles between light and dark mode. You can use the following JS snippet to apply class="wa-dark" to the <html> element accordingly:

// Function to apply color scheme
function applyScheme(dark) {
  document.documentElement.classList.toggle('wa-dark', dark);
}

// Function to get the user's preferred color scheme
// Grabs from local storage if available or falls back to system preference
function getPreferredScheme() {
  const savedMode = localStorage.getItem('wa-color-scheme');
  if (savedMode !== null) return savedMode === 'dark';
  return window.matchMedia('(prefers-color-scheme: dark)').matches;
}

// Apply the preferred color scheme on load
applyScheme(getPreferredScheme());

// Listen for changes in system preference
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
  // If nothing in local storage, update accordingly
  const savedMode = localStorage.getItem('wa-color-scheme');
  if (!savedMode) {
    applyScheme(event.matches);
  }
});

// Listen for clicks on the color scheme button
document.getElementById('color-scheme-button').addEventListener('click', () => {
  const toDark = !document.documentElement.classList.contains('wa-dark');
  applyScheme(toDark);
  localStorage.setItem('wa-color-scheme', toDark ? 'dark' : 'light');
});

Customizing with CSS

Link to This Section

For even more customizations, you can off-road and override any theme just with CSS — no preprocessor required. All tokens use the --wa- prefix to prevent collisions with other libraries. Write a stylesheet that overrides Web Awesome's design tokens and you're off to the races.

Here's a starter that tweaks fonts, spacing, and corner radius across both color schemes:

/* Custom CSS — applies to both light and dark mode */
:where(:root),
.wa-light,
.wa-dark,
.wa-invert {
  --wa-font-family-body: 'Inter', sans-serif;
  --wa-font-family-heading: 'Crimson Pro', serif;
  --wa-border-radius-scale: 1.5;
  --wa-space-scale: 1.125;
}

To create your own light mode styles, scope your styles to the following selectors:

:where(:root),
.wa-light,
.wa-dark .wa-invert {
  /* your styles here */
}

To create your own dark mode styles, scope your styles to these selectors:

.wa-dark,
.wa-invert {
  /* your styles here */
}
Selector What It Targets
:where(:root) The default scope, with low specificity so other theme classes can override it
.wa-light Explicit light sections
.wa-dark Explicit dark sections
.wa-invert Flips the current color scheme on this element
.wa-dark .wa-invert An inverted descendant inside a dark section (becomes light)

For a complete list of all custom properties used for theming, refer to src/styles/themes/default.css in the project's source code.

Using Multiple Themes

Link to This Section

You can use multiple themes on a single page as long as the styles for each theme are scoped to a specific class. All pre-built themes are scoped to their own classes. The Default theme is additionally scoped to :where(:root) so that the styles are applied automatically.

Simply load the theme stylesheets, then add your preferred classes to each element.

You can also use multiple variant colors on the same page. On each element where you change the variant color, also add wa-theme-* — even if the theme doesn't change. Otherwise the theme keeps using its original variant colors.

Customizing Components

Link to This Section

While themes offer a high-level way to customize the library, individual components offer different hooks as a low-level way to customize them one at a time. Web Awesome components use a shadow DOM to encapsulate their styles and behaviors. As a result, you can't simply target their internals with the usual CSS selectors. Instead, components expose a set of CSS parts, custom properties, and custom states that can be targeted to customize their appearance.

CSS Parts

Link to This Section

CSS parts offer the most flexibility to customize individual components. The "parts" exposed by each component can be targeted with the CSS part selector, or ::part().

Parts allow you to style any standard CSS property, not just those exposed through custom properties. Here's an example that modifies buttons with the gradient-button class.

Gradient Button

CSS parts have a few important advantages:

Most (but not all) components expose parts. You can find them in each component's API documentation under the "CSS Parts" section.

Custom Properties

Link to This Section

Components expose custom properties that are scoped to the component, not global, so they do not have the same --wa- prefix as a theme's custom properties. These custom properties reflect common qualities of a component, such as --background-color, --border-style, --size, etc.

You can set custom properties on a component in your stylesheet.

wa-avatar {
  --size: 6rem;
}

This will also work if you need to target a subset of components with a specific class.

wa-avatar.your-class {
  --size: 6rem;
}

Alternatively, you can set them inline directly on the element.

<wa-avatar style="--size: 6rem;"></wa-avatar>

The custom properties exposed by each component can be found in the component's API documentation.

Custom States

Link to This Section

Components can expose custom states that allow you to style them based on their current condition using the :state() selector. Custom states provide a way to target specific component states that aren't covered by standard pseudo-classes like :hover or :focus. Here's an example that styles a checkbox that's checked.

wa-checkbox:state(checked) {
  outline: dotted 2px tomato;
}

Custom states can be combined with CSS parts and custom properties to create sophisticated customizations. The custom states exposed by each component can be found in the component's API documentation under the "Custom States" section.

Native Elements

Link to This Section

If you're using native styles, any custom styles added for a component should also target the corresponding native element. In general, the same styles you declare for components will work just the same to style their native counterparts.

For example, we can give <input type="checkbox"> the same custom styles as <wa-checkbox> by using standard CSS properties and CSS parts:

Web Awesome checkbox