DEV Community

Cover image for Elegant Form Validation with React Hook Form and Tailwind CSS
HexShift
HexShift

Posted on

Elegant Form Validation with React Hook Form and Tailwind CSS

Forms are a fundamental part of any application. By combining React Hook Form and Tailwind CSS, you can build accessible, responsive, and well-validated forms with minimal code and maximum flexibility.


Why React Hook Form?

  • Small and performant
  • Easy to integrate with UI libraries
  • Built-in validation
  • Supports schema-based validation with Zod/Yup

Install Dependencies

npm install react-hook-form
Enter fullscreen mode Exit fullscreen mode

ContactForm.js

import { useForm } from 'react-hook-form'

export default function ContactForm() {
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
  } = useForm()

  const onSubmit = (data) => {
    console.log(data)
  }

  return (
    <form
      onSubmit={handleSubmit(onSubmit)}
      className="max-w-md mx-auto bg-white p-6 shadow rounded space-y-4"
    >
      <div>
        <label className="block text-sm font-medium text-gray-700">
          Name
        </label>
        <input
          {...register('name', { required: 'Name is required' })}
          className={`mt-1 block w-full border rounded px-3 py-2 ${
            errors.name
              ? 'border-red-500 focus:border-red-500'
              : 'border-gray-300 focus:border-indigo-500'
          }`}
        />
        {errors.name && (
          <p className="text-red-600 text-sm mt-1">{errors.name.message}</p>
        )}
      </div>

      <div>
        <label className="block text-sm font-medium text-gray-700">
          Email
        </label>
        <input
          {...register('email', {
            required: 'Email is required',
            pattern: {
              value: /^\S+@\S+$/i,
              message: 'Invalid email address',
            },
          })}
          className={`mt-1 block w-full border rounded px-3 py-2 ${
            errors.email
              ? 'border-red-500 focus:border-red-500'
              : 'border-gray-300 focus:border-indigo-500'
          }`}
        />
        {errors.email && (
          <p className="text-red-600 text-sm mt-1">{errors.email.message}</p>
        )}
      </div>

      <div>
        <label className="block text-sm font-medium text-gray-700">
          Message
        </label>
        <textarea
          {...register('message', { required: 'Message is required' })}
          className={`mt-1 block w-full border rounded px-3 py-2 h-24 ${
            errors.message
              ? 'border-red-500 focus:border-red-500'
              : 'border-gray-300 focus:border-indigo-500'
          }`}
        />
        {errors.message && (
          <p className="text-red-600 text-sm mt-1">{errors.message.message}</p>
        )}
      </div>

      <button
        type="submit"
        disabled={isSubmitting}
        className="w-full bg-indigo-600 text-white py-2 px-4 rounded hover:bg-indigo-700 transition"
      >
        {isSubmitting ? 'Sending...' : 'Send Message'}
      </button>
    </form>
  )
}
Enter fullscreen mode Exit fullscreen mode

Key Tailwind Utilities Used

  • border, rounded, focus:border-*: Interactive styling
  • text-sm, mt-1, space-y-4: Typography and spacing
  • bg-indigo-600 hover:bg-indigo-700: Styled button
  • text-red-600: Validation error display

Bonus: Schema Validation with Zod

Install:

npm install zod @hookform/resolvers
Enter fullscreen mode Exit fullscreen mode

Add validation:

import { z } from 'zod'
import { zodResolver } from '@hookform/resolvers/zod'

const schema = z.object({
  name: z.string().min(1, 'Name is required'),
  email: z.string().email('Invalid email'),
  message: z.string().min(1, 'Message is required'),
})

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm({
  resolver: zodResolver(schema),
})
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

React Hook Form keeps forms lean, while Tailwind gives you all the control for layout and interaction. Together, they help you build fast, user-friendly forms without custom CSS or complex logic.

Mastering Tailwind at Scale: Architecture, Patterns & Performance

Build smarter, validate simpler.

Top comments (0)