Skip to main content

Introduction

Bulma generates CSS custom properties (also called CSS variables) for all major design tokens. Unlike Sass variables which are set at compile time, CSS variables can be modified at runtime, making them perfect for dynamic theming and component customization.

Variable Naming Convention

All Bulma CSS variables follow a consistent naming pattern:
--bulma-{property}
--bulma-{property}-{variant}
--bulma-{color}-{channel}
Examples:
  • --bulma-primary - Primary color
  • --bulma-primary-h - Primary hue
  • --bulma-primary-l - Primary lightness
  • --bulma-primary-invert - Inverted primary color
  • --bulma-radius - Border radius
  • --bulma-text-strong - Strong text color

Color System

Bulma uses the HSL color space, splitting each color into three channels for maximum flexibility:

HSL Channels

:root {
  /* Primary color channels */
  --bulma-primary-h: 171;      /* Hue (0-360) */
  --bulma-primary-s: 100%;     /* Saturation (0-100%) */
  --bulma-primary-l: 41%;      /* Lightness (0-100%) */
  
  /* Computed color */
  --bulma-primary: hsla(
    var(--bulma-primary-h),
    var(--bulma-primary-s),
    var(--bulma-primary-l),
    1
  );
}
Using HSL channels allows you to modify individual aspects of a color, like making it lighter or darker without changing hue.

Color Palette Variables

Each semantic color has a complete set of variables:
/* Primary Color */
--bulma-primary           /* Base color */
--bulma-primary-h         /* Hue */
--bulma-primary-s         /* Saturation */
--bulma-primary-l         /* Lightness */
--bulma-primary-invert    /* Contrasting color */
--bulma-primary-light     /* Light variant (90% lightness) */
--bulma-primary-dark      /* Dark variant (10% lightness) */
--bulma-primary-soft      /* Soft background variant */
--bulma-primary-bold      /* Bold foreground variant */

/* 20 shades: 00, 05, 10, 15, ..., 95, 100 */
--bulma-primary-00        /* Nearly black */
--bulma-primary-05
--bulma-primary-10
/* ... */
--bulma-primary-95
--bulma-primary-100       /* Nearly white */
This applies to all semantic colors:
  • --bulma-primary-*
  • --bulma-info-*
  • --bulma-success-*
  • --bulma-warning-*
  • --bulma-danger-*
  • --bulma-link-*
  • --bulma-dark-*
  • --bulma-light-*

Scheme Variables

Scheme variables control the overall color scheme:
:root {
  /* Base scheme */
  --bulma-scheme-h: 221;
  --bulma-scheme-s: 14%;
  
  /* Main backgrounds */
  --bulma-scheme-main-l: 100%;       /* Lightest */
  --bulma-scheme-main-bis-l: 98%;    /* Slightly darker */
  --bulma-scheme-main-ter-l: 96%;    /* Even darker */
  --bulma-scheme-main: hsl(
    var(--bulma-scheme-h),
    var(--bulma-scheme-s),
    var(--bulma-scheme-main-l)
  );
  
  /* Inverted colors (for dark text on light bg) */
  --bulma-scheme-invert-l: 4%;
  --bulma-scheme-invert-bis-l: 9%;
  --bulma-scheme-invert-ter-l: 14%;
}

Text Variables

:root {
  /* Text colors */
  --bulma-text-h: 221;
  --bulma-text-s: 14%;
  --bulma-text-l: 29%;               /* Base text */
  --bulma-text-weak-l: 48%;          /* Secondary text */
  --bulma-text-strong-l: 21%;        /* Emphasized text */
  --bulma-text-title-l: 14%;         /* Title text */
  
  /* Computed text colors */
  --bulma-text: hsl(
    var(--bulma-text-h),
    var(--bulma-text-s),
    var(--bulma-text-l)
  );
  --bulma-text-weak: hsl(
    var(--bulma-text-h),
    var(--bulma-text-s),
    var(--bulma-text-weak-l)
  );
  --bulma-text-strong: hsl(
    var(--bulma-text-h),
    var(--bulma-text-s),
    var(--bulma-text-strong-l)
  );
}

UI Variables

Background

:root {
  --bulma-background-l: 96%;
  --bulma-background: hsl(
    var(--bulma-scheme-h),
    var(--bulma-scheme-s),
    var(--bulma-background-l)
  );
}

Borders

:root {
  --bulma-border-l: 86%;
  --bulma-border-weak-l: 93%;
  --bulma-border: hsl(
    var(--bulma-scheme-h),
    var(--bulma-scheme-s),
    var(--bulma-border-l)
  );
  --bulma-border-weak: hsl(
    var(--bulma-scheme-h),
    var(--bulma-scheme-s),
    var(--bulma-border-weak-l)
  );
}

Typography Variables

:root {
  /* Font families */
  --bulma-family-primary: "Inter", "SF Pro", "Segoe UI", sans-serif;
  --bulma-family-secondary: "Inter", "SF Pro", "Segoe UI", sans-serif;
  --bulma-family-code: "Inconsolata", "Hack", monospace;
  
  /* Font sizes */
  --bulma-size-1: 3rem;         /* 48px */
  --bulma-size-2: 2.5rem;       /* 40px */
  --bulma-size-3: 2rem;         /* 32px */
  --bulma-size-4: 1.5rem;       /* 24px */
  --bulma-size-5: 1.25rem;      /* 20px */
  --bulma-size-6: 1rem;         /* 16px */
  --bulma-size-7: 0.75rem;      /* 12px */
  
  --bulma-size-small: var(--bulma-size-7);
  --bulma-size-normal: var(--bulma-size-6);
  --bulma-size-medium: var(--bulma-size-5);
  --bulma-size-large: var(--bulma-size-4);
  
  /* Font weights */
  --bulma-weight-light: 300;
  --bulma-weight-normal: 400;
  --bulma-weight-medium: 500;
  --bulma-weight-semibold: 600;
  --bulma-weight-bold: 700;
  --bulma-weight-extrabold: 800;
}

Spacing Variables

:root {
  --bulma-block-spacing: 1.5rem;
}

Border Radius Variables

:root {
  --bulma-radius-small: 0.25rem;
  --bulma-radius: 0.375rem;
  --bulma-radius-medium: 0.5em;
  --bulma-radius-large: 0.75rem;
  --bulma-radius-rounded: 9999px;
}

Animation Variables

:root {
  --bulma-speed: 86ms;
  --bulma-duration: 294ms;
  --bulma-easing: ease-out;
}

Interaction Deltas

Bulma uses “delta” variables for hover and active states:
:root {
  /* Light theme - darken on interaction */
  --bulma-hover-background-l-delta: -5%;
  --bulma-active-background-l-delta: -10%;
  --bulma-hover-border-l-delta: -10%;
  --bulma-active-border-l-delta: -20%;
  --bulma-hover-color-l-delta: -5%;
  --bulma-active-color-l-delta: -10%;
}

[data-theme="dark"] {
  /* Dark theme - lighten on interaction */
  --bulma-hover-background-l-delta: 5%;
  --bulma-active-background-l-delta: 10%;
  --bulma-hover-border-l-delta: 10%;
  --bulma-active-border-l-delta: 20%;
}

Customization Examples

Change Primary Color

:root {
  --bulma-primary-h: 271;      /* Purple hue */
  --bulma-primary-s: 100%;
  --bulma-primary-l: 71%;
}

Adjust Border Radius Globally

:root {
  --bulma-radius: 0;           /* No rounded corners */
  --bulma-radius-small: 0;
  --bulma-radius-medium: 0;
  --bulma-radius-large: 0;
}

Make Text Lighter

:root {
  --bulma-text-l: 40%;         /* Lighter than default 29% */
  --bulma-text-strong-l: 30%;  /* Lighter strong text */
}

Increase Font Sizes

:root {
  --bulma-size-1: 3.5rem;
  --bulma-size-2: 3rem;
  --bulma-size-3: 2.5rem;
  --bulma-size-4: 2rem;
  --bulma-size-5: 1.5rem;
  --bulma-size-6: 1.125rem;    /* 18px base instead of 16px */
  --bulma-size-7: 0.875rem;
}

Component-Specific Customization

Scope variables to specific components:
/* Override button colors */
.button.is-primary {
  --bulma-primary-h: 200;
  --bulma-primary-s: 80%;
  --bulma-primary-l: 50%;
}

/* Custom card styling */
.card {
  --bulma-radius: 1rem;
  --bulma-border-l: 90%;
}

/* Custom navbar */
.navbar {
  --bulma-scheme-main-l: 95%;
  --bulma-text-l: 20%;
}

Runtime Theming with JavaScript

Change variables dynamically with JavaScript:

Change Single Variable

document.documentElement.style.setProperty(
  '--bulma-primary-h',
  '271'
);

Change Multiple Variables

function setThemeColor(hue, saturation, lightness) {
  const root = document.documentElement;
  root.style.setProperty('--bulma-primary-h', hue);
  root.style.setProperty('--bulma-primary-s', `${saturation}%`);
  root.style.setProperty('--bulma-primary-l', `${lightness}%`);
}

// Usage
setThemeColor(271, 100, 71); // Purple

Theme Color Picker

<div class="field">
  <label class="label">Primary Color</label>
  <div class="control">
    <input type="color" id="color-picker" class="input" value="#00d1b2">
  </div>
</div>

<script>
const picker = document.getElementById('color-picker');

picker.addEventListener('input', (e) => {
  const color = e.target.value;
  
  // Convert hex to HSL
  const rgb = hexToRgb(color);
  const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
  
  // Update CSS variables
  document.documentElement.style.setProperty('--bulma-primary-h', hsl.h);
  document.documentElement.style.setProperty('--bulma-primary-s', `${hsl.s}%`);
  document.documentElement.style.setProperty('--bulma-primary-l', `${hsl.l}%`);
});

function hexToRgb(hex) {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null;
}

function rgbToHsl(r, g, b) {
  r /= 255;
  g /= 255;
  b /= 255;
  
  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  let h, s, l = (max + min) / 2;
  
  if (max === min) {
    h = s = 0;
  } else {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    
    switch (max) {
      case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
      case g: h = ((b - r) / d + 2) / 6; break;
      case b: h = ((r - g) / d + 4) / 6; break;
    }
  }
  
  return {
    h: Math.round(h * 360),
    s: Math.round(s * 100),
    l: Math.round(l * 100)
  };
}
</script>

Dynamic Font Size Adjustment

<input 
  type="range" 
  id="font-scale" 
  min="0.8" 
  max="1.2" 
  step="0.05" 
  value="1"
>

<script>
const fontScale = document.getElementById('font-scale');

fontScale.addEventListener('input', (e) => {
  const scale = parseFloat(e.target.value);
  const root = document.documentElement;
  
  root.style.setProperty('--bulma-size-1', `${3 * scale}rem`);
  root.style.setProperty('--bulma-size-2', `${2.5 * scale}rem`);
  root.style.setProperty('--bulma-size-3', `${2 * scale}rem`);
  root.style.setProperty('--bulma-size-4', `${1.5 * scale}rem`);
  root.style.setProperty('--bulma-size-5', `${1.25 * scale}rem`);
  root.style.setProperty('--bulma-size-6', `${1 * scale}rem`);
  root.style.setProperty('--bulma-size-7', `${0.75 * scale}rem`);
});
</script>

Comparison: Sass Variables vs CSS Variables

// Sass variable - compile time
$primary: hsl(171, 100%, 41%);

.button {
  background-color: $primary; // → background-color: hsl(171, 100%, 41%);
}
/* CSS variable - runtime */
:root {
  --bulma-primary: hsl(171, 100%, 41%);
}

.button {
  background-color: var(--bulma-primary); /* Can be changed dynamically */
}
Bulma uses Sass variables to generate CSS variables, giving you the best of both worlds.

Browser Support

CSS custom properties are supported in all modern browsers:
  • Chrome 49+
  • Firefox 31+
  • Safari 9.1+
  • Edge 15+
CSS variables are not supported in Internet Explorer 11. Consider using a PostCSS plugin like postcss-custom-properties for fallback support.

Next Steps

Theme System

Learn how to implement light/dark themes using CSS variables

Sass Variables

Understand the relationship between Sass and CSS variables

Build docs developers (and LLMs) love