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.
<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 & Documents folders</label>
<p class="field-description">
Your Desktop & 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.
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.
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>