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
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
Sign up or log in to create a project, then follow the steps below.
Free Workspace Projects
| Step | Action |
|---|---|
| 1 | Go to your project's |
| 2 | Find |
| 3 | Find |
| 4 | Save your changes to immediately update anywhere you're using your project. |
Pro Workspace Projects
| Step | Action |
|---|---|
| 1 | Go to your project's |
| 2 | Press |
| 3 | Select a pre-built theme or customize colors, fonts, icons, and more. |
| 4 | Save your theme to immediately update anywhere you're using your project. |
Theme Builder
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
Light and Dark Mode
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".
Light
Dark
Inverting the Color Scheme
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.
Invert
Detecting Color Scheme Preference
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:
- Check for
prefers-color-schemeand use its value by default - Allow the user to override this setting in your app
- Remember the user's preference and restore it on subsequent visits
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
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
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.
wa-theme-awesome and wa-brand-yellow.
wa-theme-shoelace and wa-brand-cyan.
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
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
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.
CSS parts have a few important advantages:
-
Customizations can be made to components with explicit selectors, such as
::part(icon), rather than implicit selectors, such as.button > div > span + .icon, that are much more fragile. -
The internal structure of a component will likely change as it evolves. By exposing CSS parts through an API, the internals can be reworked without fear of breaking customizations as long as its parts remain intact.
-
It encourages us to think more about how components are designed and how customizations should be allowed before users can take advantage of them. Once we opt a part into the component's API, it's guaranteed to be supported and can't be removed until a major version of the library is released.
Most (but not all) components expose parts. You can find them in each component's API documentation under the "CSS Parts" section.
Custom Properties
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
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
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: