CSS Form Pseudo-classes ๐Ÿ“

Style form elements based on their state, validity, and user interaction without JavaScript.

What are Form Pseudo-classes?

Form pseudo-classes are CSS selectors that allow you to style form elements based on their current state, validity, and user interaction. They provide powerful ways to create interactive and user-friendly forms with immediate visual feedback.

๐ŸŽฏ State-based Styling

Style elements based on :focus, :checked, :disabled states

โœ… Validation Feedback

Provide instant visual feedback with :valid and :invalid

โšก No JavaScript Required

Create interactive forms with pure CSS

Basic Form Pseudo-classes

Essential Pseudo-classes:

  • :focus - Styles when element is focused
  • :valid / :invalid - Based on input validation
  • :required / :optional - For required fields
  • :disabled / :enabled - For disabled state
  • :read-only / :read-write - For editable state

Basic Form Pseudo-classes Implementation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Basic Form Pseudo-classes</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Inter', sans-serif;
      line-height: 1.6;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      min-height: 100vh;
      padding: 2rem;
    }
    
    .container {
      max-width: 800px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      margin-bottom: 3rem;
      color: white;
    }
    
    .header h1 {
      font-size: 3rem;
      margin-bottom: 1rem;
      text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
    }
    
    .form-container {
      background: white;
      border-radius: 15px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }
    
    .form-group {
      margin-bottom: 2rem;
    }
    
    label {
      display: block;
      margin-bottom: 0.5rem;
      font-weight: 600;
      color: #2c3e50;
    }
    
    .form-control {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      font-size: 1rem;
      transition: all 0.3s ease;
    }
    
    /* :focus pseudo-class */
    .form-control:focus {
      outline: none;
      border-color: #3498db;
      box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
      transform: translateY(-2px);
    }
    
    /* :required pseudo-class */
    .form-control:required {
      border-left: 4px solid #e74c3c;
    }
    
    .form-control:required:valid {
      border-left-color: #2ecc71;
    }
    
    /* :optional pseudo-class */
    .form-control:optional {
      background-color: #f8f9fa;
    }
    
    /* :valid and :invalid pseudo-classes */
    .form-control:valid {
      border-color: #2ecc71;
      background-color: rgba(46, 204, 113, 0.05);
    }
    
    .form-control:invalid {
      border-color: #e74c3c;
      background-color: rgba(231, 76, 60, 0.05);
    }
    
    /* :disabled pseudo-class */
    .form-control:disabled {
      background-color: #ecf0f1;
      color: #95a5a6;
      cursor: not-allowed;
      opacity: 0.6;
    }
    
    /* :read-only pseudo-class */
    .form-control:read-only {
      background-color: #fff3cd;
      border-color: #ffeaa7;
      color: #856404;
    }
    
    .demo-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 1rem;
      margin-top: 2rem;
    }
    
    .demo-item {
      padding: 1rem;
      border-radius: 8px;
      background: #f8f9fa;
    }
    
    .code-example {
      background: #2c3e50;
      color: white;
      padding: 1rem;
      border-radius: 10px;
      margin-top: 1rem;
      font-family: monospace;
      font-size: 0.9rem;
    }
    
    .status-indicator {
      display: inline-block;
      width: 10px;
      height: 10px;
      border-radius: 50%;
      margin-right: 0.5rem;
    }
    
    .status-valid { background: #2ecc71; }
    .status-invalid { background: #e74c3c; }
    .status-optional { background: #3498db; }
    .status-required { background: #f39c12; }
    
    @media (max-width: 768px) {
      .demo-grid {
        grid-template-columns: 1fr;
      }
      
      .header h1 {
        font-size: 2rem;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>๐ŸŽฏ Form Pseudo-classes</h1>
      <p>Style form elements based on their state</p>
    </div>
    
    <div class="form-container">
      <form id="demoForm">
        <div class="form-group">
          <label for="email">Email Address <span class="status-required status-indicator"></span>Required</label>
          <input type="email" id="email" class="form-control" placeholder="Enter your email" required>
          <div class="code-example">
            input:required { border-left: 4px solid #e74c3c; }
            input:required:valid { border-left-color: #2ecc71; }
          </div>
        </div>
        
        <div class="form-group">
          <label for="name">Full Name <span class="status-optional status-indicator"></span>Optional</label>
          <input type="text" id="name" class="form-control" placeholder="Enter your name">
          <div class="code-example">
            input:optional { background-color: #f8f9fa; }
          </div>
        </div>
        
        <div class="form-group">
          <label for="password">Password <span class="status-required status-indicator"></span>Required</label>
          <input type="password" id="password" class="form-control" placeholder="Enter password" required minlength="6">
          <div class="code-example">
            input:valid { border-color: #2ecc71; }
            input:invalid { border-color: #e74c3c; }
          </div>
        </div>
        
        <div class="demo-grid">
          <div class="demo-item">
            <label for="disabledInput">Disabled Field</label>
            <input type="text" id="disabledInput" class="form-control" value="This field is disabled" disabled>
            <div class="code-example">
              input:disabled { 
                background-color: #ecf0f1;
                cursor: not-allowed;
              }
            </div>
          </div>
          
          <div class="demo-item">
            <label for="readonlyInput">Read-only Field</label>
            <input type="text" id="readonlyInput" class="form-control" value="This field is read-only" readonly>
            <div class="code-example">
              input:read-only { 
                background-color: #fff3cd;
                border-color: #ffeaa7;
              }
            </div>
          </div>
        </div>
        
        <div class="form-group">
          <label for="url">Website URL</label>
          <input type="url" id="url" class="form-control" placeholder="https://example.com">
          <div class="code-example">
            input:focus { 
              border-color: #3498db;
              box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
            }
          </div>
        </div>
      </form>
      
      <div style="margin-top: 2rem; padding: 1rem; background: #e8f4fd; border-radius: 8px;">
        <h3>๐Ÿ’ก Interactive Demo</h3>
        <p>Try interacting with the form fields to see the different states:</p>
        <ul>
          <li><span class="status-valid status-indicator"></span> Focus on fields to see :focus styles</li>
          <li><span class="status-invalid status-indicator"></span> Enter invalid data to see :invalid styles</li>
          <li><span class="status-required status-indicator"></span> Required fields have special indicators</li>
        </ul>
      </div>
    </div>
  </div>
</body>
</html>

Advanced Form Pseudo-classes

Input Validation

Use :in-range, :out-of-range, and :placeholder-shown for advanced validation states.

input:in-range { border-color: green; }
input:out-of-range { border-color: red; }

Custom Controls

Create custom checkboxes, radio buttons, and selects using :checked and :indeterminate.

input:checked ~ .checkmark {
ย ย background: blue;
}

Advanced Form Pseudo-classes Implementation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Advanced Form Pseudo-classes</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Inter', sans-serif;
      line-height: 1.6;
      background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
      min-height: 100vh;
      padding: 2rem;
    }
    
    .container {
      max-width: 1000px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      margin-bottom: 3rem;
      color: white;
    }
    
    .header h1 {
      font-size: 3rem;
      margin-bottom: 1rem;
      text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
    }
    
    .form-container {
      background: white;
      border-radius: 15px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }
    
    .form-group {
      margin-bottom: 2rem;
    }
    
    label {
      display: block;
      margin-bottom: 0.5rem;
      font-weight: 600;
      color: #2c3e50;
    }
    
    /* :in-range and :out-of-range */
    .range-input {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      font-size: 1rem;
    }
    
    .range-input:in-range {
      border-color: #2ecc71;
      background-color: rgba(46, 204, 113, 0.05);
    }
    
    .range-input:out-of-range {
      border-color: #e74c3c;
      background-color: rgba(231, 76, 60, 0.05);
    }
    
    /* :checked for checkboxes and radio buttons */
    .checkbox-group, .radio-group {
      display: flex;
      gap: 1rem;
      flex-wrap: wrap;
      margin: 1rem 0;
    }
    
    .custom-checkbox, .custom-radio {
      position: relative;
      padding-left: 2rem;
      cursor: pointer;
    }
    
    .custom-checkbox input, .custom-radio input {
      position: absolute;
      opacity: 0;
    }
    
    .checkmark {
      position: absolute;
      left: 0;
      top: 0;
      height: 1.5rem;
      width: 1.5rem;
      background: #ecf0f1;
      border: 2px solid #bdc3c7;
      border-radius: 4px;
      transition: all 0.3s ease;
    }
    
    .custom-checkbox input:checked ~ .checkmark {
      background: #3498db;
      border-color: #3498db;
    }
    
    .custom-checkbox input:checked ~ .checkmark::after {
      content: "โœ“";
      position: absolute;
      color: white;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
    
    .radiomark {
      position: absolute;
      left: 0;
      top: 0;
      height: 1.5rem;
      width: 1.5rem;
      background: #ecf0f1;
      border: 2px solid #bdc3c7;
      border-radius: 50%;
      transition: all 0.3s ease;
    }
    
    .custom-radio input:checked ~ .radiomark {
      border-color: #9b59b6;
    }
    
    .custom-radio input:checked ~ .radiomark::after {
      content: "";
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 0.75rem;
      height: 0.75rem;
      background: #9b59b6;
      border-radius: 50%;
    }
    
    /* :default pseudo-class */
    .default-demo input:default {
      border-color: #f39c12;
      background-color: rgba(243, 156, 18, 0.1);
    }
    
    /* :indeterminate for checkboxes */
    .indeterminate-checkbox input:indeterminate ~ .checkmark {
      background: #95a5a6;
      border-color: #95a5a6;
    }
    
    .indeterminate-checkbox input:indeterminate ~ .checkmark::after {
      content: "โ€“";
      position: absolute;
      color: white;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
    
    /* :placeholder-shown */
    .placeholder-demo {
      position: relative;
    }
    
    .placeholder-demo input {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      font-size: 1rem;
    }
    
    .placeholder-demo input:placeholder-shown {
      border-color: #e67e22;
    }
    
    .placeholder-demo input:not(:placeholder-shown) {
      border-color: #27ae60;
    }
    
    /* :user-valid and :user-invalid */
    .user-validation input {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      font-size: 1rem;
      transition: all 0.3s ease;
    }
    
    .user-validation input:user-valid {
      border-color: #27ae60;
      background-color: rgba(39, 174, 96, 0.05);
    }
    
    .user-validation input:user-invalid {
      border-color: #c0392b;
      background-color: rgba(192, 57, 43, 0.05);
    }
    
    .demo-section {
      background: #f8f9fa;
      padding: 1.5rem;
      border-radius: 10px;
      margin: 1rem 0;
    }
    
    .code-example {
      background: #2c3e50;
      color: white;
      padding: 1rem;
      border-radius: 10px;
      margin-top: 1rem;
      font-family: monospace;
      font-size: 0.8rem;
    }
    
    .browser-note {
      background: #fff3cd;
      border-left: 4px solid #ffc107;
      padding: 1rem;
      margin: 1rem 0;
      border-radius: 5px;
    }
    
    @media (max-width: 768px) {
      .checkbox-group, .radio-group {
        flex-direction: column;
      }
      
      .header h1 {
        font-size: 2rem;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>โšก Advanced Form Pseudo-classes</h1>
      <p>Advanced state management for complex forms</p>
    </div>
    
    <div class="form-container">
      <form id="advancedForm">
        <!-- :in-range and :out-of-range -->
        <div class="form-group">
          <label for="age">Age (10-100):</label>
          <input type="number" id="age" class="range-input" min="10" max="100" value="25">
          <div class="code-example">
            input:in-range { border-color: #2ecc71; }
            input:out-of-range { border-color: #e74c3c; }
          </div>
        </div>
        
        <!-- :checked for checkboxes -->
        <div class="form-group">
          <label>Interests:</label>
          <div class="checkbox-group">
            <label class="custom-checkbox">
              <input type="checkbox" name="interests" value="tech" checked>
              <span class="checkmark"></span>
              Technology
            </label>
            <label class="custom-checkbox">
              <input type="checkbox" name="interests" value="sports">
              <span class="checkmark"></span>
              Sports
            </label>
            <label class="custom-checkbox">
              <input type="checkbox" name="interests" value="music">
              <span class="checkmark"></span>
              Music
            </label>
          </div>
          <div class="code-example">
            input:checked ~ .checkmark { 
              background: #3498db;
              border-color: #3498db;
            }
          </div>
        </div>
        
        <!-- :checked for radio buttons -->
        <div class="form-group">
          <label>Preferred Contact:</label>
          <div class="radio-group">
            <label class="custom-radio">
              <input type="radio" name="contact" value="email" checked>
              <span class="radiomark"></span>
              Email
            </label>
            <label class="custom-radio">
              <input type="radio" name="contact" value="phone">
              <span class="radiomark"></span>
              Phone
            </label>
            <label class="custom-radio">
              <input type="radio" name="contact" value="sms">
              <span class="radiomark"></span>
              SMS
            </label>
          </div>
          <div class="code-example">
            input:checked ~ .radiomark { 
              border-color: #9b59b6;
            }
          </div>
        </div>
        
        <!-- :default -->
        <div class="form-group default-demo">
          <label for="country">Country:</label>
          <select id="country" class="form-control">
            <option value="us" selected>United States</option>
            <option value="ca">Canada</option>
            <option value="uk">United Kingdom</option>
            <option value="au">Australia</option>
          </select>
          <div class="code-example">
            select:default { 
              border-color: #f39c12;
              background-color: rgba(243, 156, 18, 0.1);
            }
          </div>
        </div>
        
        <!-- :indeterminate -->
        <div class="form-group">
          <label class="custom-checkbox indeterminate-checkbox">
            <input type="checkbox" id="indeterminateCheckbox">
            <span class="checkmark"></span>
            Indeterminate State (Toggle with button below)
          </label>
          <button type="button" onclick="toggleIndeterminate()" style="margin-top: 0.5rem; padding: 0.5rem 1rem; background: #95a5a6; color: white; border: none; border-radius: 4px; cursor: pointer;">
            Toggle Indeterminate
          </button>
          <div class="code-example">
            input:indeterminate ~ .checkmark { 
              background: #95a5a6;
              border-color: #95a5a6;
            }
          </div>
        </div>
        
        <!-- :placeholder-shown -->
        <div class="form-group placeholder-demo">
          <label for="search">Search:</label>
          <input type="text" id="search" placeholder="Enter search terms...">
          <div class="code-example">
            input:placeholder-shown { border-color: #e67e22; }
            input:not(:placeholder-shown) { border-color: #27ae60; }
          </div>
        </div>
        
        <!-- :user-valid and :user-invalid -->
        <div class="form-group user-validation">
          <label for="username">Username (min 3 chars):</label>
          <input type="text" id="username" required minlength="3" placeholder="Enter username">
          <div class="browser-note">
            <strong>Note:</strong> :user-valid and :user-invalid have limited browser support. 
            They only apply after user interaction.
          </div>
          <div class="code-example">
            input:user-valid { border-color: #27ae60; }
            input:user-invalid { border-color: #c0392b; }
          </div>
        </div>
      </form>
    </div>
  </div>

  <script>
    function toggleIndeterminate() {
      const checkbox = document.getElementById('indeterminateCheckbox');
      checkbox.indeterminate = !checkbox.indeterminate;
    }
    
    // Demo for :user-valid and :user-invalid
    document.getElementById('advancedForm').addEventListener('input', function(e) {
      // Force validation display
      e.target.reportValidity();
    });
  </script>
</body>
</html>

Validation & UI States

Enhanced User Experience

Use :focus-within for container styling, :user-valid/:user-invalid for user-triggered validation, and create sophisticated validation feedback systems.

.form-group:focus-within {
ย ย border-color: blue;
ย ย background: lightblue;
}

Validation & UI States Implementation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Validation & UI Pseudo-classes</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Inter', sans-serif;
      line-height: 1.6;
      background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%);
      min-height: 100vh;
      padding: 2rem;
    }
    
    .container {
      max-width: 1000px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      margin-bottom: 3rem;
      color: #2c3e50;
    }
    
    .header h1 {
      font-size: 3rem;
      margin-bottom: 1rem;
    }
    
    .form-container {
      background: white;
      border-radius: 15px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }
    
    /* Validation states with custom messages */
    .validation-group {
      position: relative;
      margin-bottom: 2rem;
    }
    
    .validation-input {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      font-size: 1rem;
      transition: all 0.3s ease;
    }
    
    .validation-input:valid {
      border-color: #27ae60;
    }
    
    .validation-input:invalid:not(:focus):not(:placeholder-shown) {
      border-color: #e74c3c;
    }
    
    .validation-message {
      display: none;
      font-size: 0.875rem;
      margin-top: 0.5rem;
      padding: 0.5rem;
      border-radius: 4px;
    }
    
    .validation-input:invalid:not(:focus):not(:placeholder-shown) ~ .validation-message {
      display: block;
      background-color: #f8d7da;
      color: #721c24;
      border-left: 4px solid #e74c3c;
    }
    
    .validation-input:valid ~ .validation-message.valid {
      display: block;
      background-color: #d4edda;
      color: #155724;
      border-left: 4px solid #28a745;
    }
    
    /* :focus-within for form groups */
    .focus-within-group {
      position: relative;
      padding: 1.5rem;
      border: 2px solid transparent;
      border-radius: 10px;
      margin-bottom: 2rem;
      transition: all 0.3s ease;
    }
    
    .focus-within-group:focus-within {
      border-color: #3498db;
      background-color: rgba(52, 152, 219, 0.05);
      transform: translateY(-2px);
      box-shadow: 0 5px 15px rgba(0,0,0,0.1);
    }
    
    /* :enabled and :disabled states */
    .state-buttons {
      display: flex;
      gap: 1rem;
      margin: 1rem 0;
    }
    
    .state-button {
      padding: 1rem 2rem;
      border: none;
      border-radius: 8px;
      font-size: 1rem;
      cursor: pointer;
      transition: all 0.3s ease;
    }
    
    .state-button:enabled {
      background: #3498db;
      color: white;
    }
    
    .state-button:enabled:hover {
      background: #2980b9;
      transform: translateY(-2px);
    }
    
    .state-button:disabled {
      background: #bdc3c7;
      color: #7f8c8d;
      cursor: not-allowed;
      opacity: 0.6;
    }
    
    /* :read-only and :read-write */
    .read-write-group {
      margin: 2rem 0;
    }
    
    .read-write-input {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      font-size: 1rem;
      transition: all 0.3s ease;
    }
    
    .read-write-input:read-write {
      background-color: #d4edda;
      border-color: #28a745;
    }
    
    .read-write-input:read-only {
      background-color: #f8d7da;
      border-color: #e74c3c;
      color: #721c24;
    }
    
    /* Progress bar with :indeterminate */
    .progress-group {
      margin: 2rem 0;
    }
    
    .progress-bar {
      width: 100%;
      height: 20px;
      background: #ecf0f1;
      border-radius: 10px;
      overflow: hidden;
      position: relative;
    }
    
    .progress-fill {
      height: 100%;
      background: linear-gradient(90deg, #3498db, #2980b9);
      width: 60%;
      transition: width 0.3s ease;
    }
    
    .progress-bar:indeterminate .progress-fill {
      animation: indeterminate 1.5s infinite linear;
      width: 50%;
    }
    
    @keyframes indeterminate {
      0% { transform: translateX(-100%); }
      100% { transform: translateX(200%); }
    }
    
    /* Custom select styles with :checked */
    .custom-select {
      position: relative;
      margin: 2rem 0;
    }
    
    .select-button {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      background: white;
      cursor: pointer;
      text-align: left;
    }
    
    .select-options {
      display: none;
      position: absolute;
      top: 100%;
      left: 0;
      right: 0;
      background: white;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      margin-top: 0.5rem;
      z-index: 10;
    }
    
    .select-option {
      padding: 1rem;
      cursor: pointer;
      transition: background 0.3s ease;
    }
    
    .select-option:hover {
      background: #3498db;
      color: white;
    }
    
    .select-option:checked {
      background: #2980b9;
      color: white;
    }
    
    .custom-select:focus-within .select-options {
      display: block;
    }
    
    .demo-section {
      background: #f8f9fa;
      padding: 1.5rem;
      border-radius: 10px;
      margin: 1rem 0;
    }
    
    .code-example {
      background: #2c3e50;
      color: white;
      padding: 1rem;
      border-radius: 10px;
      margin-top: 1rem;
      font-family: monospace;
      font-size: 0.8rem;
    }
    
    @media (max-width: 768px) {
      .state-buttons {
        flex-direction: column;
      }
      
      .header h1 {
        font-size: 2rem;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>โœ… Validation & UI States</h1>
      <p>Advanced validation and user interface states</p>
    </div>
    
    <div class="form-container">
      <form id="validationForm">
        <!-- Validation with custom messages -->
        <div class="validation-group">
          <label for="email">Email Address:</label>
          <input type="email" id="email" class="validation-input" placeholder="Enter valid email" required>
          <div class="validation-message">
            Please enter a valid email address
          </div>
          <div class="validation-message valid">
            Email address looks good!
          </div>
          <div class="code-example">
            input:invalid:not(:focus):not(:placeholder-shown) ~ .validation-message {
              display: block;
              background-color: #f8d7da;
            }
          </div>
        </div>
        
        <!-- :focus-within demo -->
        <div class="focus-within-group">
          <label for="name">Full Name:</label>
          <input type="text" id="name" class="validation-input" placeholder="Enter your name" required>
          <div class="code-example">
            .form-group:focus-within {
              border-color: #3498db;
              background-color: rgba(52, 152, 219, 0.05);
            }
          </div>
        </div>
        
        <!-- :enabled and :disabled -->
        <div class="demo-section">
          <label>Button States:</label>
          <div class="state-buttons">
            <button type="button" class="state-button">Enabled Button</button>
            <button type="button" class="state-button" disabled>Disabled Button</button>
          </div>
          <div class="code-example">
            button:enabled { background: #3498db; color: white; }
            button:disabled { background: #bdc3c7; cursor: not-allowed; }
          </div>
        </div>
        
        <!-- :read-only and :read-write -->
        <div class="read-write-group">
          <label for="readWrite">Read-Write Field:</label>
          <input type="text" id="readWrite" class="read-write-input" value="You can edit this field">
          
          <label for="readOnly" style="margin-top: 1rem;">Read-Only Field:</label>
          <input type="text" id="readOnly" class="read-write-input" value="This field is read-only" readonly>
          
          <div class="code-example">
            input:read-write { background-color: #d4edda; }
            input:read-only { background-color: #f8d7da; }
          </div>
        </div>
        
        <!-- Progress bar -->
        <div class="progress-group">
          <label>Progress Bar:</label>
          <div class="progress-bar">
            <div class="progress-fill"></div>
          </div>
          <button type="button" onclick="toggleProgress()" style="margin-top: 0.5rem; padding: 0.5rem 1rem; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer;">
            Toggle Indeterminate
          </button>
          <div class="code-example">
            .progress-bar:indeterminate .progress-fill {
              animation: indeterminate 1.5s infinite linear;
            }
          </div>
        </div>
      </form>
    </div>
  </div>

  <script>
    let progressIndeterminate = false;
    
    function toggleProgress() {
      const progressBar = document.querySelector('.progress-bar');
      progressIndeterminate = !progressIndeterminate;
      
      if (progressIndeterminate) {
        progressBar.setAttribute('indeterminate', '');
      } else {
        progressBar.removeAttribute('indeterminate');
      }
    }
    
    // Real-time validation
    document.getElementById('validationForm').addEventListener('input', function(e) {
      const input = e.target;
      input.reportValidity();
    });
  </script>
</body>
</html>

Practical Examples

๐Ÿ“ Registration Forms

Real-time validation and user feedback

๐Ÿ“Š Survey Forms

Interactive options with visual states

๐Ÿ” Search & Filters

Dynamic filtering with CSS-only interactions

Practical Examples Implementation

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Practical Form Examples</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Inter', sans-serif;
      line-height: 1.6;
      background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
      min-height: 100vh;
      padding: 2rem;
    }
    
    .container {
      max-width: 1200px;
      margin: 0 auto;
    }
    
    .header {
      text-align: center;
      margin-bottom: 3rem;
      color: #2c3e50;
    }
    
    .header h1 {
      font-size: 3rem;
      margin-bottom: 1rem;
    }
    
    .examples-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
      gap: 2rem;
      margin-bottom: 3rem;
    }
    
    .example-card {
      background: white;
      border-radius: 15px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }
    
    /* Registration Form */
    .registration-form .form-group {
      margin-bottom: 1.5rem;
    }
    
    .registration-form label {
      display: block;
      margin-bottom: 0.5rem;
      font-weight: 600;
      color: #2c3e50;
    }
    
    .registration-form input {
      width: 100%;
      padding: 1rem;
      border: 2px solid #bdc3c7;
      border-radius: 8px;
      font-size: 1rem;
      transition: all 0.3s ease;
    }
    
    .registration-form input:focus {
      outline: none;
      border-color: #3498db;
      box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
    }
    
    .registration-form input:valid {
      border-color: #2ecc71;
    }
    
    .registration-form input:invalid:not(:focus) {
      border-color: #e74c3c;
    }
    
    .submit-btn {
      width: 100%;
      padding: 1rem;
      background: #3498db;
      color: white;
      border: none;
      border-radius: 8px;
      font-size: 1rem;
      cursor: pointer;
      transition: all 0.3s ease;
    }
    
    .submit-btn:hover:enabled {
      background: #2980b9;
      transform: translateY(-2px);
    }
    
    .submit-btn:disabled {
      background: #bdc3c7;
      cursor: not-allowed;
      opacity: 0.6;
    }
    
    /* Survey Form */
    .survey-form .question {
      margin-bottom: 2rem;
    }
    
    .options-group {
      display: flex;
      flex-direction: column;
      gap: 1rem;
      margin-top: 1rem;
    }
    
    .option-label {
      display: flex;
      align-items: center;
      gap: 1rem;
      padding: 1rem;
      border: 2px solid #ecf0f1;
      border-radius: 8px;
      cursor: pointer;
      transition: all 0.3s ease;
    }
    
    .option-label:hover {
      border-color: #3498db;
      background: rgba(52, 152, 219, 0.05);
    }
    
    .option-label:has(input:checked) {
      border-color: #2ecc71;
      background: rgba(46, 204, 113, 0.1);
    }
    
    /* Search Filter */
    .search-filter {
      margin: 2rem 0;
    }
    
    .filter-options {
      display: flex;
      gap: 1rem;
      flex-wrap: wrap;
      margin: 1rem 0;
    }
    
    .filter-btn {
      padding: 0.5rem 1rem;
      border: 2px solid #bdc3c7;
      background: white;
      border-radius: 20px;
      cursor: pointer;
      transition: all 0.3s ease;
    }
    
    .filter-btn:checked {
      background: #3498db;
      color: white;
      border-color: #3498db;
    }
    
    .filter-btn:hover {
      border-color: #3498db;
    }
    
    /* Password Strength Meter */
    .password-strength {
      margin: 2rem 0;
    }
    
    .strength-meter {
      height: 5px;
      background: #ecf0f1;
      border-radius: 5px;
      margin: 0.5rem 0;
      overflow: hidden;
    }
    
    .strength-fill {
      height: 100%;
      width: 0%;
      transition: width 0.3s ease;
    }
    
    .password-input:valid ~ .strength-meter .strength-fill {
      width: 100%;
      background: #2ecc71;
    }
    
    .password-input:invalid:not(:focus):not(:placeholder-shown) ~ .strength-meter .strength-fill {
      width: 33%;
      background: #e74c3c;
    }
    
    .password-input:placeholder-shown ~ .strength-meter .strength-fill {
      width: 0%;
    }
    
    /* Multi-step Form */
    .multi-step-form {
      position: relative;
    }
    
    .form-step {
      display: none;
    }
    
    .form-step:first-child {
      display: block;
    }
    
    .step-indicator {
      display: flex;
      justify-content: space-between;
      margin-bottom: 2rem;
    }
    
    .step {
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background: #bdc3c7;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
    }
    
    .step.active {
      background: #3498db;
    }
    
    .step.completed {
      background: #2ecc71;
    }
    
    .nav-buttons {
      display: flex;
      gap: 1rem;
      margin-top: 2rem;
    }
    
    .code-example {
      background: #2c3e50;
      color: white;
      padding: 1rem;
      border-radius: 10px;
      margin-top: 1rem;
      font-family: monospace;
      font-size: 0.8rem;
    }
    
    @media (max-width: 768px) {
      .examples-grid {
        grid-template-columns: 1fr;
      }
      
      .header h1 {
        font-size: 2rem;
      }
      
      .filter-options {
        flex-direction: column;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>๐Ÿš€ Practical Form Examples</h1>
      <p>Real-world form implementations using pseudo-classes</p>
    </div>
    
    <div class="examples-grid">
      <!-- Registration Form -->
      <div class="example-card">
        <h3>๐Ÿ“ Registration Form</h3>
        <form class="registration-form">
          <div class="form-group">
            <label for="regEmail">Email:</label>
            <input type="email" id="regEmail" required placeholder="Enter your email">
          </div>
          <div class="form-group">
            <label for="regPassword">Password:</label>
            <input type="password" id="regPassword" required minlength="6" placeholder="Enter password">
          </div>
          <div class="form-group">
            <label for="regConfirm">Confirm Password:</label>
            <input type="password" id="regConfirm" required placeholder="Confirm password">
          </div>
          <button type="submit" class="submit-btn">Register</button>
        </form>
        <div class="code-example">
          input:valid { border-color: #2ecc71; }
          input:invalid:not(:focus) { border-color: #e74c3c; }
          button:disabled { opacity: 0.6; cursor: not-allowed; }
        </div>
      </div>
      
      <!-- Survey Form -->
      <div class="example-card">
        <h3>๐Ÿ“Š Survey Form</h3>
        <form class="survey-form">
          <div class="question">
            <label>How satisfied are you with our service?</label>
            <div class="options-group">
              <label class="option-label">
                <input type="radio" name="satisfaction" value="very-satisfied" required>
                <span>Very Satisfied</span>
              </label>
              <label class="option-label">
                <input type="radio" name="satisfaction" value="satisfied">
                <span>Satisfied</span>
              </label>
              <label class="option-label">
                <input type="radio" name="satisfaction" value="neutral">
                <span>Neutral</span>
              </label>
              <label class="option-label">
                <input type="radio" name="satisfaction" value="unsatisfied">
                <span>Unsatisfied</span>
              </label>
            </div>
          </div>
        </form>
        <div class="code-example">
          .option-label:has(input:checked) {
            border-color: #2ecc71;
            background: rgba(46, 204, 113, 0.1);
          }
        </div>
      </div>
      
      <!-- Search Filter -->
      <div class="example-card">
        <h3>๐Ÿ” Search Filter</h3>
        <div class="search-filter">
          <input type="text" placeholder="Search products..." style="width: 100%; padding: 1rem; border: 2px solid #bdc3c7; border-radius: 8px; margin-bottom: 1rem;">
          <div class="filter-options">
            <label class="filter-btn">
              <input type="checkbox" name="category" value="electronics" hidden>
              Electronics
            </label>
            <label class="filter-btn">
              <input type="checkbox" name="category" value="clothing" hidden>
              Clothing
            </label>
            <label class="filter-btn">
              <input type="checkbox" name="category" value="books" hidden>
              Books
            </label>
            <label class="filter-btn">
              <input type="checkbox" name="category" value="home" hidden>
              Home
            </label>
          </div>
        </div>
        <div class="code-example">
          .filter-btn:has(input:checked) {
            background: #3498db;
            color: white;
            border-color: #3498db;
          }
        </div>
      </div>
      
      <!-- Password Strength -->
      <div class="example-card">
        <h3>๐Ÿ” Password Strength Meter</h3>
        <div class="password-strength">
          <input type="password" class="password-input" placeholder="Enter password" required minlength="6" style="width: 100%; padding: 1rem; border: 2px solid #bdc3c7; border-radius: 8px;">
          <div class="strength-meter">
            <div class="strength-fill"></div>
          </div>
          <div style="font-size: 0.875rem; color: #7f8c8d; margin-top: 0.5rem;">
            Password must be at least 6 characters long
          </div>
        </div>
        <div class="code-example">
          .password-input:valid ~ .strength-meter .strength-fill {
            width: 100%;
            background: #2ecc71;
          }
        </div>
      </div>
    </div>
    
    <!-- Multi-step Form -->
    <div class="example-card">
      <h3>๐Ÿ”ข Multi-step Form</h3>
      <form class="multi-step-form">
        <div class="step-indicator">
          <div class="step active">1</div>
          <div class="step">2</div>
          <div class="step">3</div>
        </div>
        
        <div class="form-step">
          <h4>Personal Information</h4>
          <div class="form-group">
            <label for="firstName">First Name:</label>
            <input type="text" id="firstName" required>
          </div>
          <div class="form-group">
            <label for="lastName">Last Name:</label>
            <input type="text" id="lastName" required>
          </div>
        </div>
        
        <div class="nav-buttons">
          <button type="button" class="submit-btn" style="background: #95a5a6;">Previous</button>
          <button type="button" class="submit-btn">Next</button>
        </div>
      </form>
      <div class="code-example">
        .step.active { background: #3498db; }
        .step.completed { background: #2ecc71; }
      </div>
    </div>
  </div>
</body>
</html>

Best Practices & Accessibility

โœ… Do's

  • Use high contrast colors for validation states
  • Provide clear visual feedback for all interactions
  • Test with keyboard navigation
  • Use :focus styles for accessibility
  • Combine with ARIA attributes when needed
  • Test across different devices and browsers

โŒ Don'ts

  • Don't rely solely on color for validation
  • Avoid removing default focus outlines completely
  • Don't make forms too complex with excessive states
  • Avoid using pseudo-classes for critical functionality
  • Don't ignore browser support limitations
  • Avoid overwhelming users with too much feedback

๐ŸŽฏ Browser Support Guide

Well Supported:

  • :focus, :hover, :active
  • :checked, :disabled
  • :valid, :invalid
  • :required, :optional
  • :first-child, :last-child

Limited Support:

  • :user-valid, :user-invalid
  • :placeholder-shown (older browsers)
  • :focus-visible (newer feature)
  • :blank (experimental)

Ready to Build Better Forms? ๐Ÿ“

Experiment with form pseudo-classes and create interactive, accessible forms that provide immediate feedback to users. From simple validation to complex multi-step forms, these techniques will elevate your form design.

< PreviousNext >