Form
Form groups with labels, validation states, helper text, addons, sections, and layout utilities.
Basic Form Group
Preview
<div class="form-group">
<label class="form-group-label">Email address</label>
<div class="form-group-control">
<input type="email" class="input" placeholder="you@example.com" />
</div>
<span class="form-group-helper">We'll never share your email.</span>
</div>
<div class="form-group">
<label class="form-group-label form-group-label-required">Password</label>
<div class="form-group-control">
<input type="password" class="input" placeholder="••••••••" />
</div>
</div> Requires: ux.min.css
<div class="flex flex-col gap-1 mb-4">
<label class="text-sm font-medium" style="color: color-mix(in oklch, var(--color-base-content) 60%, transparent)">Email address</label>
<div class="relative flex flex-col gap-1">
<input type="email" class="input" placeholder="you@example.com" />
</div>
<span class="text-xs text-base-content/40">We'll never share your email.</span>
</div>
<div class="flex flex-col gap-1 mb-4">
<label class="text-sm font-medium" style="color: color-mix(in oklch, var(--color-base-content) 60%, transparent)">Password <span class="font-semibold" style="color: var(--color-error)">*</span></label>
<div class="relative flex flex-col gap-1">
<input type="password" class="input" placeholder="••••••••" />
</div>
</div> Requires: tw.min.css
// No JavaScript required — pure CSS form styling Validation: Error State
Preview
Please enter a valid email address.
<div class="form-group form-group-has-error">
<label class="form-group-label">Email</label>
<div class="form-group-control">
<div class="form-group-input-wrapper">
<input type="email" class="input" value="invalid-email" />
<span class="form-group-icon form-group-icon-error">
<svg viewBox="0 0 20 20" fill="currentColor"><circle cx="10" cy="10" r="8"/></svg>
</span>
</div>
<div class="form-group-error" style="opacity:1; max-height:100px;">
<svg viewBox="0 0 20 20" fill="currentColor"><circle cx="10" cy="10" r="8"/></svg>
Please enter a valid email address.
</div>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col gap-1 mb-4">
<label class="text-sm font-medium" style="color: var(--color-error)">Email</label>
<div class="relative flex items-center">
<input type="email" class="input w-full" value="invalid-email" style="border-color: var(--color-error); background: color-mix(in oklch, var(--color-error) 3%, var(--color-base-100))" />
</div>
<span class="text-xs flex items-start gap-1" style="color: var(--color-error)">Please enter a valid email address.</span>
</div> Requires: tw.min.css
// Toggle error state by adding/removing .form-group-has-error
const group = document.querySelector('.form-group');
group.classList.add('form-group-has-error'); // show error
group.classList.remove('form-group-has-error'); // clear error Validation: Success State
Preview
Username is available!
<div class="form-group form-group-has-success">
<label class="form-group-label">Username</label>
<div class="form-group-control">
<div class="form-group-input-wrapper">
<input type="text" class="input" value="john_doe" />
<span class="form-group-icon form-group-icon-success">
<svg viewBox="0 0 20 20" fill="currentColor"><path d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"/></svg>
</span>
</div>
<div class="form-group-success" style="opacity:1; max-height:100px;">Username is available!</div>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col gap-1 mb-4">
<label class="text-sm font-medium" style="color: var(--color-success)">Username</label>
<div class="relative flex items-center">
<input type="text" class="input w-full" value="john_doe" style="border-color: var(--color-success); background: color-mix(in oklch, var(--color-success) 3%, var(--color-base-100))" />
</div>
<span class="text-xs" style="color: var(--color-success)">Username is available!</span>
</div> Requires: tw.min.css
// Toggle success with .form-group-has-success class Addons (Prefix / Suffix)
Preview
https://
.com
$
<div class="form-group">
<label class="form-group-label">Website</label>
<div class="form-group-control">
<div class="form-group-input-wrapper">
<span class="form-group-addon form-group-addon-start">https://</span>
<input type="url" class="input" placeholder="example.com" style="border-radius: 0;" />
<span class="form-group-addon form-group-addon-end">.com</span>
</div>
</div>
</div>
<div class="form-group">
<label class="form-group-label">Price</label>
<div class="form-group-control">
<div class="form-group-input-wrapper">
<span class="form-group-addon form-group-addon-start">$</span>
<input type="number" class="input" placeholder="0.00" style="border-radius: 0 var(--radius-field, 0.375rem) var(--radius-field, 0.375rem) 0;" />
</div>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col gap-1 mb-4">
<label class="text-sm font-medium text-base-content/60">Website</label>
<div class="flex items-center">
<span class="flex items-center px-2 bg-base-200 border border-base-300 border-r-0 text-base-content/60 text-sm rounded-l-field">https://</span>
<input type="url" class="input rounded-none" placeholder="example.com" />
<span class="flex items-center px-2 bg-base-200 border border-base-300 border-l-0 text-base-content/60 text-sm rounded-r-field">.com</span>
</div>
</div> Requires: tw.min.css
// No JavaScript required — pure CSS addons Horizontal Layout
Preview
<div class="form-group form-group-horizontal">
<label class="form-group-label">First name</label>
<div class="form-group-control">
<input type="text" class="input" placeholder="John" />
</div>
</div>
<div class="form-group form-group-horizontal">
<label class="form-group-label">Last name</label>
<div class="form-group-control">
<input type="text" class="input" placeholder="Doe" />
</div>
</div> Requires: ux.min.css
<div class="flex flex-row items-center gap-3 mb-4">
<label class="text-sm font-medium text-base-content/60 shrink-0 min-w-[120px]">First name</label>
<div class="flex-1">
<input type="text" class="input w-full" placeholder="John" />
</div>
</div>
<div class="flex flex-row items-center gap-3 mb-4">
<label class="text-sm font-medium text-base-content/60 shrink-0 min-w-[120px]">Last name</label>
<div class="flex-1">
<input type="text" class="input w-full" placeholder="Doe" />
</div>
</div> Requires: tw.min.css
// No JavaScript required — stacks vertically on mobile via CSS media query Form Row (Multi-column)
Preview
<div class="form-row">
<div class="form-group">
<label class="form-group-label">First name</label>
<div class="form-group-control">
<input type="text" class="input" placeholder="John" />
</div>
</div>
<div class="form-group">
<label class="form-group-label">Last name</label>
<div class="form-group-control">
<input type="text" class="input" placeholder="Doe" />
</div>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label class="form-group-label">Email</label>
<div class="form-group-control">
<input type="email" class="input" placeholder="you@example.com" />
</div>
</div>
<div class="form-group form-group-fixed">
<label class="form-group-label">Zip Code</label>
<div class="form-group-control">
<input type="text" class="input" placeholder="12345" />
</div>
</div>
</div> Requires: ux.min.css
<div class="flex gap-4 mb-4">
<div class="flex-1 flex flex-col gap-1">
<label class="text-sm font-medium text-base-content/60">First name</label>
<input type="text" class="input" placeholder="John" />
</div>
<div class="flex-1 flex flex-col gap-1">
<label class="text-sm font-medium text-base-content/60">Last name</label>
<input type="text" class="input" placeholder="Doe" />
</div>
</div> Requires: tw.min.css
// No JavaScript required — collapses to single column on mobile Form Section
Preview
<fieldset class="form-section">
<div class="form-section-header">
<h3 class="form-section-title">Personal Information</h3>
<p class="form-section-description">Fill in your personal details below.</p>
</div>
<div class="form-section-content">
<div class="form-group">
<label class="form-group-label">Full name</label>
<div class="form-group-control">
<input type="text" class="input" />
</div>
</div>
<div class="form-group">
<label class="form-group-label">Email</label>
<div class="form-group-control">
<input type="email" class="input" />
</div>
</div>
</div>
</fieldset> Requires: ux.min.css
<fieldset class="mb-8 p-0 border-none">
<div class="mb-4 pb-2 border-b border-base-300">
<h3 class="text-lg font-semibold text-base-content m-0 mb-1">Personal Information</h3>
<p class="text-sm text-base-content/60 m-0">Fill in your personal details below.</p>
</div>
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-1">
<label class="text-sm font-medium text-base-content/60">Full name</label>
<input type="text" class="input" />
</div>
<div class="flex flex-col gap-1">
<label class="text-sm font-medium text-base-content/60">Email</label>
<input type="email" class="input" />
</div>
</div>
</fieldset> Requires: tw.min.css
// No JavaScript required — pure CSS section styling Form Actions
Preview
<div class="form-actions">
<button class="btn">Cancel</button>
<button class="btn color-primary">Save Changes</button>
</div>
<div class="form-actions form-actions-between">
<button class="btn color-error">Delete</button>
<div class="flex gap-2">
<button class="btn">Cancel</button>
<button class="btn color-primary">Save</button>
</div>
</div> Requires: ux.min.css
<div class="flex gap-2 justify-end pt-4 mt-4 border-t border-base-300">
<button class="btn">Cancel</button>
<button class="btn color-primary">Save Changes</button>
</div>
<div class="flex gap-2 justify-between pt-4 mt-4 border-t border-base-300">
<button class="btn color-error">Delete</button>
<div class="flex gap-2">
<button class="btn">Cancel</button>
<button class="btn color-primary">Save</button>
</div>
</div> Requires: tw.min.css
// No JavaScript required — layout utilities Character Counter
Preview
Max 200 characters
0 / 200
85 / 100
<div class="form-group">
<label class="form-group-label">Bio</label>
<div class="form-group-control">
<textarea class="textarea" rows="3" maxlength="200" placeholder="Tell us about yourself..."></textarea>
<div class="form-group-footer">
<span class="form-group-helper">Max 200 characters</span>
<span class="form-group-counter">0 / 200</span>
</div>
</div>
</div>
<div class="form-group">
<label class="form-group-label">Description</label>
<div class="form-group-control">
<textarea class="textarea" rows="3" maxlength="100"></textarea>
<div class="form-group-footer">
<span class="form-group-counter form-group-counter-warning">85 / 100</span>
</div>
</div>
</div> Requires: ux.min.css
<div class="flex flex-col gap-1 mb-4">
<label class="text-sm font-medium text-base-content/60">Bio</label>
<textarea class="textarea" rows="3" maxlength="200" placeholder="Tell us about yourself..."></textarea>
<div class="flex justify-between items-center gap-2">
<span class="text-xs text-base-content/40">Max 200 characters</span>
<span class="text-xs text-base-content/40 text-right ml-auto">0 / 200</span>
</div>
</div> Requires: tw.min.css
// Update counter on input:
const textarea = document.querySelector('textarea');
const counter = document.querySelector('.form-group-counter');
textarea.addEventListener('input', () => {
counter.textContent = textarea.value.length + ' / ' + textarea.maxLength;
}); Disabled State
Preview
<div class="form-group form-group-disabled">
<label class="form-group-label">Disabled field</label>
<div class="form-group-control">
<input type="text" class="input" value="Cannot edit this" disabled />
</div>
<span class="form-group-helper">This field is locked.</span>
</div> Requires: ux.min.css
<div class="flex flex-col gap-1 mb-4 opacity-50 pointer-events-none">
<label class="text-sm font-medium text-base-content/60">Disabled field</label>
<input type="text" class="input" value="Cannot edit this" disabled />
<span class="text-xs text-base-content/40">This field is locked.</span>
</div> Requires: tw.min.css
// No JavaScript required — uses .form-group-disabled class Glass Variant
Preview
<div class="p-6 rounded-box" style="background: linear-gradient(135deg, var(--color-primary), var(--color-info));">
<div class="form-group glass">
<label class="form-group-label" style="color: rgba(255,255,255,0.8)">Search</label>
<div class="form-group-control">
<input type="text" class="input" placeholder="Search items..." />
</div>
</div>
</div> Requires: ux.min.css
<div class="p-6 rounded-box" style="background: linear-gradient(135deg, var(--color-primary), var(--color-info));">
<div class="flex flex-col gap-1 mb-4">
<label class="text-sm font-medium" style="color: rgba(255,255,255,0.8)">Search</label>
<input type="text" class="input glass" placeholder="Search items..." />
</div>
</div> Requires: tw.min.css
// No JavaScript required — .glass class on .form-group applies glass to inputs