Form Styling
Style forms beautifully with Tailwind — inputs, selects, checkboxes, validation states, and accessible form layout patterns.
Form Input Styling
Style text inputs with border, rounded, padding, and focus ring utilities. The @tailwindcss/forms plugin provides sensible defaults that normalize cross-browser form element appearance.
Always include focus styles: focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500. Never remove focus indicators without providing an alternative.
- Install @tailwindcss/forms for consistent cross-browser styling
- Use peer variant for label-input associations
- Disabled state: disabled:opacity-50 disabled:cursor-not-allowed
<input type="text"
class="w-full px-3 py-2 border border-gray-300 rounded-lg
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500
placeholder:text-gray-400" />Form Layout
Stack form fields with space-y-4. Use grid for multi-column forms: grid grid-cols-1 md:grid-cols-2 gap-4. Label-input pairs work well with flex flex-col gap-1.
Group related fields with fieldset and legend. Use consistent spacing and alignment so forms feel structured and scannable.
<form class="space-y-6 max-w-lg">
<div class="flex flex-col gap-1">
<label class="text-sm font-medium text-gray-700">Email</label>
<input type="email" class="..." />
</div>
<div class="flex flex-col gap-1">
<label class="text-sm font-medium text-gray-700">Password</label>
<input type="password" class="..." />
</div>
<button type="submit" class="btn-primary w-full">Sign In</button>
</form>Validation States
Show validation with color-coded borders and messages. Error state: border-red-500 focus:ring-red-500 with a text-red-600 message below. Success state: border-green-500.
Use aria-invalid and aria-describedby for screen reader accessibility. Connect error messages to inputs so assistive technology announces validation failures.
<div class="flex flex-col gap-1">
<input aria-invalid="true" aria-describedby="email-error"
class="border-red-500 focus:ring-red-500" />
<p id="email-error" class="text-sm text-red-600">
Please enter a valid email address.
</p>
</div>Checkboxes and Custom Controls
Style checkboxes and radios with accent-color or custom designs using peer and sr-only. Hide the native input with sr-only, style a custom element, and toggle appearance with peer-checked:.
Custom form controls must preserve keyboard accessibility and screen reader compatibility. Never remove the native input — hide it visually with sr-only.
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="peer sr-only" />
<span class="w-5 h-5 border-2 border-gray-300 rounded
peer-checked:bg-blue-600 peer-checked:border-blue-600
flex items-center justify-center">
<svg class="w-3 h-3 text-white hidden peer-checked:block">...</svg>
</span>
Accept terms
</label>Select and Textarea
Style selects with the same border and focus utilities as text inputs. Add appearance-none and a custom chevron background image for consistent cross-browser styling.
Textareas benefit from resize-y or resize-none and min-h-* for consistent initial height. Match padding and border radius with other form elements for visual cohesion.
<select class="w-full px-3 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 appearance-none
bg-[url('chevron.svg')] bg-no-repeat bg-[right_0.5rem_center]">
<option>Choose...</option>
</select>
<textarea rows="4" class="w-full px-3 py-2 border border-gray-300
rounded-lg focus:ring-2 focus:ring-blue-500 resize-y min-h-[100px]" />