Variables and Modes

This content was generated with the assistance of AI and should be verified against the official Webflow documentation before being relied on in production.

This sub-section’s Webflow bibliography lists the reference material consulted while preparing these pages.

This page was checked against the Webflow Help Center, the Webflow updates feed and the Designer API reference on 2026-10-28. Webflow is a hosted service without version numbers, so a menu name or a limit can change between two visits. Variables are available in the Designer of every plan, including the free Starter Site plan in a Starter Workspace, and nothing on this page depends on a paid tier. The Designer API examples use @webflow/designer-extension-typings 2.2.2 and the Designer API as documented at developers.webflow.com; they need the canModifyVariables ability, which a Designer Extension has only when the user who runs it is allowed to edit the site in the Designer.

Variables are the part of Webflow that turns a design into a system. A variable is a named value, for example a colour, a size or a font, that is stored once and used in many places. When the value changes, every place that uses it changes. Variables are the Webflow interface to CSS custom properties, which the HTML and CSS theming page explains from the CSS side; this page explains the Webflow side: what kinds of variables exist, how they are organised, how a second set of values (a mode) is defined and applied, what CSS Webflow publishes, how to drive all of it from code, and how to move a site that was built on swatches to variables.

The running example is the Fernbrook Gardens site, a fictitious botanical garden. Fernbrook wants one brand palette, one spacing scale, a fluid type scale, a Day and a Night look for the evening events pages, and a roomier layout on large screens. All of those are variables and modes, and this page builds them in that order.

The problem variables solve

Before variables, a Webflow designer who wanted every call-to-action button to use Fernbrook green had two options. The first was to type the same hex value into every class that needed it, which makes a rebrand a search-and-replace across hundreds of classes. The second was to keep a swatch, a saved colour in the colour picker, which is a shortcut for choosing a colour and is not a link: editing the swatch afterwards does not update the places that already used it.

A variable is a link. The Style panel stores a reference to the variable instead of a literal value, and the published CSS contains var(--name) where the literal value would have been. Three consequences follow, and they explain why the rest of the Design Systems section builds on this page.

  • One edit changes everything. Changing the variable Brand / Green changes every class, state and breakpoint that uses it.

  • A value can have several versions. A mode gives the same variable a different value in a different context: night instead of day, a larger spacing scale on a wide screen.

  • Design intent gets a name. Text / Primary says what a colour is for; #1f3d2b says only what it looks like. Names are what lets a team, a component library and a code export agree.

Variable types

Webflow supports five types of variable. The type is chosen when the variable is created and cannot be changed afterwards, although the value can be edited at any time. A type decides where the variable can be used, because the Style panel only offers a variable in a control that accepts its type.

Type Holds Where it can be used

Color

A colour, with or without transparency

Text, background, border and stroke colours, shadow colours and gradient stops

Size

A length with a unit, for example 1.5rem, 24px, 100vh

Width, height, margin, padding, gap, position offsets, font size, line height, border width and radius, blur and shadow lengths

Percentage

A percentage

A narrower set than Size: gap, flex basis, spacing, sizing, position and some typography and border-radius properties

Number

A unitless number

Properties that take a plain number such as opacity, z-index, flex grow and shrink, or line height as a multiplier

Font

A font family name

Font family controls

Two details save time. First, a Size variable stores its unit with the number, so a spacing scale in rem stays in rem wherever it is used; use Percentage only where the percentage reads as a share of the parent. Second, a Font variable stores the family, not the weight or style, so Heading font and Body font are the usual pair and the weight is still chosen in the Typography section, as described in Typography and Fonts.

The set of types follows the CSS properties Webflow’s Style panel can write. There is no variable type for a free-form string, an image or a shadow as a whole. A shadow is built from a Size for the offsets and blur and a Color for the colour, each bound separately, as Backgrounds, Borders and Effects shows.

Collections

Variables live in collections. A collection groups variables that belong together and is the unit to which modes are attached: a mode belongs to a collection and gives a value to each variable in that collection. A new site starts with one collection, called Base collection, and the Variables panel (the variables icon in the left toolbar, or the keyboard shortcut shown in its tooltip) lists the collections of the site, the variables of the selected collection and one column per mode.

Collections are mostly an organisation tool, and the most useful split follows how often values change together:

Collection (Fernbrook) Contents Modes

Brand

Green 700, Green 100, Soil 800, Petal 500 and other raw palette colours

Base only

Theme

Surface, Text / Primary, Text / Muted, Border, Accent as aliases of the palette

Base (Day) and Night

Spacing

Space 1 to Space 8, Gutter, Section padding

Base, plus Wide (breakpoint)

Type

Heading font, Body font, Size / Body, Size / H1 as function variables

Base

Within a collection, variables can be grouped in folders using a slash in the name, such as Text / Primary, which the panel shows as a folder Text containing Primary. The folder is purely organisational in the panel; it also shows up in the generated custom property name, as described in the section on generated CSS.

Collections can also be shared between sites with a library; see Shared Libraries.

Aliases

An alias is a variable whose value is another variable. In the Variables panel, the value field of a variable accepts a variable instead of a literal, and the alias then displays the name of its target. Updating the target updates every alias, in every mode.

Aliases give a design system two layers, which is the standard way to build a theme.

  • Primitive variables hold raw values and are named after what they are: Green 700, Space 4. They are changed rarely.

  • Semantic variables are aliases named after what they do: Text / Primary, Accent, Section padding. They are the variables that classes use.

The benefit is that a mode only needs to repoint the semantic layer. In the Theme collection, Surface points to Paper 50 in the base (Day) mode and to Soil 800 in the Night mode; the classes never mention either palette colour.

flowchart LR subgraph Brand["Collection: Brand (Base mode)"] P1["Paper 50
#faf8f2"] P2["Soil 800
#24201b"] P3["Green 700
#1f3d2b"] P4["Green 100
#d9eadf"] end subgraph Theme["Collection: Theme"] direction TB subgraph Day["Base mode: Day"] D1["Surface"] D2["Text / Primary"] end subgraph Night["Manual mode: Night"] N1["Surface"] N2["Text / Primary"] end end D1 -- alias --> P1 D2 -- alias --> P2 N1 -- alias --> P2 N2 -- alias --> P1 C[".plant-card
background: var(--surface)"] -. uses .-> D1 C -. uses .-> N1

The diagram shows the three relationships to remember: aliases point from the semantic layer to the primitive layer, each mode of a collection has its own pointer for the same variable, and a class refers to the variable only, so the mode that applies at that point of the page decides which pointer is followed.

Aliases can chain, and an alias can refer to a variable of another collection. Avoid long chains: when a colour looks wrong, the cause has to be found by following the chain by hand.

Function variables

Since June 2025 a variable value is not limited to a literal. A variable can hold a CSS function written in the custom value editor, and the value is published as written. The functions Webflow supports are calc(), clamp(), min(), max() and color-mix(). The custom value editor autocompletes variable names and function names, and the menu that connects a control to a variable, formerly marked with a purple dot, is called the Connect menu.

Function variables are how a fluid type or spacing scale is defined once. The variable Size / H1 below grows with the viewport between two limits and refers to the spacing variable Space 2 in an expression:

/* Value typed into the custom value editor of the variable "Size / H1" */
clamp(2rem, 1.4rem + 2.4vw, 3.5rem)

/* A value that refers to another variable inside a function */
calc(var(--space-2) * 2)

/* A derived colour: Green 700 mixed 20% with white */
color-mix(in srgb, var(--green-700) 80%, white)

Four rules keep function variables manageable.

  • The type still decides where the variable can be used. A function that returns a length belongs in a Size variable; a function that returns a colour, such as color-mix(), belongs in a Color variable.

  • Unitless math fails. calc(1rem + 2) is invalid CSS because the browser cannot add a length and a number. The editor writes what is typed, so test the result at a few viewport widths.

  • A function does not make a variable responsive on its own. clamp() with a vw term is fluid between its limits. A step change at a breakpoint is a mode, described next.

  • Reuse before repeating. Define the scale once and alias it, so that Size / H1 is used by the heading classes and never retyped.

The feature was announced in the Webflow updates feed. A follow-up Designer API update added the helper methods getBinding() and getCSSName(), which return the var() reference and the custom property name of a variable.

Modes

A mode is a second, third or fourth set of values for the variables of one collection. Every collection has one mode that always exists, the base mode, and any number of additional modes. Each mode appears as a column in the Variables panel; a cell is either the inherited value or an explicit override for that variable in that mode.

Modes come in two kinds, which differ in how they are activated.

Kind Activated by Typical use

Manual mode

The designer, by applying it to an element or a page

Themes: Night, High contrast, a campaign look, a section on a different background

Breakpoint (automatic) mode

A breakpoint: the mode applies from that breakpoint down, with no action by the designer

Responsive systems: larger spacing and type on large screens, tighter spacing on mobile

The Help Center calls the second kind a responsive mode; the Designer API calls it an automatic mode. They are the same thing.

The base mode

The base mode is the default of every collection. Its reserved identifier is base, it is called "Base mode" until renamed, and a rename does not change the identifier. It cannot be deleted. Every variable has a value in the base mode, and every other mode starts as a copy of it: a new mode shows the base values, and only the cells that are edited become overrides. A variable that has no override in a mode simply falls back to the base value, so editing a base value later also changes every mode that did not override it.

Because the base mode is what applies when nothing else does, choose the most common case for it. For Fernbrook the Theme collection’s base mode is Day, since that is how the site normally looks, and Night is the additional manual mode.

Manual modes

A manual mode is created from the New mode dropdown in the Variables panel by naming it and leaving the Responsive option off. Its column starts with the base values, and the designer overrides the cells that should change. For the Night mode, Surface is aliased to Soil 800 and Text / Primary to Paper 50, as in the diagram above.

A manual mode applies where the designer applies it, and it applies to the element and everything inside it. That is the reason modes can be used for a whole page, for one section and for a single card: the mode is attached to an element, and the variables it redefines are redefined for that element’s subtree.

Breakpoint modes

A breakpoint mode is created the same way, with the Responsive option on and a breakpoint chosen in the dropdown. It then applies automatically when the viewport reaches that breakpoint. Modes follow the same inheritance rules as breakpoints: a mode set for a larger breakpoint cascades down to smaller ones until another mode takes over. Two limits are worth knowing.

  • A collection can have only one automatic mode per breakpoint, counting the base mode as the mode of the main breakpoint.

  • The values of a new breakpoint mode default to the base mode, so only the differences need editing.

For Fernbrook the Spacing collection has a mode called Wide set to the 1920 px breakpoint, in which Section padding grows from 4rem to 7rem and Gutter from 1.5rem to 3rem. No class mentions the breakpoint; the classes only use Section padding, and the mode changes the value. The breakpoints themselves and the cascade between them are explained in Responsive Design and Breakpoints.

The distinction from setting a value on a breakpoint in the Style panel is where the decision is stored. A style override on a breakpoint belongs to one class and one property. A breakpoint mode belongs to the variable, so one edit adjusts every class that uses it, and a team can read the whole responsive rule in one column.

Applying modes to elements and pages

An automatic mode needs no application. A manual mode does, and Webflow exposes the application in the Style panel of an element: the panel lists the collections that have manual modes, and a menu per collection selects which mode applies to the selected element, with the base mode as the default. The mode is stored with the class or element style that is being edited, so the same breakpoint and state targeting as the rest of the panel applies.

Target How a mode is applied

A whole page

Apply the mode to the Body element of the page. Everything on the page inherits it.

A section or a card

Apply the mode to that element’s class. Its descendants inherit it; the rest of the page does not.

Every page of the site

Apply the mode to the class used by the Body element on every page, or to a wrapper class that is the page root of a layout.

A component instance

Apply the mode to the instance’s root element; see Components, Props, Slots and Variants.

Two practical consequences deserve a name.

  • A mode on a class applies wherever the class is used. A Night mode on .section-night makes every section with that class night; putting the mode on an element without a class creates the automatic class name the panel offers. The same mechanism is why a combo class can carry the mode while the base class does not, which is the pattern that Classes, Combo Classes and Selectors recommends for variants.

  • Inheritance is what makes nesting work. Putting .section-night inside a Day page makes that section dark, and a Day card inside it can switch back by being given the base mode.

A Day/Night example

The Fernbrook "Evening in the Garden" events page is a dark page for the lantern festival. The rest of the site stays light. The steps are:

  1. In the Variables panel, create the collection Theme with the semantic variables Surface, Text / Primary and Accent, each an alias of a Brand variable, with the Day values in the base mode.

  2. Create a manual mode named Night in Theme and override the three cells with the dark aliases.

  3. Build every class from the semantic variables only: .page-wrapper has background-color: Surface, headings have color: Text / Primary, links have color: Accent.

  4. On the events page, select the Body element and choose Night in the Theme menu of the Style panel.

No class is duplicated, and the same classes render both looks. The visitor sees the Night page because the generated CSS redefines the custom properties for the element that the mode is applied to.

A mode can be driven by the visitor’s operating-system preference or by a toggle, but only with a little custom code. Webflow’s mode application is static: it fixes the mode in the published HTML and CSS. Switching a page between Day and Night at runtime means toggling the class that carries the mode, for example from a button, as the next section’s code shows after the custom property output.

The CSS Webflow generates

A variable is published as a CSS custom property. The values of the base mode go on the :root selector, the values of a manual mode go on a selector that the applied element carries, and the values of a breakpoint mode go inside the media query of the breakpoint. A class uses the variable with var(). The exact selector names that Webflow generates for modes are internal and have changed over time, so do not write CSS against them; the shape of the output is what matters.

/* Base mode of Theme (Day) and of Brand */
:root {
  --green-700: #1f3d2b;
  --paper-50: #faf8f2;
  --soil-800: #24201b;
  --surface: var(--paper-50);
  --text--primary: var(--soil-800);
  --section-padding: 4rem;
}

/* A manual mode: the same custom properties, redefined for a subtree */
.mode-night-example {
  --surface: var(--soil-800);
  --text--primary: var(--paper-50);
}

/* A breakpoint mode: the same custom properties inside a media query */
@media screen and (min-width: 1920px) {
  :root {
    --section-padding: 7rem;
  }
}

/* A class that uses the variables, written by the Style panel */
.plant-card {
  background-color: var(--surface);
  color: var(--text--primary);
  padding: var(--section-padding);
}

Four points explain how to read this output.

  • Names come from variable names. The custom property name is derived from the variable name; a folder in the name appears as a double hyphen, as in --text--primary for Text / Primary. Read the exact name with the Designer API helper getCSSName() instead of guessing, because it is the value that a hand-written snippet should use.

  • The browser does the work. Webflow publishes plain CSS, not JavaScript. The cascade decides which declaration wins, which is why a mode on a subtree changes only that subtree, and why a breakpoint mode applies like a media query.

  • Variables are available to custom code. A snippet in an embed or in the page’s custom code can use var(--surface) in its own CSS, so third-party widgets can follow the theme. Because the names derive from the variable names, renaming a variable that custom code depends on breaks the code; treat the names as an interface.

  • The legacy colour picker still writes literals. A control bound to a swatch or typed by hand publishes a literal value, and only controls connected to a variable publish var().

A visitor-controlled toggle needs the class that carries the mode. This snippet assumes the mode is applied to the class section-night; the button, the class and the storage key are all Fernbrook names:

// Toggle the class that carries the Night mode on the page wrapper.
const wrapper = document.querySelector(".page-wrapper");
const button = document.querySelector("[data-theme-toggle]");

button.addEventListener("click", () => {
  const night = wrapper.classList.toggle("section-night");
  try {
    localStorage.setItem("fernbrook-theme", night ? "night" : "day");
  } catch (e) {
    /* storage can be unavailable in private windows */
  }
});

Custom code and attributes are covered in Custom Attributes and JavaScript.

Designer API equivalent

The Designer API exposes the same objects as the Variables panel, so a Designer Extension can create a design system from code, audit a site for stray literals or keep two sites in sync. The entry point is a collection; the default collection is returned by webflow.getDefaultVariableCollection(), and further collections come from webflow.getAllVariableCollections() and webflow.createVariableCollection(name).

Designer API Panel equivalent

collection.createColorVariable(name, value, options?)

New variable of type Color

collection.createSizeVariable, createPercentageVariable, createNumberVariable, createFontFamilyVariable

New variable of the other four types

variable.set(value, { mode })

Edit a cell of a mode column

variable.set(null, { mode })

Clear an override so the cell falls back to the base value

collection.createVariableMode(name, breakpointId?)

New mode (manual without a breakpoint, automatic with one)

mode.setBreakpoint(breakpointId | null)

Promote, move or demote a mode

mode.remove()

Delete a mode; fails on the base mode with a VariableModeInvalid error

variable.getBinding()

The var() reference to use in a custom value

variable.getCSSName()

The custom property name

createColorVariable takes a name, a value and an optional options object. The value is a colour string (a colour name, a hex value or a hex value with alpha), another variable of the same type, which creates an alias, or a custom value. The method resolves to a ColorVariable.

// Fernbrook Gardens: build the Brand collection and the Theme collection.
const brand = await webflow.getDefaultVariableCollection();

const green700 = await brand.createColorVariable("Green 700", "#1f3d2b");
const paper50 = await brand.createColorVariable("Paper 50", "#faf8f2");
const soil800 = await brand.createColorVariable("Soil 800", "#24201b");

// The semantic layer is made of aliases: pass a variable instead of a string.
const surface = await brand.createColorVariable("Surface", paper50);
const textPrimary = await brand.createColorVariable("Text / Primary", soil800);

// A manual mode, then a mode-specific override for each alias.
const night = await brand.createVariableMode("Night");
await surface.set(soil800, { mode: night });
await textPrimary.set(paper50, { mode: night });

// An automatic mode tied to a breakpoint, for the spacing scale.
const wide = await brand.createVariableMode("Wide", "xxl");
const sectionPadding = await brand.createSizeVariable("Section padding", { unit: "rem", value: 4 });
await sectionPadding.set({ unit: "rem", value: 7 }, { mode: wide });

The sample keeps everything in the default collection for brevity; a real system would create the Theme collection with webflow.createVariableCollection("Theme") and put the semantic variables there. The size variable value shape and the breakpoint identifiers (medium, small, tiny for the smaller breakpoints, large, xl and xxl for the larger ones) should be read from the reference of the version of the typings that is installed, because the shapes are typed and the compiler reports a mismatch.

Binding a variable to a style uses the same style API as plain values. Passing a variable instead of a string writes var(--name):

const style = await webflow.getStyleByName("plant-card");
await style?.setProperties({ "background-color": surface });

Custom values use the function support described earlier: variable.set({ type: "custom", value: "clamp(2rem, 1.4rem + 2.4vw, 3.5rem)" }) stores a function. Inside a custom value, getBinding() returns the text to use for another variable, so a calc() that refers to Space 2 survives a rename of the variable.

An extension needs the Designer to be in the main branch, on the canvas and in design mode for these calls, and the call fails if the user lacks the canModifyVariables ability. Designer Extensions and the Designer API explains how extensions are built and installed.

Migrating from swatches

Swatches are the older mechanism and still exist. A swatch is a saved colour in the colour picker: choosing it copies the value into the control, and from then on the control holds a literal. This is what older books and tutorials teach, including the 2021 book on Webflow, in which colours are saved as swatches and reused by picking them again. Swatches are a convenience for selecting a colour, not a link; the reuse stops at the moment of selection. Three things in that description changed since: variables now exist, modes make theming a built-in feature, and the Style panel’s colour picker lists variables above the swatches.

A migration from swatches to variables takes five steps and can be done gradually, because variables and literals can coexist on a site.

  1. Inventory. List the swatches and the literal colours in use. The Style Manager lists every class and its values, and the colour picker lists swatches.

  2. Create primitives. Create a Color variable for each distinct brand colour in a Brand collection, named after what it is: Green 700.

  3. Create semantics. Create aliases named after what they are for: Surface, Text / Primary, Accent. Do this only for roles that actually exist in the design.

  4. Rebind. Select a class, find each colour control that holds a literal and connect it to the matching variable. Work from the most reused classes down, and from the base breakpoint outward, so that breakpoint overrides and states are updated as well.

  5. Retire the literals. Delete swatches that nothing uses. A literal that remains is a candidate for a new variable or for deletion.

The same steps apply to sizes: spacing and font-size literals become Size variables, and a scale of nine values is easier to maintain than hundreds of one-off pixel values. Component libraries benefit as well, since the variables travel with the library; see Building a Design System.

A migration through the Designer API can detect literals that equal a variable’s value and offer to bind them, which is the idea behind the Variables Refactor prompt of the Webflow MCP server (see MCP Server and AI Agents); review the proposed bindings before accepting them, because two different roles can share one colour today.

Variables, class custom properties and swatches compared

Three mechanisms can store a reusable value in Webflow, and choosing between them is a matter of scope and tooling.

Aspect Variable Custom property on a class Swatch

Where it is defined

Variables panel

Custom properties section of the Style panel

Colour picker

Scope

The whole site, optionally per element through a mode

The element carrying the class and its descendants

None: a copy of the colour is stored in the control

Appears in pickers

Yes, in every control of the matching type

No, it has to be typed as var(--name)

Yes, in colour controls

Modes and breakpoints

Yes

Only by writing the override on each breakpoint

No

Survives renaming and refactoring

Yes, controls hold a reference

No, text is not checked

Not applicable

Travels in a library

Yes

Only with the class

Not applicable

Published as

A custom property on :root or on a mode selector

A custom property on the class

A literal value

The rule of thumb is the one from the Style panel page: use a variable when a value is shared across classes or needs a mode; use a class custom property for a value that is local to one component; use a swatch only as a shortcut while exploring a palette.

A worked build for Fernbrook Gardens

The following order builds the whole system in the Designer and avoids rework. Each step is a few minutes of work and can be done by one designer.

  1. Brand colours. In the Variables panel, rename the Base collection to Brand and create the Color variables Green 700, Green 100, Soil 800, Paper 50 and Petal 500. Enter the values once.

  2. Theme. Create a second collection, Theme. Create Surface, Text / Primary, Text / Muted, Border and Accent, each as an alias of a Brand variable. Rename the base mode to Day.

  3. Night. In Theme, create a mode called Night without the Responsive option. Edit the cells to point to the dark aliases. Leave Accent untouched if the same green reads well on both backgrounds, so that it falls back to the Day value.

  4. Spacing. Create a Spacing collection with Size variables Space 1 to Space 8 in rem, and Section padding and Gutter as aliases of them. Create a mode Wide with the Responsive option and the largest breakpoint, and override Section padding and Gutter in it.

  5. Type. Create a Type collection with the Font variables Heading font and Body font, and function variables for the type scale.

  6. Rebind classes. Open each class of the plant card, the navigation, the hero and the footer, and connect each colour, spacing and font control to a variable. The Style panel marks controls that hold a variable, so the remaining literals are easy to find.

  7. Apply modes. Apply Night to the Body element of the lantern festival page. Preview with the Designer’s preview, check the Wide mode by switching the breakpoint bar to the largest breakpoint, and publish to the staging domain before the live domain.

At the end, rebranding Fernbrook means editing five cells in Brand, and a new dark page means choosing one mode.

Checking the result

Because a missing var() does not raise an error, verify the output explicitly.

  • Preview each mode. Switch the Designer to the page that carries the mode and read the colours in the canvas; then publish to the webflow.io staging domain and look at the live page.

  • Inspect in the browser. In the developer tools, select an element and read the computed value of the custom property; the Styles pane shows the var() chain and which rule defined the property.

  • Test at the breakpoint. Resize the browser across the breakpoint of a responsive mode and confirm the value changes at the width expected.

  • Look for stragglers. Search the published stylesheet for the hex values of the palette. A hex that appears on a class is a literal that was not rebound.

  • Check contrast in both themes. Contrast of text against Surface has to pass in Day and in Night.

Governance on larger sites

On a site edited by several people, variables are also a permission and a review question. Any member who can edit the site in the Designer can change a variable, and a change reaches every page as soon as the site is published, so a one-cell edit can alter the whole site. Three habits reduce the risk.

  • Make variable changes in a page branch or a release, where the plan and role allow it, so that they are reviewed before they go live; see Page Branching, Releases and Approvals.

  • Keep primitives and semantics in separate collections, and let only the design-system owner edit the primitives.

  • Keep a short written list of the variables that custom code or an embedded widget depends on, since renaming one breaks that code.

For several sites that share a design system, the variables are part of a shared library, which pushes updates to the sites that installed it; see Shared Libraries.

Pitfalls

  • Unclear naming. Color 1 and Blue become wrong the day the brand changes. Name primitives after the value (Green 700) and semantics after the role (Surface).

  • Using a primitive where a semantic was meant. A class bound to Paper 50 does not follow the Night mode; a class bound to Surface does. Bind classes to semantic variables.

  • Overriding too many cells. A mode that overrides every variable is a second theme to maintain. Override only what differs; the rest should fall back to the base mode.

  • Forgetting that the base mode is the default. Editing the base value changes every mode that did not override it, which is useful for shared values and surprising for a Night mode that was meant to be fixed.

  • Expecting a mode to follow the visitor automatically. Webflow applies a manual mode statically. A preference-based switch needs custom code, and a visitor toggle needs a class swap.

  • Renaming a variable used in custom code. The published custom property name derives from the variable name.

  • Contrast. A Night mode that swaps two colours can pass or fail contrast checks differently from Day. Check both; see Accessibility.

  • Changing the type. The type is fixed at creation. A colour created as the wrong type is recreated, not converted.

  • Two automatic modes on one breakpoint. Only one automatic mode per breakpoint is allowed in a collection; the base mode already uses the main breakpoint.

Corrections to older material

  • "Colours are saved as swatches." Swatches still exist, but they store no link. Variables are the way to keep a palette editable in one place.

  • "Responsive design is a matter of overriding properties on each breakpoint." It still can be, but breakpoint modes move the decision from each class to the variable.

  • "Dark mode needs duplicated classes." A manual mode redefines the variables and the classes stay as they are.

  • "CSS functions need custom code." Since 2025, calc(), clamp(), min(), max() and color-mix() can be used in variable values.

The full list is on Where Older Books and Tutorials Are Outdated; the Style panel controls that accept variables are described in Style Panel and the Box Model.

Where to go next