Form Basics

What You'll Learn

  • How to style basic form inputs with consistent, accessible design patterns
  • Master focus states using :focus, :focus-visible, and :focus-within
  • Customize placeholder text appearance with ::placeholder pseudo-element
  • Style disabled and read-only states to provide clear visual feedback
  • Implement common form layout patterns: stacked, inline, and grid layouts
  • Create accessible form controls with proper keyboard navigation support

Introduction to Form Styling

Form styling is essential for creating intuitive, accessible user interfaces. Well-styled forms guide users through data entry, provide clear feedback, and ensure consistency across different browsers and devices. Forms are one of the most important interaction points between users and web applications, making their design critical for usability.

CSS provides powerful pseudo-classes and pseudo-elements for styling form states. Understanding how to use :focus, :disabled, ::placeholder, and other form-specific selectors allows you to create professional, accessible forms that work well with keyboard navigation and assistive technologies.

Basic Input Styling

Start with clean, consistent styling for text inputs. Remove default browser styles and add custom borders, padding, and focus states. Using font-family: inherit ensures inputs match your page typography.

.input { width: 100%; padding: 10px 12px; border: 2px solid #ddd; border-radius: 4px; font-size: 16px; font-family: inherit; transition: border-color 0.3s ease; } .input:focus { outline: none; border-color: #10b981; }

Focus States

CSS provides three pseudo-classes for managing focus: :focus, :focus-visible, and :focus-within. Each serves a different purpose in creating accessible, user-friendly forms.

:focus (Standard Focus)

The :focus pseudo-class applies when an element receives focus through any method, including mouse clicks, touch, or keyboard navigation. It always shows a focus indicator regardless of how the element was focused.

input:focus { outline: 3px solid #3b82f6; outline-offset: 2px; border-color: #3b82f6; }

:focus-visible (Keyboard-Only Focus)

The :focus-visible pseudo-class is smarter. It only shows focus indicators when the user navigates with a keyboard, hiding them when clicking with a mouse. This provides a cleaner visual experience without sacrificing accessibility.

input:focus { outline: none; border-color: #ddd; } input:focus-visible { outline: 3px solid #f59e0b; outline-offset: 2px; border-color: #f59e0b; }

:focus-within (Parent Container Focus)

The :focus-within pseudo-class styles a parent element when any child element has focus. This is useful for highlighting entire form sections or containers when users interact with inputs inside them.

.form-container:focus-within { border-color: #a855f7; background: #faf5ff; box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.1); }

Placeholder Styling

The ::placeholder pseudo-element allows you to style placeholder text in form inputs. Use it to create subtle hints that don't distract from the actual input content.

input::placeholder { color: #9ca3af; font-style: italic; opacity: 1; } /* Custom styled placeholder */ .custom::placeholder { color: #6366f1; font-weight: 600; letter-spacing: 0.5px; }

Disabled and Read-only States

Disabled and read-only inputs serve different purposes. Disabled inputs cannot be interacted with and their values aren't submitted with the form. Read-only inputs can be focused and copied, and their values are submitted.

Disabled State

input:disabled { background: #f3f4f6; color: #9ca3af; cursor: not-allowed; opacity: 0.6; } <input type="text" value="Cannot edit" disabled>

Read-only State

input:read-only { background: #fef3c7; border-color: #f59e0b; cursor: default; } <input type="text" value="Can focus but not edit" readonly>

Form Layout Patterns

Common form layouts include stacked (vertical), inline (horizontal), and grid patterns. Each serves different use cases and screen sizes.

Stacked Layout (Mobile-First)

The stacked layout places labels above inputs, creating a vertical flow. This is the most mobile-friendly pattern and works well for all form lengths.

.form-group { margin-bottom: 1.5rem; } .form-group label { display: block; margin-bottom: 6px; font-weight: 600; } .form-group input { width: 100%; padding: 10px 12px; border: 2px solid #ddd; border-radius: 4px; }

Inline Layout

Inline layouts place labels and inputs on the same line using flexbox. This works well for short forms or single-field patterns like search bars.

.form-inline { display: flex; gap: 10px; align-items: center; } .form-inline label { flex-shrink: 0; font-weight: 600; } .form-inline input { flex: 1; }

Grid Layout

Grid layouts create multi-column forms that respond automatically to available space using grid-template-columns with auto-fit.

.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; }

Key Takeaways