Apsara uses a comprehensive CSS variable system that allows you to customize colors, spacing, typography, and more throughout your application.
CSS variable system
The theming system is built on CSS custom properties (variables) defined in the :root selector. All variables use the -- prefix and are organized into semantic categories.
Color tokens
Apsara provides semantic color tokens that automatically adapt to light and dark themes:
:root {
/* Foreground colors */
--foreground-base : #3c4347 ;
--foreground-muted : #687076 ;
--foreground-subtle : #7e868c ;
--foreground-inverted : #fbfcfd ;
--foreground-accent : #3e63dd ;
--foreground-danger : #e5484d ;
--foreground-success : #30a46c ;
/* Background colors */
--background-base : #fbfcfd ;
--background-base-hover : #f1f3f5 ;
--background-inset : #f1f3f5 ;
--background-accent : #e6edfe ;
--background-danger : #ffe5e5 ;
--background-success : #ddf3e4 ;
/* Border colors */
--border-base : #d7dbdf ;
--border-base-hover : #c1c8cd ;
--border-accent : #aec0f5 ;
--border-danger : #f3aeaf ;
--border-success : #92ceac ;
}
Typography tokens
Customize fonts and font sizes across your application:
:root {
/* Font families */
--ff-inter : "Inter" , -apple-system , system-ui , sans-serif ;
--ff-mono : Söhne Mono, menlo, monospace ;
/* Font sizes */
--fs-100 : 0.688 rem ; /* ~11px */
--fs-200 : 0.75 rem ; /* 12px */
--fs-300 : 0.813 rem ; /* ~13px */
--fs-400 : 0.875 rem ; /* 14px */
--fs-500 : 0.938 rem ; /* ~15px */
--fs-600 : 1 rem ; /* 16px */
}
Spacing tokens
A consistent spacing scale from 2px to 120px:
:root {
--space-1 : 2 px ;
--space-2 : 4 px ;
--space-3 : 8 px ;
--space-4 : 12 px ;
--space-5 : 16 px ;
--space-6 : 20 px ;
--space-7 : 24 px ;
--space-8 : 28 px ;
--space-9 : 32 px ;
--space-10 : 40 px ;
--space-11 : 48 px ;
--space-12 : 56 px ;
--space-13 : 64 px ;
--space-14 : 72 px ;
--space-15 : 80 px ;
--space-16 : 96 px ;
--space-17 : 120 px ;
}
Border radius tokens
Control the roundness of component corners:
:root {
--radius-1 : 2 px ;
--radius-2 : 4 px ;
--radius-3 : 6 px ;
--radius-4 : 8 px ;
--radius-5 : 12 px ;
--radius-6 : 16 px ;
--radius-full : 800 px ;
}
Shadow tokens
Elevation shadows for depth and hierarchy:
:root {
--shadow-xs : 0 px 1 px 2 px 0 px rgba ( 16 , 24 , 40 , 0.06 );
--shadow-sm : 0 px 1 px 4 px 0 px rgba ( 0 , 0 , 0 , 0.09 );
--shadow-md : 0 px 12 px 16 px -4 px rgba ( 16 , 24 , 40 , 0.08 ),
0 px 4 px 6 px -2 px rgba ( 16 , 24 , 40 , 0.03 );
--shadow-lg : 0 px 20 px 24 px -4 px rgba ( 16 , 24 , 40 , 0.08 ),
0 px 8 px 8 px -4 px rgba ( 16 , 24 , 40 , 0.03 );
}
Customizing your theme
You can override any CSS variable to customize your theme. Create a custom CSS file and import it after the Apsara stylesheet:
:root {
/* Override accent color */
--foreground-accent : #7c3aed ;
--background-accent : #ede9fe ;
--border-accent : #c4b5fd ;
/* Customize spacing */
--space-4 : 16 px ;
--space-5 : 20 px ;
/* Change border radius */
--radius-2 : 8 px ;
--radius-3 : 12 px ;
}
html [ data-theme = "dark" ] {
/* Override dark theme accent */
--foreground-accent : #a78bfa ;
--background-accent : #2e1065 ;
--border-accent : #5b21b6 ;
}
import "@raystack/apsara/style.css" ;
import "./custom-theme.css" ;
function App () {
return < YourApp /> ;
}
Make sure to import your custom theme CSS after the Apsara stylesheet to ensure your overrides take precedence.
Using CSS variables in components
You can reference CSS variables directly in your custom component styles:
.my-component {
color : var ( --foreground-base );
background-color : var ( --background-base );
border : 1 px solid var ( --border-base );
padding : var ( --space-4 );
border-radius : var ( --radius-2 );
box-shadow : var ( --shadow-sm );
}
.my-component:hover {
background-color : var ( --background-base-hover );
border-color : var ( --border-base-hover );
}
Component-specific tokens
Many components use their own namespaced tokens. For example, buttons use:
.button {
padding : var ( --rs-space-3 ) var ( --rs-space-4 );
border-radius : var ( --rs-radius-2 );
font-size : var ( --rs-font-size-small );
font-weight : var ( --rs-font-weight-medium );
}
Component-specific tokens like --rs-* variables are automatically mapped to the global tokens, but you can override them for fine-grained control.
Best practices
Prefer semantic tokens like --foreground-accent over direct color values. This ensures your customizations work correctly in both light and dark themes.
Maintain consistent spacing
Stick to the spacing scale (--space-*) for margins, padding, and gaps to maintain visual consistency.
Always test your customizations in both light and dark modes to ensure good contrast and readability.
Override at the right level
Override global tokens in :root for app-wide changes, or target specific components for localized customization.
Related resources
Dark mode Learn how to implement dark mode in your application
Styling Explore different styling approaches for components