anonymous.

Button Design Covering States, Sizes, Hierarchy, and WCAG 2.2 Touch Targets

Button design covering every state from default to loading, with WCAG 2.2 touch-target minimums and the functional hierarchy of primary versus secondary actions.

Button Design States, Sizes, Hierarchy, and Touch Targets: The Specification, Not The Opinion

A common wrong assumption about button design is that it is a visual discipline: pick a color, round the corners, call it done. In practice, button design states sizes hierarchy touch targets are a set of measurable constraints defined by WCAG 2.2, platform guidelines, and component behavior specifications. A button that looks good but fails contrast minimums, omits a loading state, or measures 22 px on a touchscreen is not a design decision. It is a failure that excludes users and breaks legal requirements under the EU Accessibility Act and Section 508. This specification defines the six required button states, the size specifications for each platform, and the hierarchy rules that determine which button gets the user's action.

The Six Required Button States: Default, Hover, Focus, Active, Disabled, And Loading

Every interactive button must visually communicate its current state to the user. The standard is six states. Omitting one is a defect.

Default And Hover

The resting state uses a solid fill (primary), an outline (secondary), or text only (tertiary). The label is legible at the minimum contrast ratio of 4.5:1 for normal text under WCAG 2.2 AA, or 3:1 if the text is large (18 pt regular or 14 pt bold). The fill itself must have a 3:1 contrast ratio against the background behind it per WCAG 2.2 AA for UI components. The cursor is pointer.

Hover is visible only on pointer-driven devices. Material Design specifies an overlay of 8% white or black on the fill. The transition duration is 200 ms with a cubic-bezier(0.4, 0, 0.2, 1) easing. On a primary button, the brand color shifts slightly lighter or darker. On a secondary outline button, the border may thicken or the fill may gain a faint tint. The cursor remains pointer.

Focus And Active

Focus is the most commonly omitted state and the one that most frequently causes WCAG 2.2 failure. A focus indicator must be visible when the button receives keyboard focus. WCAG 2.2 requires the indicator to be at least 2 CSS pixels thick and have a contrast ratio of 3:1 against the adjacent colors. The area of the indicator must equal at least the perimeter of a 2 px thick line on the shortest side of the component. Use the CSS :focus-visible pseudo-class to show the indicator only when the user navigates by keyboard, not by mouse click.

Active (Pressed) gives momentary feedback during the click or tap. Material Design specifies an overlay of 12% white or black on the fill. The transition duration is 100 ms, half the hover duration. The button may also drop to a shadow elevation of 0 dp (flat) in Material Design 3, compared to 1 dp on hover. On a mobile touchscreen, the active state is the primary feedback because hover never fires.

Disabled And Loading

The disabled button is present but non-interactive. The visual treatment reduces emphasis. Material Design sets the container fill opacity to 12% and the text or icon opacity to 38%. Apple HIG sets foreground elements to 40% opacity. The cursor changes to cursor: not-allowed. The button must not receive focus, hover, or press events. The critical failure mode here is accessibility: a button in this state without an ARIA label or helper text strands a screen-reader user because the user cannot determine why the action is unavailable. Add aria-disabled="true" or use the disabled HTML attribute, and provide a reason in adjacent live text or via aria-describedby.

Loading means the button has been pressed and the action is in progress. Replace the label with a circular spinner. Material Design specifies a 24 dp diameter spinner with a minimum animation cycle of 1000 ms per rotation. The button remains interactive in the sense that it prevents double submission: the state is visually active but functionally non-operable. For users who set prefers-reduced-motion in their system settings, the CSS media query should disable the spinner animation and show a static indicator or a text label like "Submitting...".

Touch Target Requirements: 24 CSS Pixels vs 44 Pt vs 48 Dp

The single most common sizing error in button design is treating WCAG 2.2's minimum touch target, Apple HIG's recommendation, and Material Design's specification as interchangeable units. They are not equivalent and each applies to a different context.

WCAG 2.2 AA requires a minimum target size of 24 x 24 CSS pixels. This is the legal baseline. It applies to all interactive elements except inline links. A button smaller than 24 CSS pixels fails WCAG 2.2. Apple HIG recommends a minimum tappable area of 44 x 44 pt. A point on Apple platforms is a logical unit that maps to a physical pixel ratio. At standard display density, 44 pt equals roughly 7.2 mm, which is the size at which finger-tap accuracy reaches near 100 percent. Material Design 3 sets the minimum at 48 x 48 dp. On Android, a density-independent pixel (dp) equals one physical pixel on a baseline screen, so 48 dp is approximately 7.6 mm. Microsoft Fluent UI specifies 40 x 40 effective pixels (epx), and IBM Carbon and Adobe Spectrum both set a 40 x 40 px minimum.

What this means in practice: if you design a button at 24 CSS pixels, it passes WCAG 2.2 but falls below Apple HIG, Material Design, Fluent, Carbon, and Spectrum recommendations. A user with large fingers or reduced motor control will miss the target repeatedly. Design to the highest platform recommendation your product targets. For a web application used primarily on desktop, 40 x 40 CSS pixels is a safe minimum. For mobile, 44 pt (Apple) or 48 dp (Android) is the floor. The touch target can be larger than the visible button: use transparent padding or the CSS min-width and min-height properties to extend the hit area beyond the visual bounds.

Platform Touch Target Minimums and the Legal Baseline
StandardMinimum SizeUnitContext
WCAG 2.2 AA24CSS pixelsLegal minimum; exempts inline links
Apple HIG44PtiOS, iPadOS, macOS; finger-tap accuracy baseline
Material Design 348DpAndroid; baseline reference screen
Microsoft Fluent UI40EpxWindows; effective pixel
IBM Carbon40PxEnterprise web applications
Adobe Spectrum40PxAdobe product ecosystem

Primary vs Secondary vs Tertiary: Hierarchy By Function, Not Aesthetics

Many designers choose primary, secondary, and tertiary button styles by matching the brand color palette or by personal preference. Assign hierarchy by the action's function. A primary button performs the most important or most common action on the screen: "Submit", "Save", "Continue", "Add to Cart". It must have a solid fill of the brand color or a high-emphasis fill. A secondary button performs an alternative but valid action: "Cancel", "Back", "Skip". It uses an outline only or a low-emphasis fill, with no fill or a transparent fill. A tertiary button performs a less critical action or navigates: "Learn More", "View Details". It has no fill and no outline, appearing as text only.

Place exactly one primary button per view, except in multi-step workflows where each step has its own primary action. Multiple primary buttons on the same screen confuse the user about which action is recommended. The secondary and tertiary buttons should be visually subordinate through reduced fill, reduced weight, or reduced size. Material Design sets the primary button font weight to 500 (Medium) and the tertiary to 400 (Regular). Apple HIG uses Semibold for primary and Regular for secondary. The sizing ratio between hierarchy levels is roughly 1.0x base for primary, 0.9x to 1.0x for secondary, and 0.85x to 1.0x for tertiary, though the primary effect comes from fill and weight rather than size alone.

Before And After: A Button Set Missing Focus And Loading States

Consider a sign-up form with a "Create Account" button. The before version has four states: default, hover, active, and disabled. The non-interactive state uses 40% opacity. There is no focus indicator, so keyboard users see no change when tabbing to the button. There is no loading state, so a user who clicks the button twice submits the form twice. The after version adds a 2 px focus ring with a 3:1 contrast ratio using :focus-visible. It adds a loading state that replaces the label with a 24 dp circular spinner that animates for 1000 ms per cycle and stops when the action completes. The non-interactive state now includes an aria-describedby attribute pointing to text that reads "Complete all required fields above to enable this button." The before set fails WCAG 2.2 SC 2.4.11 (Focus Appearance) and SC 2.5.8 (Target Size) if the button is smaller than 24 px. The after set passes both.

Accessible Button Design: Contrast, Focus, And The Disabled State Trap

Accessible button design is not an add-on. It is a set of pass-fail criteria. The minimum contrast for button text against its fill is 4.5:1 (WCAG 2.2 AA) at any text size. If the button uses only a border to indicate its boundary, that border must have a 3:1 contrast ratio against the background behind it. The focus indicator must be at least 2 CSS pixels thick with a 3:1 contrast against adjacent colors. The indicator's area must equal at least the perimeter of a 2 px line on the shortest side of the button. For a 40 x 40 px button, that is 80 square pixels of indicator area.

The disabled state trap is the most common failure. A button that is greyed out but still focusable by keyboard can receive focus, but a screen reader user cannot activate it. The user hears the button label but receives no feedback about why it is unavailable. The fix: use aria-disabled="true" on the button element, or use the disabled HTML attribute, and add helper text visible to screen readers via aria-describedby or an adjacent live region. Do not use aria-hidden="true" on a non-interactive button; it removes the element from the accessibility tree entirely.

The Single Most Practical Thing To Do Next

Open your current button component in Figma or your codebase. Check for six states. If the focus state is missing, add it now: a 2 px thick outline with 3:1 contrast against the button's background, triggered by :focus-visible. If the loading state is missing, add a 24 dp circular spinner with a 1000 ms cycle. If the non-interactive state lacks an ARIA label or helper text, add aria-describedby pointing to a visible or screen-reader-only message explaining why the action is unavailable. Test the button set against WCAG 2.2 target size: measure the touch target in CSS pixels, not the visible button area. If it is below 24 px, increase the hit area with transparent padding. That one audit catches the most common failures that cause accessibility lawsuits and user drop-off.

Frequently Asked Questions

What is the difference between a disabled button and a loading button?

A disabled button is non-interactive and cannot receive focus or clicks. A loading button is visually active but functionally prevents double submission: it shows a spinner or progress indicator, keeps the button in the tab order, and becomes re-enabled when the action completes. Both states must be communicated visually and programmatically.

Can a button have both a hover state and a focus state visible at the same time?

Yes. On a pointer-driven device, a user can hover over a button while it also has keyboard focus. In this case, the focus indicator must remain visible, and the hover overlay applies on top of it. The focus indicator should never be removed or obscured by a hover effect.

What is the minimum font size for button labels?

Apple HIG recommends 17 pt for mobile. Material Design specifies 14 sp. For desktop, 12 pt is a common minimum, though platform guidelines vary. The WCAG 2.2 large text threshold is 18 pt regular or 14 pt bold, so text below that size must meet the 4.5:1 contrast ratio.

How do I handle button spacing between adjacent buttons?

Material Design specifies a minimum of 8 dp between adjacent buttons. Apple HIG recommends 8 pt. For web, use margin or gap values that match the platform guideline. Insufficient spacing causes users to tap the wrong button, especially on mobile.

What CSS properties control the button box model?

The CSS box model applies: content, padding, border, and margin. Use <code>box-sizing: border-box</code> so that width and height include padding and border. Material Design specifies horizontal padding of 16 dp and vertical padding of 10 dp for filled buttons. Apple HIG specifies 16 pt horizontal and 8 pt vertical.

What is the difference between touch target and CSS pixel?

A CSS pixel is a logical unit that maps to a physical pixel on the screen. A touch target is the area that responds to a tap. The touch target can be larger than the visible button if you add transparent padding or use <code>min-width</code> and <code>min-height</code>. WCAG 2.2 requires a 24 x 24 CSS pixel touch target, not a 24 x 24 visual button.

When does the EU Accessibility Act require WCAG 2.1 AA compliance for buttons?

The enforcement date for private sector products and services is June 28, 2025. The standard referenced is EN 301 549 V3.2.1, which mandates WCAG 2.1 AA. This includes the 24 x 24 CSS pixel target size requirement for buttons and other interactive elements.