Forms
Forms translate intent into structured data—signups, shipping details, profile updates, or preferences that keep the experience moving. Clear labels, predictable spacing, and well-placed helper text ensure people know what belongs in each field without guessing, while validation and state feedback gently guide them through completion.
The patterns below show how to compose different form types, from expansive address capture to focused logins and compact, integrated labels. Use them with the same care you apply to typography, links, and buttons so every form feels like part of a cohesive system that respects both speed and accessibility.
Basic form
Basic forms rely on stacked labels, generous gutters, and consistent field widths so long inputs (addresses, company info, tax IDs) stay readable. Start with this layout for most data-entry screens, pair related fields in logical groups, and keep the control row aligned to the grid so desktop and mobile flows remain predictable.
Accessibility first: keep every control paired with a visible label (even when placeholders exist), announce required vs. optional fields clearly, and surface inline errors with concrete guidance. Respect logical tab order, preserve focus rings, and ensure touch targets and contrast meet WCAG so long forms stay usable for keyboards and screen readers.
<form class="basic-form">
<label for="...">...</label>
<input type="..." id="...">
</form>
Login form
Login forms should be fast, calm checkpoints: a username/email, a password, and a clear submit action. Keep labels visible instead of relying solely on placeholders so password managers and assistive tech can map inputs reliably, and reserve inline links (like “Forgot password?”) for contextual recovery without pulling users out of the flow.
Arrange fields in a concise vertical rhythm, align controls in the .controls row, and avoid competing calls-to-action near the primary button. Treat validation gently—highlight the specific field, explain how to fix it, and let Enter/Return submit to respect keyboard habits.
Constrain the canvas: wrapping login forms in a .container keeps the layout narrow, centers it within a page, and reduces scanning distance so people can focus on the two critical fields.
Add subtle cues: icons next to email and password inputs hint at expected content in compact views. Keep them purely decorative (aria-hidden=\"true\") and let the visible labels and placeholders carry meaning so screen readers remain in sync.
Usability checklist: honor browser autofill and password managers, provide a visible focus state on every element (including the “Remember me” checkbox), and avoid locking out repeated attempts with aggressive rate limits. For failed sign-ins, use plain language, keep the form populated, and offer a recovery link or contact path without breaking the page flow.
<form action="..." class="login-form container" >
<label for="username">Username</label>
<input type="text" id="username" required>
<label for="password">Password</label>
<input type="password" id="password" required>
<div class="controls">
<label for="remember">
<input id="remember" type="checkbox"> Keep me logged in
</label>
<button type="submit" class="primary">Login</button>
<a href="" class="forgot-password">Forgot password?</a>
<div class="spacer"></div>
</div>
</form>
<!-- Compact Login Form -->
<form action="..." class="login-form container gray">
<div class="group">
<svg class="icon"></svg>
<input type="email" id="email" required placeholder="E-mail address" class="prepend-icon">
</div>
<div class="group">
<svg class="icon"></svg>
<input type="password" id="password" required class="prepend-icon" placeholder="Password">
</div>
<div class="controls">
<label for="remember">
<input id="remember" type="checkbox"> Remember me
</label>
<button type="submit" class="primary">Sign in</button>
<div class="spacer"></div>
</div>
</form>
Integrated labels
Integrated labels keep labels inside the field boundary, preserving context even after someone starts typing. They reduce vertical height, work well in dense UIs, and keep the label present so the input’s purpose never disappears once the placeholder is replaced with real content.
Use this pattern for short inputs like email, passwords, or URLs when space is tight. Keep motion minimal: labels should lift or shrink smoothly without obscuring typed text, and placeholder copy should remain concise so the control still reads as an input rather than a button.
Clarity over flair: ensure the resting label has sufficient contrast, and that the floating state leaves enough room for long translations. Never rely on placeholder text to convey requirements; the persistent label and any helper text should carry the meaning for screen readers and speech-to-text users.
<div class="integrated-label">
<input type="..." id="..." placeholder="...">
<label for="...">...</label>
</div>
Integrated labels in groups
Grouped integrated labels place multiple floating-label inputs on a single row, balancing density with clarity. They’re ideal for compact auth forms or paired fields like URL + selector, letting related inputs stay visually connected while keeping each label discoverable.
Mind the flow: keep tab order aligned with the visual layout, collapse groups to a single column on small screens, and check that floating labels never overlap icons or adornments. For additional validation patterns and state handling, see Input fields.
<div class="integrated-label">
<input type="..." id="..." placeholder="...">
<label for="...">...</label>
</div>