Material Design 3 Color System: Dynamic Color and Theme Builder Guide

· Coloracci Team

Material Design 3 Color System: Dynamic Color and Theme Builder Guide

What Changed in Material Design 3

Material Design 3 (also called Material You) represents a fundamental shift in how Google approaches color in UI design. Instead of prescribing fixed palettes, M3 generates entire color schemes dynamically from a single source color—or even from a user's wallpaper.

This guide covers the M3 color system in depth: how it works, how to build with it, and how it compares to its predecessor.

Dynamic Color: The Core Innovation

Dynamic color is M3's signature feature. On Android 12+, the system extracts colors from the user's wallpaper and generates a complete theme.

How It Works

  1. Source color extraction: The system identifies a dominant color from the wallpaper
  2. Tonal palette generation: That source color generates five tonal palettes (Primary, Secondary, Tertiary, Neutral, Neutral Variant)
  3. Color role mapping: Each palette shade maps to specific UI roles
  4. Theme application: The entire system UI and compatible apps update automatically

The result? Every user's device feels personally theirs, while maintaining accessibility and harmony.

The Tonal Palette System

Each tonal palette contains 13 tones: 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99, 100.

For a source color of #6750A4 (M3's default purple):

Tone Primary Palette Usage
0 #000000
10 #21005D Primary (dark theme) container
20 #381E72
30 #4F378B
40 #6750A4 Primary (light theme)
50 #7F67BE
60 #9A82DB
70 #B69DF8
80 #D0BCFF Primary (dark theme)
90 #EADDFF Primary Container (light)
95 #F6EDFF
99 #FFFBFE Background/Surface
100 #FFFFFF

Understanding M3 Color Roles

M3 defines specific roles for colors, ensuring consistent application across components.

Primary Colors

Secondary Colors

Tertiary Colors

Error Colors

Surface Colors

Outline Colors

Using Material Theme Builder

Google's Material Theme Builder is the official tool for generating M3 color schemes.

Step-by-Step

  1. Open the Theme Builder
  2. Choose a source color — enter a hex value or use the color picker
  3. Review the generated scheme—all roles are automatically populated
  4. Customize individual roles if needed (though the generated values are already accessible)
  5. Preview on sample components
  6. Export for your platform:
    • Android: Kotlin/XML theme files
    • Flutter: Dart theme file
    • Web: CSS/DSP tokens
    • Figma: Plugin integration

Custom Colors

M3 allows adding custom color roles beyond the three defaults:

  1. Click Custom colors in Theme Builder
  2. Add a color with a name (e.g., "Success" → #16A34A)
  3. The system generates tonal palettes and light/dark variants automatically
  4. Use these in your app alongside the standard roles

Accessibility Built Into M3

One of M3's strongest features is built-in accessibility:

Automatic Contrast

The tonal system ensures that "On" colors always meet WCAG AA contrast requirements against their background. For example:

Dark Theme Accessibility

In dark themes, M3 flips the tone mapping:

This is a significant improvement over manually managing dark mode colors. For more on accessibility standards, see our WCAG color accessibility guide.

Implementing M3 Colors

Android (Jetpack Compose)

@Composable
fun MyAppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context)
            else dynamicLightColorScheme(context)
        }
        darkTheme -> darkColorScheme(
            primary = Color(0xFFD0BCFF),
            secondary = Color(0xFFCCC2DC),
            tertiary = Color(0xFFEFB8C8)
        )
        else -> lightColorScheme(
            primary = Color(0xFF6750A4),
            secondary = Color(0xFF625B71),
            tertiary = Color(0xFF7D5260)
        )
    }
    MaterialTheme(colorScheme = colorScheme, content = content)
}

Web (CSS)

:root {
  --md-sys-color-primary: #6750A4;
  --md-sys-color-on-primary: #FFFFFF;
  --md-sys-color-primary-container: #EADDFF;
  --md-sys-color-surface: #FFFBFE;
  --md-sys-color-on-surface: #1C1B1F;
  --md-sys-color-outline: #79747E;
}

@media (prefers-color-scheme: dark) {
  :root {
    --md-sys-color-primary: #D0BCFF;
    --md-sys-color-on-primary: #381E72;
    --md-sys-color-primary-container: #4F378B;
    --md-sys-color-surface: #1C1B1F;
    --md-sys-color-on-surface: #E6E1E5;
    --md-sys-color-outline: #938F99;
  }
}

Flutter

final lightColorScheme = ColorScheme.fromSeed(
  seedColor: const Color(0xFF6750A4),
  brightness: Brightness.light,
);

final darkColorScheme = ColorScheme.fromSeed(
  seedColor: const Color(0xFF6750A4),
  brightness: Brightness.dark,
);

M3 vs M2 Color Changes

Feature Material Design 2 Material Design 3
Color source Fixed palette Dynamic/seed-based
Palette size Primary + Accent Primary + Secondary + Tertiary
Shading system 100-900 Tonal (0-100)
Dark mode Manual inversion Automatic tone shifting
Personalization None Wallpaper-based
Accessibility Manual checking Built-in contrast
Container concept Not explicit Primary/Secondary/Tertiary containers

Tips for Designing with M3

  1. Start with one source color — the system generates everything else
  2. Trust the generated palette — it's mathematically optimized for harmony and accessibility
  3. Use containers for secondary emphasis rather than primary colors everywhere
  4. Test with dynamic color on real Android devices—wallpaper-derived themes can surprise you
  5. Don't fight the system — if you need 10 custom colors, M3 might not be the right fit

Generate Your M3 Source Color

The entire M3 system starts with one well-chosen color. Use Coloracci's AI palette generator to explore options, find your perfect brand color, and then feed it into Material Theme Builder.

For the best results, choose a source color that's neither too saturated nor too muted—M3 works best in the mid-saturation range. Then let the system do what it does best: generate a complete, accessible, harmonious color scheme from that single seed.