Skip to main content
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:
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,
        },
      },
    },
  },
})

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

Build docs developers (and LLMs) love