Skip to main content

Customize GUI themes

@rpgjs/ui-css styles DOM interfaces independently of their renderer. Use it with HTML, CanvasEngine DOMContainer components or Vue. Theme changes run on the client in both standalone RPG and MMORPG modes; they do not change GUI IDs, server data or gameplay authority. Browse the GUI catalogue for foundations, interactive elements and complete compositions. The catalogue is published from v5; contributors can run it locally with pnpm --filter @rpgjs/ui-css storybook.

Load a theme

Load the base stylesheet first, a theme second and your overrides last:
The default theme uses navy surfaces, silver borders, cyan accents and gold selection. No font service or remote artwork is required. Replace the second import with theme-pixel.css for the pixel theme. The existing index.css includes the legacy game-page reset (including body overflow). For an embedded widget on a normal webpage, import @rpgjs/ui-css/components.css instead: it includes tokens and components without resetting the page. Add your own box sizing within the widget.

Use elements and compositions

The text above is example game content. In a real RPGJS component, provide labels through i18n. Bind actions through the existing GUI contracts, rather than adding gameplay behavior to the CSS library. Use the same classes inside a CanvasEngine <DOMContainer> or a Vue template. Register the GUI normally; CSS does not replace registration or input handling. For interactive HTML, prefer native buttons and fields.

Button contract

CSS does not disable a non-native element. If you use aria-disabled, your component must block its click and keyboard handlers. Keep accessible labels on icon-only buttons and preserve visible keyboard focus. Put an inline SVG before the label for an icon; no icon font is required.

Layout helpers

Use rpg-ui-stack for vertical groups, rpg-ui-row for wrapping horizontal groups, rpg-ui-grid for responsive panels and rpg-ui-inventory-grid for slots. Complete built-in screens keep their existing semantic classes and responsive layouts. Storybook compositions are presentation fixtures, not a server simulator.

Customize globally or locally

Override colors globally in :root. To limit changes to one game or widget, put a theme boundary on an ancestor:
A theme boundary resets base tokens and resolves semantic aliases locally. Declare the palette on that same boundary and load its rules after the theme imports. A nested boundary is a new theme, not a partial inheritance of its parent. The built-in boundary classes are rpg-ui-theme-default and rpg-ui-theme-pixel. Both theme imports may coexist: the last import controls the global default, while each explicit class selects its own local palette. Use one boundary per subtree. Storybook’s Theme isolation story demonstrates all three themes simultaneously.

Token reference

Palette tokens describe values. Semantic tokens describe roles. Component tokens let you change one family without restyling every screen. The source tokens.css and src/semantic.css contain the full token sets, including existing HUD, chat and shop dimensions. Hotbar customization retains its --rpg-hotbar-* API; semantic defaults now connect it to the active theme.

Common recipes

Component variants can override their own tokens. For example, customize primary buttons through .rpg-ui-btn[data-variant="primary"] after the library imports if their surface must differ from the theme’s accent treatment.

Canvas mobile controls

The native mobile controls draw with CanvasEngine rather than DOM CSS. They read surface, background, text, accent, border and danger colors from #rpg (or the document root when unavailable). Changes to ancestor classes, inline styles or data-rpg-theme refresh these colors while mounted. Load stylesheets before mounting; stylesheet replacement alone is not observed. Explicit withMobile({ buttons: ..., joystick: ... }) props remain authoritative. Use these props or custom CanvasEngine components for textures and specialized shapes. CSS panel shadows and gradients do not automatically become canvas effects.

Migration and verification

Existing imports and class names remain supported. The appearance of theme-default.css intentionally changes; the old Fredoka font is no longer required. Remove redundant overrides that were specific to the old glass theme. Check every theme with long translated text, empty inventories, unavailable actions, keyboard focus and narrow viewports. Keep portraits and item artwork in your game’s asset library: the mockup’s illustrations are not bundled UI assets.