Sanity Studio’s appearance can be customized through theming to match your brand identity. You can customize colors, fonts, spacing, and more.
Theme structure
Sanity Studio uses the Sanity UI theme system, which provides:
- Color schemes: Light and dark mode support
- Typography: Font families and sizes
- Spacing: Consistent spacing scales
- Tones: Semantic color tones (primary, positive, caution, critical)
Basic theme configuration
Customize your studio theme in the config:
import {defineConfig} from 'sanity'
export default defineConfig({
projectId: 'your-project-id',
dataset: 'production',
theme: {
fonts: {
text: {
family: 'Inter, -apple-system, sans-serif',
},
code: {
family: 'JetBrains Mono, Monaco, monospace',
},
},
},
})
Typography customization
Customize font families for text and code:
Custom fonts
Loading web fonts
import {defineConfig} from 'sanity'
export default defineConfig({
theme: {
fonts: {
text: {
family: '"Open Sans", sans-serif',
sizes: [
{fontSize: 12, lineHeight: 16},
{fontSize: 14, lineHeight: 20},
{fontSize: 16, lineHeight: 24},
{fontSize: 18, lineHeight: 26},
{fontSize: 21, lineHeight: 30},
],
weights: {
regular: 400,
medium: 500,
semibold: 600,
bold: 700,
},
},
code: {
family: '"Fira Code", monospace',
sizes: [
{fontSize: 11, lineHeight: 16},
{fontSize: 13, lineHeight: 18},
{fontSize: 15, lineHeight: 22},
],
weights: {
regular: 400,
medium: 500,
semibold: 600,
bold: 700,
},
},
},
},
})
// app.tsx or index.html
import '@fontsource/inter'
import '@fontsource/jetbrains-mono'
Or in your HTML:<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
Legacy theme builder
For advanced customization, use the legacy theme builder:
import {defineConfig, buildLegacyTheme} from 'sanity'
const theme = buildLegacyTheme({
// Brand colors
'--brand-primary': '#6366f1',
// Base colors
'--black': '#101010',
'--white': '#ffffff',
'--gray': '#6b7280',
'--gray-base': '#6b7280',
// Component colors
'--component-bg': '#ffffff',
'--component-text-color': '#101010',
// Button colors
'--default-button-color': '#6b7280',
'--default-button-primary-color': '#6366f1',
'--default-button-success-color': '#10b981',
'--default-button-warning-color': '#f59e0b',
'--default-button-danger-color': '#ef4444',
// Focus color
'--focus-color': '#6366f1',
// Navigation
'--main-navigation-color': '#101010',
'--main-navigation-color--inverted': '#ffffff',
// State colors
'--state-info-color': '#3b82f6',
'--state-success-color': '#10b981',
'--state-warning-color': '#f59e0b',
'--state-danger-color': '#ef4444',
// Typography
'--font-family-base': '"Inter", -apple-system, sans-serif',
'--font-family-monospace': '"JetBrains Mono", Monaco, monospace',
})
export default defineConfig({
theme,
})
Available theme properties
The legacy theme builder accepts these CSS custom properties:
{
'--black': string,
'--white': string,
'--gray': string,
'--gray-base': string,
'--brand-primary': string,
'--component-bg': string,
'--component-text-color': string,
'--default-button-color': string,
'--default-button-danger-color': string,
'--default-button-primary-color': string,
'--default-button-success-color': string,
'--default-button-warning-color': string,
'--focus-color': string,
'--state-info-color': string,
'--state-success-color': string,
'--state-warning-color': string,
'--state-danger-color': string,
'--main-navigation-color': string,
'--main-navigation-color--inverted': string,
}
{
'--font-family-base': string,
'--font-family-monospace': string,
}
{
'--screen-medium-break': string,
'--screen-default-break': string,
'--screen-large-break': string,
'--screen-xlarge-break': string,
}
Multiple themes
Provide different themes for different workspaces:
import {defineConfig, buildLegacyTheme} from 'sanity'
const lightTheme = buildLegacyTheme({
'--brand-primary': '#6366f1',
'--component-bg': '#ffffff',
'--component-text-color': '#101010',
})
const darkTheme = buildLegacyTheme({
'--brand-primary': '#818cf8',
'--component-bg': '#1f2937',
'--component-text-color': '#f3f4f6',
})
export default defineConfig([
{
name: 'production',
title: 'Production',
projectId: 'your-project-id',
dataset: 'production',
theme: lightTheme,
},
{
name: 'staging',
title: 'Staging',
projectId: 'your-project-id',
dataset: 'staging',
theme: darkTheme,
},
])
Studio component styling
For more control, override studio components with custom styling:
import {defineConfig, type LayoutProps} from 'sanity'
import {Card} from '@sanity/ui'
function ThemedLayout(props: LayoutProps) {
return (
<Card
height="fill"
style={{
'--custom-bg': '#f8fafc',
background: 'var(--custom-bg)',
} as React.CSSProperties}
>
{props.renderDefault(props)}
</Card>
)
}
export default defineConfig({
studio: {
components: {
layout: ThemedLayout,
},
},
})
Color tone customization
Customize semantic color tones:
import {buildLegacyTheme} from 'sanity'
const theme = buildLegacyTheme({
'--brand-primary': '#6366f1',
'--state-info-color': '#3b82f6', // Info/primary actions
'--state-success-color': '#10b981', // Success states
'--state-warning-color': '#f59e0b', // Warning states
'--state-danger-color': '#ef4444', // Danger/critical actions
})
These tones are used throughout the UI:
- Primary: Main brand actions
- Positive/Success: Confirmations, approvals
- Caution/Warning: Alerts, warnings
- Critical/Danger: Destructive actions, errors
Dark mode support
Dark mode is determined by the theme colors. If your base background is dark, the studio will adapt accordingly.
Create a dark theme:
const darkTheme = buildLegacyTheme({
'--black': '#ffffff',
'--white': '#0a0a0a',
'--gray': '#9ca3af',
'--gray-base': '#6b7280',
'--component-bg': '#1f2937',
'--component-text-color': '#f3f4f6',
'--brand-primary': '#818cf8',
'--main-navigation-color': '#f3f4f6',
'--main-navigation-color--inverted': '#111827',
})
CSS custom properties
Access theme values in custom components:
import {Card, Text} from '@sanity/ui'
function CustomBanner() {
return (
<Card
padding={4}
style={{
borderLeft: '4px solid var(--card-border-color)',
background: 'var(--card-bg-color)',
}}
>
<Text style={{color: 'var(--card-fg-color)'}}>
Custom themed content
</Text>
</Card>
)
}
Theme defaults
The default theme uses:
- Fonts: System fonts for text, monospace for code
- Colors: Neutral grays with blue accents
- Spacing: 4px base unit
- Radius: Subtle border radius
Debugging themes
Inspect theme values in browser DevTools:
import {useTheme} from '@sanity/ui'
function ThemeDebugger() {
const theme = useTheme()
console.log('Current theme:', theme)
return null
}
Migration from v2
If migrating from Sanity Studio v2:
- Use
buildLegacyTheme for CSS custom properties
- The new theme system uses Sanity UI’s theme structure
- Some v2 properties may not have direct equivalents
Start with buildLegacyTheme to maintain compatibility, then migrate to the new theme structure when ready.
Best practices
- Test in both light and dark environments: Ensure sufficient contrast
- Use semantic colors: Apply tones consistently (primary for actions, critical for destructive operations)
- Maintain accessibility: Ensure text has adequate contrast ratios
- Test on different screens: Verify readability at various sizes
- Keep it simple: Avoid over-customization that might confuse users
Next steps