Theme Settings and Extensibility Beginner 12 min read

Global Theme Settings: Colors, Typography, Spacing

Create a robust settings system for your Shopify theme with global controls for colors, typography, and spacing that cascade throughout the entire theme.

Global theme settings let merchants customize their store’s visual identity without touching code. A well-designed settings system creates a cohesive design while offering meaningful flexibility.

Settings Schema Location

Global settings live in config/settings_schema.json:

[
{
"name": "theme_info",
"theme_name": "My Theme",
"theme_version": "1.0.0",
"theme_author": "Your Name",
"theme_documentation_url": "https://docs.example.com",
"theme_support_url": "https://support.example.com"
},
{
"name": "Colors",
"settings": [
{
"type": "color",
"id": "color_primary",
"label": "Primary color",
"default": "#3B82F6"
}
]
}
]

Accessing Global Settings

Use settings object anywhere in your theme:

{{ settings.color_primary }}
{{ settings.type_base_font }}
{{ settings.spacing_grid }}

Color Settings

Basic Color Palette

{
"name": "Colors",
"settings": [
{
"type": "header",
"content": "Primary colors"
},
{
"type": "color",
"id": "color_primary",
"label": "Primary",
"default": "#3B82F6",
"info": "Used for buttons, links, and accents"
},
{
"type": "color",
"id": "color_secondary",
"label": "Secondary",
"default": "#10B981"
},
{
"type": "header",
"content": "Text colors"
},
{
"type": "color",
"id": "color_text",
"label": "Text",
"default": "#1F2937"
},
{
"type": "color",
"id": "color_text_light",
"label": "Secondary text",
"default": "#6B7280"
},
{
"type": "header",
"content": "Background colors"
},
{
"type": "color",
"id": "color_background",
"label": "Page background",
"default": "#FFFFFF"
},
{
"type": "color",
"id": "color_background_secondary",
"label": "Secondary background",
"default": "#F3F4F6",
"info": "Used for cards, callouts, and alternate sections"
},
{
"type": "header",
"content": "UI colors"
},
{
"type": "color",
"id": "color_border",
"label": "Borders",
"default": "#E5E7EB"
},
{
"type": "color",
"id": "color_success",
"label": "Success",
"default": "#10B981"
},
{
"type": "color",
"id": "color_error",
"label": "Error",
"default": "#EF4444"
}
]
}

Applying Colors via CSS Variables

In your main layout or CSS file:

{# snippets/css-variables.liquid #}
{%- style -%}
:root {
--color-primary: {{ settings.color_primary }};
--color-primary-rgb: {{ settings.color_primary | color_to_rgb | remove: 'rgb(' | remove: ')' }};
--color-secondary: {{ settings.color_secondary }};
--color-text: {{ settings.color_text }};
--color-text-light: {{ settings.color_text_light }};
--color-background: {{ settings.color_background }};
--color-background-secondary: {{ settings.color_background_secondary }};
--color-border: {{ settings.color_border }};
--color-success: {{ settings.color_success }};
--color-error: {{ settings.color_error }};
{# Derived colors with transparency #}
--color-primary-10: {{ settings.color_primary | color_modify: 'alpha', 0.1 }};
--color-primary-20: {{ settings.color_primary | color_modify: 'alpha', 0.2 }};
}
{%- endstyle -%}

Typography Settings

Font Selection

{
"name": "Typography",
"settings": [
{
"type": "header",
"content": "Headings"
},
{
"type": "font_picker",
"id": "type_heading_font",
"label": "Font",
"default": "assistant_n4"
},
{
"type": "select",
"id": "type_heading_weight",
"label": "Weight",
"options": [
{ "value": "400", "label": "Regular" },
{ "value": "500", "label": "Medium" },
{ "value": "600", "label": "Semibold" },
{ "value": "700", "label": "Bold" }
],
"default": "700"
},
{
"type": "select",
"id": "type_heading_transform",
"label": "Letter case",
"options": [
{ "value": "none", "label": "Normal" },
{ "value": "uppercase", "label": "Uppercase" },
{ "value": "capitalize", "label": "Capitalize" }
],
"default": "none"
},
{
"type": "header",
"content": "Body text"
},
{
"type": "font_picker",
"id": "type_body_font",
"label": "Font",
"default": "assistant_n4"
},
{
"type": "range",
"id": "type_body_size",
"label": "Base size",
"min": 14,
"max": 20,
"step": 1,
"default": 16,
"unit": "px"
},
{
"type": "range",
"id": "type_body_line_height",
"label": "Line height",
"min": 1.2,
"max": 2,
"step": 0.1,
"default": 1.6
}
]
}

Applying Typography

{# Font face declarations #}
{%- style -%}
{{ settings.type_heading_font | font_face: font_display: 'swap' }}
{{ settings.type_body_font | font_face: font_display: 'swap' }}
:root {
--font-heading: {{ settings.type_heading_font.family }}, {{ settings.type_heading_font.fallback_families }};
--font-heading-weight: {{ settings.type_heading_weight }};
--font-heading-style: {{ settings.type_heading_font.style }};
--font-heading-transform: {{ settings.type_heading_transform }};
--font-body: {{ settings.type_body_font.family }}, {{ settings.type_body_font.fallback_families }};
--font-body-weight: {{ settings.type_body_font.weight }};
--font-body-style: {{ settings.type_body_font.style }};
--font-size-base: {{ settings.type_body_size }}px;
--line-height-base: {{ settings.type_body_line_height }};
}
{%- endstyle -%}

Using Typography Variables

body {
font-family: var(--font-body);
font-weight: var(--font-body-weight);
font-style: var(--font-body-style);
font-size: var(--font-size-base);
line-height: var(--line-height-base);
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-heading);
font-weight: var(--font-heading-weight);
font-style: var(--font-heading-style);
text-transform: var(--font-heading-transform);
}

Spacing Settings

Spacing Scale

{
"name": "Layout",
"settings": [
{
"type": "header",
"content": "Spacing"
},
{
"type": "range",
"id": "spacing_base",
"label": "Base spacing unit",
"min": 4,
"max": 8,
"step": 1,
"default": 4,
"unit": "px",
"info": "All spacing is calculated from this value"
},
{
"type": "range",
"id": "spacing_section",
"label": "Section spacing",
"min": 20,
"max": 100,
"step": 10,
"default": 60,
"unit": "px"
},
{
"type": "header",
"content": "Container"
},
{
"type": "range",
"id": "container_width",
"label": "Maximum width",
"min": 1000,
"max": 1600,
"step": 40,
"default": 1200,
"unit": "px"
},
{
"type": "range",
"id": "container_padding",
"label": "Horizontal padding",
"min": 16,
"max": 48,
"step": 4,
"default": 24,
"unit": "px"
}
]
}

Spacing Variables

{%- style -%}
:root {
{# Base unit #}
--spacing-unit: {{ settings.spacing_base }}px;
{# Spacing scale (multiples of base) #}
--spacing-xs: calc(var(--spacing-unit) * 1); {# 4px #}
--spacing-sm: calc(var(--spacing-unit) * 2); {# 8px #}
--spacing-md: calc(var(--spacing-unit) * 4); {# 16px #}
--spacing-lg: calc(var(--spacing-unit) * 6); {# 24px #}
--spacing-xl: calc(var(--spacing-unit) * 8); {# 32px #}
--spacing-2xl: calc(var(--spacing-unit) * 12); {# 48px #}
--spacing-3xl: calc(var(--spacing-unit) * 16); {# 64px #}
--spacing-section: {{ settings.spacing_section }}px;
--container-width: {{ settings.container_width }}px;
--container-padding: {{ settings.container_padding }}px;
}
{%- endstyle -%}

Border and Radius Settings

{
"name": "Borders",
"settings": [
{
"type": "range",
"id": "border_radius",
"label": "Corner radius",
"min": 0,
"max": 24,
"step": 2,
"default": 8,
"unit": "px"
},
{
"type": "select",
"id": "border_width",
"label": "Border width",
"options": [
{ "value": "1", "label": "Thin" },
{ "value": "2", "label": "Medium" },
{ "value": "3", "label": "Thick" }
],
"default": "1"
},
{
"type": "select",
"id": "button_style",
"label": "Button corners",
"options": [
{ "value": "square", "label": "Square" },
{ "value": "rounded", "label": "Rounded" },
{ "value": "pill", "label": "Pill" }
],
"default": "rounded"
}
]
}

Border Variables

{%- style -%}
:root {
--border-radius-sm: calc({{ settings.border_radius }}px * 0.5);
--border-radius: {{ settings.border_radius }}px;
--border-radius-lg: calc({{ settings.border_radius }}px * 2);
--border-width: {{ settings.border_width }}px;
{%- case settings.button_style -%}
{%- when 'square' -%}
--button-radius: 0;
{%- when 'rounded' -%}
--button-radius: var(--border-radius);
{%- when 'pill' -%}
--button-radius: 9999px;
{%- endcase -%}
}
{%- endstyle -%}

Animation Settings

{
"name": "Animations",
"settings": [
{
"type": "checkbox",
"id": "enable_animations",
"label": "Enable animations",
"default": true,
"info": "Respects user's reduced motion preference"
},
{
"type": "select",
"id": "animation_speed",
"label": "Animation speed",
"options": [
{ "value": "fast", "label": "Fast" },
{ "value": "normal", "label": "Normal" },
{ "value": "slow", "label": "Slow" }
],
"default": "normal"
}
]
}

Animation Variables

{%- style -%}
:root {
{%- case settings.animation_speed -%}
{%- when 'fast' -%}
--duration-short: 100ms;
--duration-medium: 200ms;
--duration-long: 300ms;
{%- when 'normal' -%}
--duration-short: 150ms;
--duration-medium: 300ms;
--duration-long: 500ms;
{%- when 'slow' -%}
--duration-short: 200ms;
--duration-medium: 400ms;
--duration-long: 700ms;
{%- endcase -%}
--ease-default: cubic-bezier(0.4, 0, 0.2, 1);
--ease-in: cubic-bezier(0.4, 0, 1, 1);
--ease-out: cubic-bezier(0, 0, 0.2, 1);
}
{%- unless settings.enable_animations -%}
@media (prefers-reduced-motion: no-preference) {
:root {
--duration-short: 0ms;
--duration-medium: 0ms;
--duration-long: 0ms;
}
}
{%- endunless -%}
@media (prefers-reduced-motion: reduce) {
:root {
--duration-short: 0ms;
--duration-medium: 0ms;
--duration-long: 0ms;
}
}
{%- endstyle -%}

Complete CSS Variables Snippet

Organize all variables in one place:

{# snippets/css-variables.liquid #}
{%- style -%}
{# Font faces #}
{{ settings.type_heading_font | font_face: font_display: 'swap' }}
{{ settings.type_body_font | font_face: font_display: 'swap' }}
:root {
{# Colors #}
--color-primary: {{ settings.color_primary }};
--color-primary-rgb: {{ settings.color_primary | color_to_rgb | remove: 'rgb(' | remove: ')' }};
--color-secondary: {{ settings.color_secondary }};
--color-text: {{ settings.color_text }};
--color-text-light: {{ settings.color_text_light }};
--color-background: {{ settings.color_background }};
--color-background-secondary: {{ settings.color_background_secondary }};
--color-border: {{ settings.color_border }};
--color-success: {{ settings.color_success }};
--color-error: {{ settings.color_error }};
{# Typography #}
--font-heading: {{ settings.type_heading_font.family }}, {{ settings.type_heading_font.fallback_families }};
--font-heading-weight: {{ settings.type_heading_weight }};
--font-body: {{ settings.type_body_font.family }}, {{ settings.type_body_font.fallback_families }};
--font-size-base: {{ settings.type_body_size }}px;
--line-height-base: {{ settings.type_body_line_height }};
{# Spacing #}
--spacing-unit: {{ settings.spacing_base }}px;
--spacing-xs: calc(var(--spacing-unit) * 1);
--spacing-sm: calc(var(--spacing-unit) * 2);
--spacing-md: calc(var(--spacing-unit) * 4);
--spacing-lg: calc(var(--spacing-unit) * 6);
--spacing-xl: calc(var(--spacing-unit) * 8);
--spacing-2xl: calc(var(--spacing-unit) * 12);
--spacing-section: {{ settings.spacing_section }}px;
{# Layout #}
--container-width: {{ settings.container_width }}px;
--container-padding: {{ settings.container_padding }}px;
{# Borders #}
--border-radius: {{ settings.border_radius }}px;
--border-width: {{ settings.border_width }}px;
}
{%- endstyle -%}

Include in layout:

{# layout/theme.liquid #}
<head>
{# ... #}
{% render 'css-variables' %}
</head>

Practice Exercise

Create a complete settings schema for:

  1. Brand colors (primary, secondary, accent)
  2. Typography (heading and body fonts)
  3. Layout spacing and container width
  4. Border radius and button style

Test by:

  • Changing colors in theme editor
  • Verifying CSS variables update
  • Checking all components use variables

Key Takeaways

  1. settings_schema.json defines global settings
  2. CSS custom properties cascade settings throughout theme
  3. Color filters like color_to_rgb for advanced use
  4. Font picker with font_face filter for loading
  5. Range inputs for numerical settings with units
  6. Spacing scale based on multipliers
  7. Reduced motion respect for accessibility

🛠 Building Section Schemas? While this lesson covers global theme settings, our Schema Builder helps you create section-level schemas with visual editing and live JSON preview.

What’s Next?

The next lesson covers Color Schemes and Design Tokens for more advanced theming systems.

Finished this lesson?

Mark it complete to track your progress.

Discussion

Loading comments...