Style Webflow button hover, focus, active, and pressed states by selecting the button element, then using the States dropdown at the top of the Style Panel to switch between states. Add smooth transitions by selecting the None state and adding a Transition in Style Panel > Effects > Transitions. Each state is fully independent — you can change background, border, shadow, and scale per state without code.
Webflow Button States: Hover, Focus, Active, Pressed, and Transitions
A well-designed button isn't just one visual — it's a system of states (default, hover, focus, active, disabled) that communicate affordance and feedback to the user. Webflow's Style Panel gives you a States dropdown at the top of the Selector section so you can style each state independently. This tutorial is specifically about buttons — their unique states, accessibility requirements (focus-visible for keyboard users), and transition techniques — which is distinct from general hover effects on images or cards. You'll build a complete, accessible button component with all states configured.
Prerequisites
- A Webflow project with a Button element on the canvas
- Understanding of how Webflow classes work (Style Panel > Selector field)
- Basic familiarity with the Style Panel (S)
Step-by-step guide
Create a button with a named class
Create a button with a named class
Add a Button element from the Add Elements panel (A) or use an existing button on your canvas. Select the button. In the Style Panel (S), check the Selector field at the top — it likely shows a generic class or the default button class. Click the Selector field and type a descriptive class name: 'btn-primary'. Press Enter to apply it. Having a dedicated class name ensures that when you style states (hover, focus, active), you're styling this specific button type rather than all buttons globally. Set the default state styles: Background Color (your primary brand color), Padding (12px top/bottom, 24px left/right), Border Radius (6px), Font Color (white), Font Weight (600).
Expected result: A styled button with class 'btn-primary' sits on the canvas with your brand colors and correct padding.
Style the hover state
Style the hover state
With the button selected and 'btn-primary' in the Selector field, find the States dropdown directly below the Selector field. It currently shows 'None' (the default state). Click it and select 'Hover'. The canvas preview may shift to show a hover-state indicator. Now apply your hover styles: change the Background Color to a slightly darker or lighter version of your primary color (e.g., if primary is #2563EB, set hover to #1D4ED8). Alternatively, add a Box Shadow in Style Panel > Effects > Box Shadows for a lift effect: Y: 4, Blur: 12, Spread: 0, Color: rgba(37,99,235,0.4). You can also add a subtle Scale transform: Style Panel > Effects > 2D & 3D Transforms > '+' > Scale > X: 1.02, Y: 1.02.
Expected result: When you hover over the button in Preview mode (top-right preview button), the button visually changes to its hover appearance.
Add a transition on the None state
Add a transition on the None state
The hover state change is currently instant. To make it smooth, you must add a Transition on the NONE (default) state — not the Hover state. Switch the States dropdown back to 'None'. Scroll to Style Panel > Effects > Transitions. Click '+' to add a transition. Set Property to 'All' (or specify individual properties like 'background-color' and 'box-shadow' for more controlled performance). Set Duration to '200ms'. Set Easing to 'Ease Out'. The transition applies in both directions — as you enter hover AND as you leave hover — because it's defined on the element's base state.
Expected result: Hovering over the button now shows a smooth 200ms animated transition into the hover state. Removing hover also transitions smoothly back to default.
Style the focused state for keyboard accessibility
Style the focused state for keyboard accessibility
The focused state appears when a user tabs to the button using a keyboard — critical for accessibility. Switch the States dropdown to 'Focused'. In Webflow, 'Focused' corresponds to the CSS :focus selector. Style it differently from hover to indicate keyboard focus clearly: remove or replace the browser default blue outline (which looks inconsistent across browsers) with your own. Add a custom Box Shadow in Effects > Box Shadows: X: 0, Y: 0, Blur: 0, Spread: 3px, Color: your primary brand color at full opacity. This creates a consistent branded focus ring. Also consider adding Outline: 2px solid [brand color] via Custom Properties if box-shadow isn't visible enough.
Expected result: Tabbing to the button in Preview mode shows a visible, branded focus ring around the button instead of (or in addition to) the browser default blue outline.
Style the pressed (active) state
Style the pressed (active) state
The pressed/active state shows while the user is clicking — the moment between mouse-down and mouse-up. Switch the States dropdown to 'Pressed'. Apply a 'depressed' visual: slightly darker background (one shade darker than hover), reduced scale (Effects > Transforms > Scale X: 0.98, Y: 0.98), and reduced box shadow (or none). This creates the physical 'press' feedback users expect. The visual difference should be: Default → Hover (lighter/lifted) → Pressed (darker/compressed). The press state typically lasts only 100-200ms during a click.
Expected result: Clicking and holding the button in Preview shows a brief 'depressed' visual before the click action fires. The button looks physically pressed.
Create a disabled state using a combo class
Create a disabled state using a combo class
Webflow doesn't have a native 'disabled' state for visual styling in the Style Panel (disabled is an HTML attribute, not a CSS selector in Webflow's UI). Create a combo class instead. Select the button. In the Selector field, after 'btn-primary', click '+' to add a combo class and name it 'is-disabled'. In the States: None, apply: Effects > Opacity 40%, Events > Pointer Events: None (prevents clicking). This visually communicates unavailability. Apply this combo class to buttons that should appear disabled. For buttons connected to form states, add a Custom Attribute in Element Settings (D): attribute 'disabled', value 'true' for the actual HTML disabled behavior.
Expected result: Buttons with the 'is-disabled' combo class appear faded (40% opacity) and do not respond to mouse clicks.
Build a loading state with an animated icon
Build a loading state with an animated icon
A loading state shows users their click registered while an async action processes. Create a Div Block inside the button (nest it using the Navigator). Inside this div, place both a Text Block ('Submit') and an SVG spinner element. Give the Div Block display: Flex, Align: Center, Gap: 8px. Initially, hide the spinner: select the spinner element, click the eye icon in the Navigator to set it hidden by default. In the Interactions panel (H), create a Mouse Click trigger on the button. First Click: Show spinner (Display: Flex), change button text opacity to 0.6. Optionally, add a CSS rotation animation to the spinner via a Page Head Code embed: .spinner { animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } }
1/* Inject in Page Settings > Head Code for spinner animation */2.btn-spinner {3 width: 16px;4 height: 16px;5 animation: btn-spin 0.8s linear infinite;6}7@keyframes btn-spin {8 to { transform: rotate(360deg); }9}Expected result: Clicking the button triggers a loading state showing an animated spinner alongside or instead of the button label text.
Complete working example
1/* Custom focus ring for all buttons — inject in Project Settings > Head Code2 This overrides browser defaults with a consistent branded focus ring.3 Requires paid Webflow plan (Basic and above). */45.btn-primary:focus-visible {6 outline: 2px solid #2563EB;7 outline-offset: 3px;8 box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.25);9}1011/* Suppress :focus (less specific) in favor of :focus-visible12 This hides the focus ring on mouse click but shows it on keyboard navigation */13.btn-primary:focus:not(:focus-visible) {14 outline: none;15 box-shadow: none;16}1718/* Spinner animation if using a loading state button */19.btn-spinner {20 width: 16px;21 height: 16px;22 border: 2px solid rgba(255,255,255,0.4);23 border-top-color: #ffffff;24 border-radius: 50%;25 animation: btn-spin 0.7s linear infinite;26 display: inline-block;27}2829@keyframes btn-spin {30 to { transform: rotate(360deg); }31}Common mistakes
Why it's a problem: The hover animation is jerky — it transitions in smoothly but snaps back instantly
How to avoid: Your transition is on the Hover state instead of the None state. The transition needs to be on the None/default state to animate in BOTH directions. Select the button, switch States to 'None', and add the Transition there under Style Panel > Effects > Transitions. Remove any transition you may have added to the Hover state.
Why it's a problem: The focus state looks identical to the default state — keyboard users can't see which button is active
How to avoid: You may have styled the Focused state to match the None state, or left it unstyled. Select the button, switch States dropdown to 'Focused', and add a visible indicator: Style Panel > Effects > Box Shadows > '+' > set Spread to 3–4px and Color to your brand primary. This creates a visible outline-style ring around the button.
Why it's a problem: Button states apply to all buttons on the site, not just this button type
How to avoid: Your styles are applied to the generic 'Button' tag selector or a class used by multiple button types. Check the Selector field — if it shows 'All Buttons button' (no custom class), you're styling all buttons. Create a specific class name (e.g., 'btn-primary') and apply it only to this button type. Then style the states under that specific class.
Why it's a problem: The Scale transform on hover makes the button shift surrounding elements
How to avoid: Scale transforms in CSS don't affect layout flow — neighboring elements won't move. However, if you're seeing layout shift, you may have accidentally used Width/Height changes instead of Scale. Check Style Panel > Effects > 2D & 3D Transforms. If you see a Move or Size change instead of Scale, remove it and replace with Scale (X: 1.02, Y: 1.02) for a layout-safe zoom effect.
Best practices
- Always define all four states: None, Hover, Focused, and Pressed. Leaving any state unstyled means users see inconsistent or jarring browser defaults.
- Put transitions on the None (default) state, not the Hover state. This ensures both hover-in and hover-out animate smoothly.
- Never remove focus indicators entirely. Use Style Panel > Effects > Box Shadows to create a branded focus ring that looks better than the browser default while remaining visible for keyboard users.
- Keep hover state changes subtle: a 10-15% darker/lighter background, a small shadow, or a 1-2% scale increase. Dramatic changes (flashing colors, large transforms) feel erratic and unprofessional.
- Test button states using the keyboard: Tab to reach the button (focus state), Enter to activate it (pressed state), and mouse hover over it. All three should look clearly distinct.
- Use combo classes ('btn-primary is-loading', 'btn-primary is-disabled') to layer state appearances without duplicating the entire button class.
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I'm styling buttons in Webflow with full state management — hover, focus, active/pressed, and disabled. I know I need to use the States dropdown in the Style Panel, but I'm not sure where to add the CSS transition so it animates both entering and leaving the hover state. Also, how do I create a proper focus state that looks good but still passes WCAG accessibility requirements? Walk me through the exact Style Panel steps.
Style all .btn-primary buttons in this Webflow project with a complete state system: default (#2563EB background, white text), hover (#1D4ED8 background, slight box shadow), focused (2px outline ring in brand color), and pressed (scale 0.98, darker background). Add a 200ms ease-out transition on the default state.
Frequently asked questions
What is the difference between Hover, Focused, and Pressed states in Webflow?
Hover corresponds to CSS :hover — activated when a mouse cursor enters the button area. Focused corresponds to CSS :focus — activated when the button receives keyboard focus (via Tab key). Pressed corresponds to CSS :active — activated during the moment a user is clicking (mouse button held down). Each requires a distinct visual style to give correct feedback for mouse, keyboard, and touch interactions respectively.
Why does my button's hover state appear to work in the Designer but not in Preview or published site?
The Designer canvas doesn't execute CSS hover states by default — you need to click the Preview button (top-right in the Designer) to see hover, focus, and active states in action. The published site will show all states correctly. If states work in Preview but not on the published site, check that you published after making the state changes (Publish button, top-right).
Can I style a button's disabled state in Webflow using native CSS :disabled?
The :disabled CSS pseudo-class is not directly available in Webflow's States dropdown. The recommended approach is to use a combo class (e.g., 'btn-primary is-disabled') with Opacity 40% and Pointer Events: None in the Style Panel > Effects > Events. For actual HTML disabled behavior on form submit buttons, add a Custom Attribute: Element Settings (D) > Custom Attributes > 'disabled' attribute.
How do I make a button 'fill' animation on hover — where a color sweeps across from left to right?
The fill sweep effect requires a pseudo-element (::before or ::after), which isn't natively accessible in Webflow's Designer. Inject this CSS in Page Settings > Head Code on a paid plan: .btn-primary { position: relative; overflow: hidden; } .btn-primary::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: rgba(0,0,0,0.15); transition: left 0.3s ease; } .btn-primary:hover::before { left: 0; } This creates a dark overlay sweep from left to right on hover.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation