Classes, Combo Classes and Selectors
|
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 written against the Webflow Designer as it was on 2026-10-28. Webflow is a hosted service without version numbers, so the Style selectors panel can change its labels or icons between two visits; the dates in the text say when something appeared, and https://webflow.com/updates and the developer changelog are where changes are announced. Classes and selectors are available on every plan, including the free Starter Site plan inside a Starter Workspace, so every example on this page can be reproduced without paying. The developer example uses the Designer API typings package @webflow/designer-extension-typings 2.2.2 and runs inside a Designer Extension on a site in a Developer workspace.
Everything visual in Webflow ends up as CSS, and the thing that decides which elements a CSS rule applies to is the selector. In the Designer the selector is chosen in one place, the Style selectors section at the top of the Style panel. A designer who understands what that section writes can predict the published CSS, avoid the "I changed one button and twelve changed" accident, and keep a large site maintainable. This page explains classes, combo classes, global and utility classes, tag selectors, states and nested selectors, shows the CSS that each produces, discusses the specificity consequences, and ends with the housekeeping tools (renaming, cleaning unused classes, finding what changed recently).
The running example is the Fernbrook Gardens site, a fictitious botanical garden. The job on this page is to build the visitor-facing "Plan your visit" button: a primary button used across the site, a secondary variant used in the hero, a small variant used in the footer, and a hover and keyboard-focus treatment for all of them.
Why selectors matter in a visual tool
In a hand-written stylesheet the author chooses a selector for every rule. In the Designer the author chooses it implicitly, because every edit in the Style panel is written to the selector that is currently active in the Style selectors section. Two designers can make the identical visual change and produce very different stylesheets, depending on whether the active selector was a class, a combo class, a tag selector or a state. That is why the active selector is the first thing to read before touching a property: it is the answer to "where is this style going?".
Three consequences follow from this.
-
A style applied to a class changes every element that has that class, on every page, at the breakpoint that is active. This is the feature that makes a design system possible, and it is also the source of most accidents.
-
A style applied to nothing (an element with no class) is written to an automatically named class, because Webflow does not use inline styles for designs. The Style panel then shows the element as having a class even though the designer never named it. See the section on unnamed styles below.
-
The cascade of the site is made of the selectors the designer created. There is no hidden layer of "Webflow styles" that wins over them, apart from the small base stylesheet described at the end of this page, so the usual CSS rules about specificity and source order explain what happens.
For the CSS concepts themselves (the cascade, specificity arithmetic, pseudo-classes, combinators and native CSS nesting) this page links the HTML and CSS section of this site instead of re-teaching them: see Selectors and Specificity.
The Style selectors section
The Style selectors section sits at the top of the Style panel in the right bar. It is the control that answers three questions about whatever element is selected on the canvas.
| Control | What it decides |
|---|---|
The class field (selector field) |
Which class or classes the element has. Typing a name and pressing Enter adds that class, creating it when it does not exist yet. The same field is used to search existing classes. Clicking the small cross on a class pill removes it from this element only. |
The state dropdown |
Whether the edits apply to the normal state of the selector or to a state such as hover or focus. |
The "used on" counter |
How many elements on the site currently carry the active class. A counter higher than one is the warning that an edit will propagate. |
The selector preview |
A text rendering of the selector that edits are being written to, for example |
The Style selectors panel (opened from the section) |
A list of all selectors on the site, with search, rename, delete and cleanup tools. It is covered in the housekeeping section. |
The colour of the class pill and of the property labels in the Style panel also carries information. A property label shown in blue is set on the active selector, in amber it is inherited from a parent selector or from a larger breakpoint, and in grey it is not set. Combined with the preview, this lets a designer trace where a value comes from. The Style panel itself, every control in it and the units used are described in The Style Panel and the Box Model, and the panel layout in Designer Tour.
Classes
A class is a named bundle of style rules. Creating one is as simple as selecting an element, typing a name in the selector field and pressing Enter. From that moment the class exists on the whole site and can be added to any other element by typing or choosing its name. Webflow writes it into the generated stylesheet as a normal class selector, and into the HTML as a value of the class attribute.
For the Fernbrook button the first step creates a class called button:
<a href="/visit" class="button">Plan your visit</a>
.button {
display: inline-block;
padding: 12px 24px;
border-radius: 4px;
background-color: var(--brand--leaf);
color: #fff;
text-decoration: none;
}
Source: Webflow Help Center: Classes
An element can carry several classes at the same time, in the same way as in HTML: class="button is-secondary". The Designer shows them as a row of pills in the order in which they were added, and that order matters, as the next section explains.
A few rules of the class system are worth stating explicitly, because older tutorials and the book Webflow by Example are vague about them.
-
A class belongs to the site, not to the element. Removing a class from an element does not delete it from the site; it stays in the list of selectors until it is deleted (see "Cleaning up unused classes").
-
A duplicated class is a new, unrelated class. Duplicating an element that has a class keeps the class (both elements share it), but duplicating the class from the selector menu produces an independent copy whose styles no longer follow the original. Use duplication when a variant should diverge permanently and a combo class when it should stay tied to the base.
-
A class can be applied to any element. Unlike a style attached to a tag, a class does not care about the element’s type, which is what makes a
section-paddingclass useful on a Section, a Div Block or a Container alike.
Classes versus element (tag) styles
The alternative to a class is a tag selector, which styles every element of a given HTML tag. In the Designer it appears as the "All" options in the selector dropdown, for example "All H1 Headings", "All Paragraphs", "All Links" or "All Lists". Choosing one writes a rule such as h1 { ... } instead of .heading-hero { ... }.
| Class | Tag selector | |
|---|---|---|
Applies to |
Only the elements that carry the class |
Every element of that tag in the whole site, including those inside Rich Text and CMS content |
Specificity |
One class, |
One element, |
Typical use |
Components, layout helpers, variants |
Sensible defaults for headings, paragraphs, links and lists, and the base style of Rich Text |
Risk |
An edit propagates to all elements with the class |
An edit propagates to every element of that tag, including ones the designer never looked at |
The recommended practice of the Webflow Way is to set the defaults of typography on tag selectors (so that a new heading dropped anywhere on the site already looks right) and to use classes for everything that is a deliberate design decision. Because a tag selector is weaker than any class, a class on a heading always wins over the tag default, and removing the class returns the element to the default. The Rich Text element is the main reason to keep tag selectors well-defined: the editor’s headings, paragraphs and lists are generated tags without classes, and only tag selectors (or nested selectors on the Rich Text class) can style them. Typography itself is covered in Typography and Fonts.
Source: The Webflow Way
Unnamed styles
When an element has no class and the designer changes a property in the Style panel, Webflow does not write an inline style. It creates a class automatically and shows it on the element. Such classes are an easily missed source of untidiness, because they are named after the element (for example div-block-12) and say nothing about their purpose. The preferred workflow is to name the class before editing anything, or to rename the automatic one immediately, so that the stylesheet stays readable. Elements that never receive a style do not get a class.
Combo classes
A combo class is a class that is added on top of a base class and that only has effect when both are present. It is created by selecting an element that already has a base class and typing a new name in the selector field next to the existing pill; the new class is then added as a second pill, drawn in a different colour. The combo can also be reached with the keyboard shortcut for the selector field (Command and Enter on macOS, Control and Enter on Windows) or from the "Add class" entry of the context menu on the element.
For the Fernbrook hero, a secondary button is the base button with a combo is-secondary:
<a href="/membership" class="button is-secondary">Become a member</a>
.button {
display: inline-block;
padding: 12px 24px;
background-color: var(--brand--leaf);
color: #fff;
}
.button.is-secondary {
background-color: transparent;
color: var(--brand--leaf);
border: 2px solid var(--brand--leaf);
}
Source: Webflow Help Center: Classes
The combo class is written as a compound selector: two class selectors with no space between them, which matches only an element that has both classes. That has four properties that are the whole story of combo classes.
-
The change is scoped to the element that has both. Styling
.button.is-secondaryleaves every plain.buttonunchanged, which is exactly the point. -
The order of the pills is fixed. The base class is first and the combo follows; the Designer does not let a combo be moved ahead of its base or reordered among other combos, and the generated selector follows the same order. In CSS a compound selector’s order does not change what it matches, so the restriction exists for the Designer’s own bookkeeping: each combo is stored as "this class on top of that class".
-
A combo is specific to its base. The combo
is-secondarycreated onbuttonis a different style object from anis-secondarycreated oncard, even though the name is the same. -
Specificity is higher. Two classes give
0-2-0, so the combo wins over the base regardless of where the two rules appear in the stylesheet.
Webflow’s own guidance is to keep stacks short: at most three or four classes on an element (the base plus two or three combos). More than that makes the result impossible to predict by reading the pills, makes later edits error-prone, and signals that the design should be restructured, for example by promoting the stack to a component with variants or by using a different base class.
A class stack compiled to selectors
The following diagram shows how a stack of pills on one element is turned into the rules written to the stylesheet. Each class in the stack that has styles produces its own rule, and every combo produces a compound selector that includes all the classes to its left.
The diagram is a schematic of the generated selectors and does not reproduce a Designer screenshot. Note that the third rule only applies when all three classes are present; an element with button and is-small but without is-secondary would not receive it, because a combo is stacked on the classes that precede it.
Combo classes and the breakpoint cascade
A combo class is edited per breakpoint just like any other selector. The Designer writes the desktop (base) values outside any media query and the other breakpoints inside media queries, so the compiled CSS for a combo can look like this:
.button.is-small { padding: 8px 16px; font-size: 14px; }
@media screen and (max-width: 767px) {
.button.is-small { padding: 6px 12px; }
}
Because the selector is the same inside the media query, the cascade resolves only through source order and breakpoint order, not through a rise in specificity. The breakpoint bar and the order in which breakpoints cascade are described in Responsive Design and Breakpoints.
When not to use a combo class
Combos are the right tool for a small, local deviation from a base. They are the wrong tool when the deviation is large or reused in unrelated places.
-
If a combo repeats most of the base’s properties, the base is probably the wrong abstraction. Create a separate class.
-
If the same combo name is used on many different bases (
is-large,is-dark), the designer is building utilities. Make them independent utility classes instead (next section). -
If a design needs options such as size, colour and icon on the same element, a component with properties and variants expresses that more reliably than a stack of combos. See Components, Props, Slots and Variants.
-
If a combo is created accidentally, remove it from the element and delete it with the cleanup tool. It does not affect the base class.
Global and utility classes
Two ideas are commonly mixed with combos and are worth separating, because they use the same machinery in the Designer but have different intent.
Global classes are ordinary classes that are not tied to one component and are used throughout the site: a container that sets a maximum width and centres its content, a section with standard vertical padding, a heading-style-h1. They are defined once and applied wherever needed.
Utility classes are small single-purpose classes that do one thing and are meant to be combined on an element: text-align-center, margin-top-small, hide-mobile, overflow-hidden. They are applied as additional independent classes, not as combos on a specific base. Because they are independent they work on any element, but they also compete with the base class on specificity: a utility with a single class selector has the same 0-1-0 as the element’s own class, so the winner is decided by source order in the stylesheet and not by the designer’s intent. That ambiguity is why naming systems and component practices advise keeping utilities for properties the base class does not set. Naming styles for global and utility classes, and a neutral comparison of the systems used by the community such as Client-First, are in Class Naming Systems.
| Combo class | Utility class | |
|---|---|---|
Stacked on |
A specific base class |
Any element |
Written as |
|
|
Specificity |
|
|
Removal effect |
Returns the element to the base look |
Removes the single property |
Best for |
Variants of one component |
Spacing, alignment and visibility helpers |
A common approach in large sites is to give the base class the identity and defaults of a component, give it combos for its few real variants, and keep utilities for layout nudges. The Fernbrook site uses button with combos is-secondary and is-small, a global container, and utilities margin-top-small and text-align-center.
States
A state is a condition under which a selector’s styles apply. Selecting a state in the dropdown next to the class field makes edits write to the selector followed by a pseudo-class. The label of the state is shown on the canvas and the element is previewed in that state while editing, so the designer can see the hover look without hovering.
| State in the Designer | CSS pseudo-class | When it applies |
|---|---|---|
Hover |
|
The pointer is over the element |
Pressed |
|
The element is being pressed (mouse down or touch) |
Focused |
|
The element has keyboard or programmatic focus |
Focus visible |
|
The element has focus and the browser decides a focus ring is useful, typically keyboard focus |
Focus within |
|
The element or any descendant has focus |
Visited |
|
A link whose target has been visited |
Placeholder |
|
The placeholder text of a form field |
Current |
|
A navigation link whose target is the page being viewed |
Further states appear for specific elements, for example form fields (such as disabled, checked, required or optional) and list or table items (such as first, last, odd and even), and the exact list shown depends on the selected element. The dropdown only offers states that make sense for the element, so a missing state usually means the element type does not support it.
For the Fernbrook button the hover and keyboard focus styles are written like this:
.button:hover {
background-color: var(--brand--bloom);
}
.button:focus-visible {
outline: 3px solid var(--brand--leaf);
outline-offset: 2px;
}
Three practical points about states.
-
Provide a focus style. A keyboard user depends on
:focus-visible(or:focus) to see where they are. Removing the outline without replacing it is an accessibility failure; see Accessibility. -
Touch devices have no hover. A hover-only reveal is invisible on a phone. The hover state should add polish, not carry information that is otherwise absent.
-
State edits are per selector and per breakpoint. A hover style set on
.buttonapplies to all buttons, and one set on.button.is-secondaryapplies only to the secondary ones, producing.button.is-secondary:hoverwith higher specificity than.button:hover.
The .w--current state deserves a note: Webflow adds the class w--current to a link that points to the page being viewed (and to a Navbar link of a parent section in some cases), and the Current state styles that class. It is the usual way to highlight the active item of a menu. It is generated by webflow.js and by the published markup, which is why it is not visible while designing links to other pages.
Nested selectors
A nested selector styles an element because of its relation to another, and it is the Designer’s way of writing a descendant or similar combinator rule without writing CSS. It is useful when the child cannot reasonably carry its own class, or when a rule is truly contextual. The common cases are:
-
the heading inside a card that is hovered, which makes the heading change colour when the card is hovered;
-
the headings, paragraphs and links inside a Rich Text element, which have no classes of their own;
-
a link inside a navigation bar, to style only the links in that context.
To build one, the designer selects the child, chooses the relation in the selector options (for example "Nested selector" or the equivalent entry of the selector menu for the parent class), and picks the ancestor class; the selector preview then shows a descendant rule. The child’s own classes stay as they are and the rule is added on top.
.rich-text h2 {
margin-top: 2rem;
color: var(--brand--leaf);
}
.card:hover .card-title {
color: var(--brand--bloom);
}
Nested selectors raise specificity: .card:hover .card-title has two classes and a pseudo-class (0-3-0), which beats a simple .card-title. They are also harder to find later, because a rule lives under another class and not on the element. Use them for genuine context, keep the chain short, and prefer a class on the child when a style would otherwise be repeated in many places. The CSS combinators behind them are explained in Selectors and Specificity.
The selector to generated CSS table
The table summarises what each choice in the Style selectors section writes. The class names are those of the Fernbrook example.
| Selection in the Designer | Generated selector | Specificity |
|---|---|---|
Class |
|
|
Class |
|
|
Class |
|
|
Class |
|
|
Combo |
|
|
All H1 Headings (tag selector) |
|
|
Tag selector |
|
|
Class |
|
|
Nested selector, |
|
|
Nested selector, hovered |
|
|
Specificity is written as the triple of ID, class and type counts used by the CSS specification; a pseudo-class counts as a class and a pseudo-element as a type.
Specificity consequences
Because the stylesheet is generated from the selectors the designer picks, the choice of selector is a choice of specificity. The consequences are practical.
-
Combos beat bases without regard to order. A secondary button never reverts to the primary look because of where its rule appears.
-
Utilities tie with bases. A single-class utility and the element’s single-class base have equal specificity, so the later rule in the stylesheet wins, and the designer does not control that order. If an element needs to be overridden reliably, a combo is more predictable than a utility.
-
States add a class' worth of specificity.
.button:hoveroutranks.button, which is what makes hover work, but also means a hover rule on the base can outrank a non-hover combo rule. In the Fernbrook example the secondary button’s background is set on.button.is-secondary(0-2-0) while the hover background is set on.button:hover(0-2-0); they tie, and the later rule wins. When both are needed, set the hover on the combo with the state, which gives.button.is-secondary:hover(0-3-0). -
Nested selectors can beat everything nearby. A rule such as
.card:hover .card-titlereaches0-3-0; to override it, a designer has to reach at least the same specificity, which is how stylesheets grow into specificity wars. Keep nested chains short. -
Tag selectors never win against a class. That is the property that makes them good defaults.
-
There is no
!importantin the Designer’s selector UI. Overriding by force is not part of the visual workflow; custom CSS in an embed can do it, but it is a code-level decision (see Custom Code in the Head, Footer and Embeds).
When the result on the canvas is not what the pills suggest, three checks resolve most cases: read the selector preview, look at the label colours of the property in question (blue means set here, amber means inherited), and switch the breakpoint to see whether the value comes from a larger one. The cascade between breakpoints is described in Responsive Design and Breakpoints.
Renaming classes
A class can be renamed from the Style selectors panel: open the list of selectors, find the class (the panel has a search field), and use the rename action, then confirm. The rename changes the class in all places the Designer manages: every element that uses it, all of its states and breakpoint values, and every combo stacked on it.
Two things are not updated automatically, and they cause most rename accidents.
-
Custom code. A script, a stylesheet in an embed or a custom attribute that mentions the old name keeps pointing at it. Search the site’s custom code before renaming a class used as a hook.
-
Names stored as text. Class names that appear in CMS fields or in component property values as strings (for example a class name entered in a text property) are not recognised as references.
The Designer prevents duplicate names for the same kind of selector, so renaming to a name that already exists is refused. Merging two classes is not a built-in operation: the panel can delete a class but not fold one into another, and community apps exist for that purpose. Since renaming a base class carries its combos with it, a system of names that is thought out up front (see Class Naming Systems) saves the most work.
Cleaning up unused classes
Removing a class from an element does not delete the class from the site, so unused classes accumulate during design, especially the automatic names such as div-block-7. The Style selectors panel shows which classes are used and offers a cleanup action that removes the classes no element uses, after a confirmation. It is a good habit to run it before publishing and before handing a site over.
Before using it, note what it cannot see.
-
A class referenced only in custom code, in a custom attribute value or in a text field will look unused and may be removed.
-
The cleanup removes the class and all of its states, breakpoint values and combos; it cannot be undone except through the Designer’s history or a backup (see Backups and Recovery).
A conservative routine for a team is to sort the list, review the candidates, publish to staging, and only then run the cleanup.
Finding recently modified classes
On a site with hundreds of classes, "what did someone just change?" matters. The Style selectors panel lets the list be filtered or sorted so that recently modified classes appear first, and the selector’s "used on" count shows how many elements a change affected. Combined with the activity log and comments described in Collaboration, Comments and the Activity Log, this is how a reviewer finds the class behind an unexpected visual change after a colleague’s session. A change to a widely used class is the usual explanation for a regression on a page that nobody edited.
The base stylesheet and the w- classes
The published page includes normalize.css, webflow.css and the site’s own stylesheet. webflow.css defines the w- prefixed classes that give Webflow’s built-in elements their behaviour: w-container, w-button, w-nav, w-form and so on. Webflow adds them next to the designer’s class, so a Container element ends up as class="w-container container". They have low specificity and carry layout essentials only, so the designer’s classes override them as intended. The generated markup and the stylesheets are described in HTML and CSS in Webflow.
Classes through the Designer API
A Designer Extension can read and write styles, which is how tools that audit or apply class systems work. The API models a class as a Style, and a combo class is created by passing a parent style when creating one, which shipped on 2025-05-08.
// Create a base class and a combo class on top of it, then apply both.
const base = await webflow.createStyle("button");
const combo = await webflow.createStyle("is-secondary", { parent: base });
await base.setProperties({ "background-color": "#2f6f4e", color: "#ffffff" });
await combo.setProperties({ "background-color": "transparent", color: "#2f6f4e" });
const element = await webflow.getSelectedElement();
if (element && element.styles) {
await element.setStyles([base, combo]);
}
An extension needs the appropriate Designer API permissions and is subject to the usual limits of Apps; see Designer Extensions and the Designer API.
Fernbrook Gardens: the finished button system
The final stylesheet for the Plan your visit button, as written by the Designer, is below. Reading it back confirms the intent: one base, two combos and two interaction states, plus a smaller size at the tablet breakpoint.
.button { display: inline-block; padding: 12px 24px; background-color: var(--brand--leaf); color: #fff; }
.button:hover { background-color: var(--brand--bloom); }
.button:focus-visible { outline: 3px solid var(--brand--leaf); outline-offset: 2px; }
.button.is-secondary { background-color: transparent; color: var(--brand--leaf); border: 2px solid var(--brand--leaf); }
.button.is-secondary:hover { background-color: var(--brand--leaf); color: #fff; }
.button.is-small { padding: 8px 16px; font-size: 14px; }
@media screen and (max-width: 991px) {
.button { padding: 10px 20px; }
}
The footer’s small button is button is-small; the hero’s secondary button is button is-secondary. A change to the base’s colour in the Designer propagates to all of them, which is the benefit of the class system.
Common mistakes and pitfalls
-
Editing with the wrong selector active. The most frequent accident is editing
.buttonwhen a combo was meant, or the reverse. Read the selector preview before every edit. -
Stacking too many combos. More than three or four pills is a sign that the design needs a component with variants or a restructured base.
-
Styling tag selectors for one case. A change to "All Paragraphs" made to fix one page changes every page and every Rich Text.
-
Relying on utility order. Utilities tie with bases; do not expect them to override reliably.
-
Using automatic class names.
div-block-12communicates nothing and breaks any naming system. -
Renaming a hook class without checking custom code. Scripts and attributes keep the old name.
-
Cleaning up before checking references. A class used only in code looks unused.
-
Removing focus outlines. If a focus style is removed, supply a visible replacement.
-
Overusing nested selectors. They raise specificity and hide rules in unexpected places.
Corrections to older tutorials
Ali Rushdan Tariq’s Webflow by Example (Packt, 2021) teaches classes and combo classes, with the Style Manager as the place to clean up and with a limited list of states, and it describes the pre-2023 Designer. Its explanation of what a class is, and of the base-plus-combo idea, still holds. What differs now is the surface: the class field and the Style selectors panel replaced the earlier layout, the focus-visible and focus-within states exist alongside the older focus state, combo classes can be created through the Designer API since 2025-05-08, and "project" is now called "site". The book’s advice to name classes in Title Case without dashes is a preference of that period; current guidance favours lowercase names with hyphens, which are easier to type and to match in code, as discussed in Class Naming Systems.