← Back to Tailwind CSS Mastery
Basic13 min read

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]" />

Get In Touch


Ready to discuss your next project? Drop me a message.