Starting Point
v0.33.0

Search documentation

Search for a page and jump to it.

Start typing to search...
Go to Page
escClose

Field

The field wraps a form control with its label, description, and error message, and lines everything up for you. It works around any control: inputs, selects, textareas, checkboxes, switches, and more.

<form class="field-group w-full max-w-md">
  <fieldset class="field-set">
    <legend class="field-legend">Payment Method</legend>
    <p class="field-description">All transactions are secure and encrypted</p>
    <div class="field-group">
      <div class="field">
        <label class="label" for="checkout-card-name">Name on Card</label>
        <input class="input" id="checkout-card-name" placeholder="Evil Rabbit" required />
      </div>
      <div class="field">
        <label class="label" for="checkout-card-number">Card Number</label>
        <input class="input" id="checkout-card-number" placeholder="1234 5678 9012 3456" required />
        <p class="field-description">Enter your 16-digit card number</p>
      </div>
      <div class="grid grid-cols-3 gap-4">
        <div class="field">
          <label class="label" for="checkout-exp-month">Month</label>
          <select class="select" id="checkout-exp-month">
            <option value="">MM</option>
            <option>01</option>
            <option>02</option>
            <option>03</option>
            <option>04</option>
            <option>05</option>
            <option>06</option>
            <option>07</option>
            <option>08</option>
            <option>09</option>
            <option>10</option>
            <option>11</option>
            <option>12</option>
          </select>
        </div>
        <div class="field">
          <label class="label" for="checkout-exp-year">Year</label>
          <select class="select" id="checkout-exp-year">
            <option value="">YYYY</option>
            <option>2024</option>
            <option>2025</option>
            <option>2026</option>
            <option>2027</option>
            <option>2028</option>
            <option>2029</option>
          </select>
        </div>
        <div class="field">
          <label class="label" for="checkout-cvv">CVV</label>
          <input class="input" id="checkout-cvv" placeholder="123" required />
        </div>
      </div>
    </div>
  </fieldset>
  <div class="field-separator"></div>
  <fieldset class="field-set">
    <legend class="field-legend">Billing Address</legend>
    <p class="field-description">
      The billing address associated with your payment method
    </p>
    <div class="field-group">
      <div class="field field-horizontal">
        <input type="checkbox" class="checkbox" id="checkout-same-as-shipping" checked />
        <label class="label font-normal" for="checkout-same-as-shipping">
          Same as shipping address
        </label>
      </div>
    </div>
  </fieldset>
  <fieldset class="field-set">
    <div class="field-group">
      <div class="field">
        <label class="label" for="checkout-comments">Comments</label>
        <textarea class="textarea resize-none" id="checkout-comments" placeholder="Add any additional comments"></textarea>
      </div>
    </div>
  </fieldset>
  <div class="field field-horizontal">
    <button type="submit" class="btn">Submit</button>
    <button type="button" class="btn btn-outline">Cancel</button>
  </div>
</form>

Usage

Add the field class to a wrapper and put the label, control, and supporting text inside. Fields stack vertically by default; group several with field-group.

ClassDescription
fieldAdd to the wrapper around a label, control, and supporting text
field-horizontal field-responsiveAdd to field to lay it out in a row, always or from the md container size
field-contentAdd to a block holding a title and description inside a field
field-titleAdd to a heading inside field-content
field-descriptionAdd to a paragraph with supporting text
field-errorAdd to a paragraph with a validation message
field-groupAdd to a container stacking several fields
field-setAdd to a <fieldset> wrapping related fields
field-legendAdd to the <legend> of a field set
field-legend-labelAdd to field-legend for a label-sized legend
field-separatorAdd to a divider between fields; put text in a <span> inside
<div class="field">
  <label class="label" for="my-input">Label</label>
  <input class="input" id="my-input" />
  <p class="field-description">Description</p>
</div>

Examples

Input

Stack the label, control, and description in any order; the field spaces them consistently.

<fieldset class="field-set">
  <div class="field-group">
    <div class="field">
      <label class="label" for="field-username">Username</label>
      <input class="input" id="field-username" type="text" placeholder="Max Leiter" />
      <p class="field-description">Choose a unique username for your account.</p>
    </div>
    <div class="field">
      <label class="label" for="field-password">Password</label>
      <p class="field-description">Must be at least 8 characters long.</p>
      <input class="input" id="field-password" type="password" placeholder="••••••••" />
    </div>
  </div>
</fieldset>

Textarea

A textarea fields like any other control.

<fieldset class="field-set">
  <div class="field-group">
    <div class="field">
      <label class="label" for="field-feedback">Feedback</label>
      <textarea class="textarea" id="field-feedback" rows="4" placeholder="Your feedback helps us improve..."></textarea>
      <p class="field-description">Share your thoughts about our service.</p>
    </div>
  </div>
</fieldset>

Select

A select with a label and supporting text.

<div class="field">
  <label class="label" for="field-department">Department</label>
  <select class="select" id="field-department">
    <option value="">Choose department</option>
    <option>Engineering</option>
    <option>Design</option>
    <option>Marketing</option>
    <option>Sales</option>
    <option>Customer Support</option>
    <option>Human Resources</option>
    <option>Finance</option>
    <option>Operations</option>
  </select>
  <p class="field-description">Select your department or area of work.</p>
</div>

Slider

Fields also wrap controls without a <label> element, like a slider titled with a field-title.

<div class="field">
  <span class="field-title">Budget</span>
  <p class="field-description">
    Set your maximum budget ($<span class="font-medium tabular-nums" data-sp-slider-value="field-budget">500</span>).
  </p>
  <input type="range" class="slider mt-2" id="field-budget" min="0" max="1000" step="10" value="500" style="--val: 50%" aria-label="Maximum budget" />
</div>

Fieldset

Group related fields in a field-set with a field-legend so they are announced together.

<fieldset class="field-set">
  <legend class="field-legend">Address Information</legend>
  <p class="field-description">We need your address to deliver your order.</p>
  <div class="field-group">
    <div class="field">
      <label class="label" for="field-street">Street Address</label>
      <input class="input" id="field-street" type="text" placeholder="123 Main St" />
    </div>
    <div class="grid grid-cols-2 gap-4">
      <div class="field">
        <label class="label" for="field-city">City</label>
        <input class="input" id="field-city" type="text" placeholder="New York" />
      </div>
      <div class="field">
        <label class="label" for="field-zip">Postal Code</label>
        <input class="input" id="field-zip" type="text" placeholder="90502" />
      </div>
    </div>
  </div>
</fieldset>

Checkbox

Horizontal fields lay out checkboxes, with a field-separator dividing sections.

<div class="field-group">
  <fieldset class="field-set">
    <legend class="field-legend field-legend-label">Show these items on the desktop</legend>
    <p class="field-description">Select the items you want to show on the desktop.</p>
    <div class="field-group gap-3">
      <div class="field field-horizontal">
        <input type="checkbox" class="checkbox" id="finder-pref-hard-disks" />
        <label class="label font-normal" for="finder-pref-hard-disks">Hard disks</label>
      </div>
      <div class="field field-horizontal">
        <input type="checkbox" class="checkbox" id="finder-pref-external-disks" />
        <label class="label font-normal" for="finder-pref-external-disks">External disks</label>
      </div>
      <div class="field field-horizontal">
        <input type="checkbox" class="checkbox" id="finder-pref-cds-dvds" />
        <label class="label font-normal" for="finder-pref-cds-dvds">CDs, DVDs, and iPods</label>
      </div>
      <div class="field field-horizontal">
        <input type="checkbox" class="checkbox" id="finder-pref-connected-servers" />
        <label class="label font-normal" for="finder-pref-connected-servers">Connected servers</label>
      </div>
    </div>
  </fieldset>
  <div class="field-separator"></div>
  <div class="field field-horizontal">
    <input type="checkbox" class="checkbox" id="finder-pref-sync-folders" checked />
    <div class="field-content">
      <label class="label" for="finder-pref-sync-folders">Sync Desktop &amp; Documents folders</label>
      <p class="field-description">
        Your Desktop &amp; Documents folders are being synced with iCloud
        Drive. You can access them from other devices.
      </p>
    </div>
  </div>
</div>

Radio

A radio group in a field set, one horizontal field per option.

<fieldset class="field-set">
  <legend class="field-legend field-legend-label">Subscription Plan</legend>
  <p class="field-description">Yearly and lifetime plans offer significant savings.</p>
  <div class="field-group gap-3">
    <div class="field field-horizontal">
      <input type="radio" class="radio" id="plan-monthly" name="plan" checked />
      <label class="label font-normal" for="plan-monthly">Monthly ($9.99/month)</label>
    </div>
    <div class="field field-horizontal">
      <input type="radio" class="radio" id="plan-yearly" name="plan" />
      <label class="label font-normal" for="plan-yearly">Yearly ($99.99/year)</label>
    </div>
    <div class="field field-horizontal">
      <input type="radio" class="radio" id="plan-lifetime" name="plan" />
      <label class="label font-normal" for="plan-lifetime">Lifetime ($299.99)</label>
    </div>
  </div>
</fieldset>

Switch

A horizontal field puts a switch beside its label.

<div class="field field-horizontal">
  <input type="checkbox" role="switch" class="switch" id="field-2fa" />
  <label class="label" for="field-2fa">Multi-factor authentication</label>
</div>

Choice card

Wrap a horizontal field in a label and the whole card becomes clickable, tinting itself while checked.

<div class="field-group">
  <fieldset class="field-set">
    <legend class="field-legend field-legend-label">Compute Environment</legend>
    <p class="field-description">Select the compute environment for your cluster.</p>
    <div class="field-group gap-3">
      <label class="label">
        <div class="field field-horizontal">
          <div class="field-content">
            <span class="field-title">Kubernetes</span>
            <p class="field-description">Run GPU workloads on a K8s cluster.</p>
          </div>
          <input type="radio" class="radio" name="field-compute" checked />
        </div>
      </label>
      <label class="label">
        <div class="field field-horizontal">
          <div class="field-content">
            <span class="field-title">Virtual Machine</span>
            <p class="field-description">Access a cluster to run GPU workloads.</p>
          </div>
          <input type="radio" class="radio" name="field-compute" />
        </div>
      </label>
    </div>
  </fieldset>
</div>

Field group

Stack sections of fields with a field-group and divide them with separators.

<div class="field-group">
  <fieldset class="field-set">
    <legend class="field-legend field-legend-label">Responses</legend>
    <p class="field-description">
      Get notified when ChatGPT responds to requests that take time, like
      research or image generation.
    </p>
    <div class="field-group gap-3">
      <div class="field field-horizontal">
        <input type="checkbox" class="checkbox" id="notif-push" checked disabled />
        <label class="label font-normal" for="notif-push">Push notifications</label>
      </div>
    </div>
  </fieldset>
  <div class="field-separator"></div>
  <fieldset class="field-set">
    <legend class="field-legend field-legend-label">Tasks</legend>
    <p class="field-description">
      Get notified when tasks you've created have updates.
      <a href="#">Manage tasks</a>
    </p>
    <div class="field-group gap-3">
      <div class="field field-horizontal">
        <input type="checkbox" class="checkbox" id="notif-push-tasks" />
        <label class="label font-normal" for="notif-push-tasks">Push notifications</label>
      </div>
      <div class="field field-horizontal">
        <input type="checkbox" class="checkbox" id="notif-email-tasks" />
        <label class="label font-normal" for="notif-email-tasks">Email notifications</label>
      </div>
    </div>
  </fieldset>
</div>

Responsive

Add field-responsive and the field stacks on narrow containers and becomes a row from the md container size. Resize the preview to see it switch.

<form class="w-full max-w-lg">
  <fieldset class="field-set">
    <legend class="field-legend">Profile</legend>
    <p class="field-description">Fill in your profile information.</p>
    <div class="field-group">
      <div class="field field-responsive">
        <div class="field-content">
          <label class="label" for="field-resp-name">Name</label>
          <p class="field-description">Provide your full name for identification</p>
        </div>
        <input class="input" id="field-resp-name" placeholder="Evil Rabbit" required />
      </div>
      <div class="field field-responsive">
        <button type="submit" class="btn">Submit</button>
        <button type="button" class="btn btn-outline">Cancel</button>
      </div>
    </div>
  </fieldset>
</form>

Invalid

Set aria-invalid on the control for the error ring and put the message in a field-error.

<div class="field">
  <label class="label" for="field-invalid-email">Email</label>
  <input class="input" id="field-invalid-email" type="email" value="not-an-email" aria-invalid="true" />
  <p class="field-error">Enter a valid email address.</p>
</div>

RTL

Add dir="rtl" to any parent element, typically <html>, to render right-to-left. See the RTL guide for details.

<div id="field-rtl-demo" dir="rtl" class="w-full">
  <form class="field-group">
    <fieldset class="field-set">
      <legend class="field-legend" data-i18n="paymentMethod">طريقة الدفع</legend>
      <p class="field-description" data-i18n="secureTransactions">جميع المعاملات آمنة ومشفرة</p>
      <div class="field-group">
        <div class="field">
          <label class="label" for="field-rtl-card-name" data-i18n="nameOnCard">الاسم على البطاقة</label>
          <input class="input" id="field-rtl-card-name" placeholder="Evil Rabbit" required />
        </div>
        <div class="field">
          <label class="label" for="field-rtl-card-number" data-i18n="cardNumber">رقم البطاقة</label>
          <input class="input" id="field-rtl-card-number" placeholder="1234 5678 9012 3456" required />
          <p class="field-description" data-i18n="cardNumberDescription">أدخل رقم البطاقة المكون من 16 رقمًا</p>
        </div>
        <div class="grid grid-cols-3 gap-4">
          <div class="field">
            <label class="label" for="field-rtl-exp-month" data-i18n="month">الشهر</label>
            <select class="select" id="field-rtl-exp-month">
              <option value="" data-i18n="monthPlaceholder">ش.ش</option>
              <option value="01" data-i18n="month01">٠١</option>
              <option value="02" data-i18n="month02">٠٢</option>
              <option value="03" data-i18n="month03">٠٣</option>
              <option value="04" data-i18n="month04">٠٤</option>
              <option value="05" data-i18n="month05">٠٥</option>
              <option value="06" data-i18n="month06">٠٦</option>
              <option value="07" data-i18n="month07">٠٧</option>
              <option value="08" data-i18n="month08">٠٨</option>
              <option value="09" data-i18n="month09">٠٩</option>
              <option value="10" data-i18n="month10">١٠</option>
              <option value="11" data-i18n="month11">١١</option>
              <option value="12" data-i18n="month12">١٢</option>
            </select>
          </div>
          <div class="field">
            <label class="label" for="field-rtl-exp-year" data-i18n="year">السنة</label>
            <select class="select" id="field-rtl-exp-year">
              <option value="">YYYY</option>
              <option>2024</option>
              <option>2025</option>
              <option>2026</option>
              <option>2027</option>
              <option>2028</option>
              <option>2029</option>
            </select>
          </div>
          <div class="field">
            <label class="label" for="field-rtl-cvv" data-i18n="cvv">CVV</label>
            <input class="input" id="field-rtl-cvv" placeholder="123" required />
          </div>
        </div>
      </div>
    </fieldset>
    <div class="field-separator"></div>
    <fieldset class="field-set">
      <legend class="field-legend" data-i18n="billingAddress">عنوان الفوترة</legend>
      <p class="field-description" data-i18n="billingAddressDescription">عنوان الفوترة المرتبط بطريقة الدفع الخاصة بك</p>
      <div class="field-group">
        <div class="field field-horizontal">
          <input type="checkbox" class="checkbox" id="field-rtl-shipping" checked />
          <label class="label font-normal" for="field-rtl-shipping" data-i18n="sameAsShipping">نفس عنوان الشحن</label>
        </div>
      </div>
    </fieldset>
    <fieldset class="field-set">
      <div class="field-group">
        <div class="field">
          <label class="label" for="field-rtl-comments" data-i18n="comments">تعليقات</label>
          <textarea class="textarea resize-none" id="field-rtl-comments" placeholder="أضف أي تعليقات إضافية" data-i18n-placeholder="commentsPlaceholder"></textarea>
        </div>
      </div>
    </fieldset>
    <div class="field field-horizontal">
      <button type="submit" class="btn" data-i18n="submit">إرسال</button>
      <button type="button" class="btn btn-outline" data-i18n="cancel">إلغاء</button>
    </div>
  </form>
</div>
 
<script>
  const translations = {
    ar: { dir: "rtl", paymentMethod: "طريقة الدفع", secureTransactions: "جميع المعاملات آمنة ومشفرة", nameOnCard: "الاسم على البطاقة", cardNumber: "رقم البطاقة", cardNumberDescription: "أدخل رقم البطاقة المكون من 16 رقمًا", month: "الشهر", year: "السنة", cvv: "CVV", monthPlaceholder: "ش.ش", month01: "٠١", month02: "٠٢", month03: "٠٣", month04: "٠٤", month05: "٠٥", month06: "٠٦", month07: "٠٧", month08: "٠٨", month09: "٠٩", month10: "١٠", month11: "١١", month12: "١٢", billingAddress: "عنوان الفوترة", billingAddressDescription: "عنوان الفوترة المرتبط بطريقة الدفع الخاصة بك", sameAsShipping: "نفس عنوان الشحن", comments: "تعليقات", commentsPlaceholder: "أضف أي تعليقات إضافية", submit: "إرسال", cancel: "إلغاء" },
    he: { dir: "rtl", paymentMethod: "אמצעי תשלום", secureTransactions: "כל העסקאות מאובטחות ומוצפנות", nameOnCard: "שם על הכרטיס", cardNumber: "מספר כרטיס", cardNumberDescription: "הזן את מספר הכרטיס בן 16 הספרות שלך", month: "חודש", year: "שנה", cvv: "CVV", monthPlaceholder: "MM", month01: "01", month02: "02", month03: "03", month04: "04", month05: "05", month06: "06", month07: "07", month08: "08", month09: "09", month10: "10", month11: "11", month12: "12", billingAddress: "כתובת חיוב", billingAddressDescription: "כתובת החיוב המשויכת לאמצעי התשלום שלך", sameAsShipping: "זהה לכתובת המשלוח", comments: "הערות", commentsPlaceholder: "הוסף הערות נוספות", submit: "שלח", cancel: "בטל" },
    en: { dir: "ltr", paymentMethod: "Payment Method", secureTransactions: "All transactions are secure and encrypted", nameOnCard: "Name on Card", cardNumber: "Card Number", cardNumberDescription: "Enter your 16-digit card number", month: "Month", year: "Year", cvv: "CVV", monthPlaceholder: "MM", month01: "01", month02: "02", month03: "03", month04: "04", month05: "05", month06: "06", month07: "07", month08: "08", month09: "09", month10: "10", month11: "11", month12: "12", billingAddress: "Billing Address", billingAddressDescription: "The billing address associated with your payment method", sameAsShipping: "Same as shipping address", comments: "Comments", commentsPlaceholder: "Add any additional comments", submit: "Submit", cancel: "Cancel" },
  };
  window.addEventListener("message", (e) => {
    const t = translations[e.data?.lang];
    if (e.data?.type !== "sp-language" || !t) return;
    document.getElementById("field-rtl-demo").dir = t.dir;
    document.querySelectorAll("[data-i18n]").forEach((el) => {
      el.textContent = t[el.dataset.i18n];
    });
    document.querySelectorAll("[data-i18n-placeholder]").forEach((el) => {
      el.placeholder = t[el.dataset.i18nPlaceholder];
    });
  });
</script>