Courses/HTML & CSS/Custom Properties Themes

    Custom Properties for Themes & Dynamic UI

    Lesson 31 โ€ข Advanced Track

    What You'll Learn

    Manipulate custom properties with JavaScript for dynamic theming
    Create component-scoped variables for variant styling
    Build a multi-theme switcher with data attributes
    Use HSL with custom properties for flexible colour systems
    Change responsive values via variables in media queries

    ๐Ÿ’ก Think of It Like This

    Custom properties are like a control panel in a car. Instead of rewiring the engine to change speed, you turn a knob. Scoped properties are like having separate climate controls for front and back seats โ€” independent settings within the same vehicle. HSL-based variables are like having a single colour wheel that generates your entire palette from one hue value.

    Understanding Dynamic Theming

    CSS custom properties (variables) are not just static value holders โ€” they're live. When you change a variable's value via JavaScript (element.style.setProperty('--hue', '300')), every CSS rule referencing that variable updates instantly. This makes them the foundation for interactive themes.

    The HSL colour model is ideal for theming because you can derive an entire colour scheme from a single hue number. By changing --hue alone, you get matching primary, light, and dark variants automatically.

    Key Custom Property Patterns

    PatternExampleUse Case
    Global tokens:root { --primary: blue }Site-wide design tokens
    Scoped overrides.alert { --color: red }Component variants
    JS manipulationstyle.setProperty()Runtime theme changes
    Fallback valuesvar(--x, fallback)Safety when var is undefined
    Responsive vars@media { :root { --cols: 1 } }Responsive without per-property overrides

    1. Dynamic Hue & Radius Controls

    Try it Yourself ยป
    Code Preview
    <!DOCTYPE html>
    <html><head><style>
    :root { --hue: 210; --saturation: 80%; --primary: hsl(var(--hue), var(--saturation), 45%); --primary-light: hsl(var(--hue), var(--saturation), 92%); --primary-dark: hsl(var(--hue), var(--saturation), 30%); --radius: 8px; --spacing: 16px; }
    body { font-family: system-ui, sans-serif; padding: 24px; background: #fafafa; }
    .controls { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 24px; align-items: center; }
    .controls label { font-weight: 600; font-siz
    ...

    2. Scoped Variables for Components

    Try it Yourself ยป
    Code Preview
    <!DOCTYPE html>
    <html><head><style>
    body { font-family: system-ui, sans-serif; padding: 24px; }
    .alert { --alert-bg: #E3F2FD; --alert-border: #1976D2; --alert-text: #0D47A1; background: var(--alert-bg); border-left: 4px solid var(--alert-border); color: var(--alert-text); padding: 16px; border-radius: 0 8px 8px 0; margin: 12px 0; }
    .alert.success { --alert-bg: #E8F5E9; --alert-border: #4CAF50; --alert-text: #1B5E20; }
    .alert.warning { --alert-bg: #FFF3E0; --alert-border: #FF9800; --alert-text: #
    ...

    Scoping explained: When you define --alert-bg inside .alert, the variable only exists within that element and its children. A modifier class (.alert.success) overrides those same variables, creating a variant without any new properties โ€” just new values.

    3. Multi-Theme Switcher

    Try it Yourself ยป
    Code Preview
    <!DOCTYPE html>
    <html><head><style>
    :root, [data-theme="ocean"] { --bg: #E3F2FD; --surface: #fff; --primary: #1565C0; --text: #0D47A1; --accent: #00BCD4; }
    [data-theme="forest"] { --bg: #E8F5E9; --surface: #fff; --primary: #2E7D32; --text: #1B5E20; --accent: #8BC34A; }
    [data-theme="sunset"] { --bg: #FFF3E0; --surface: #fff; --primary: #E65100; --text: #BF360C; --accent: #FF5722; }
    [data-theme="midnight"] { --bg: #1a1a2e; --surface: #16213e; --primary: #64B5F6; --text: #e0e0e0; --accent: #AB47BC;
    ...

    4. Responsive Variables in Media Queries

    Try it Yourself ยป
    Code Preview
    <!DOCTYPE html>
    <html><head><style>
    :root { --gap: 16px; --cols: 3; --font-body: 1rem; --padding: 24px; }
    @media (max-width: 768px) { :root { --gap: 12px; --cols: 2; --font-body: 0.95rem; --padding: 16px; } }
    @media (max-width: 480px) { :root { --gap: 8px; --cols: 1; --font-body: 0.9rem; --padding: 12px; } }
    body { font-family: system-ui; padding: var(--padding); background: #fafafa; }
    .grid { display: grid; grid-template-columns: repeat(var(--cols), 1fr); gap: var(--gap); }
    .item { background: 
    ...

    When to Use This

    • Design systems: Define all tokens (colours, spacing, radii) as variables for consistency
    • Theme switchers: Light/dark mode, brand theming, user preferences
    • Component libraries: Scoped variables let consumers customise without !important
    • Interactive demos: Sliders, colour pickers that update UI in real time

    โš ๏ธ Common Mistakes

    • Forgetting fallback values โ€” Always provide: var(--color, blue). If the variable is undefined, the fallback prevents breakage.
    • Overusing :root โ€” Scope variables to components when they're only needed there. Global scope pollutes the namespace.
    • Using custom properties for static values โ€” If a value never changes and isn't part of a theme, a regular property is simpler.
    • Not using HSL for colour systems โ€” Hex codes make deriving light/dark variants impossible. HSL lets you mathematically generate shades.
    • Nesting var() inside calc() incorrectly โ€” calc(var(--x) + 10px) works, but calc(var(--x) + 10) fails if --x has units.
    • Expecting animations on variables โ€” CSS variables can't be transitioned directly (yet). Use @property registration for animatable custom properties.

    ๐ŸŽ‰ Lesson Complete

    • โœ… JavaScript can update custom properties in real time via style.setProperty()
    • โœ… HSL + custom properties = flexible, math-friendly colour systems
    • โœ… Scoped variables create component variants without extra classes
    • โœ… [data-theme] selectors enable multi-theme switching
    • โœ… Variables in media queries simplify responsive design
    • โœ… Fallbacks prevent breakage when variables are undefined
    • โœ… @property enables animating custom properties
    • โœ… Custom properties are the foundation of modern CSS architecture

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy Policy โ€ข Terms of Service