Forms
A complete guide to inputs, controls, layout, sizing, states and validation. Every example reacts to the style / dark / RTL controls above.
Anatomy of a field
Wrap each control in .field. Pair it with .label, optional .help text, and a hidden .error-text that appears on invalid input. .field stacks these with consistent spacing.
<div class="field">
<label class="label" for="name">Full name</label>
<input class="input" id="name" placeholder="Jane Doe">
<span class="help">As it appears on your ID.</span>
</div>
Text inputs
The .input class works on every text-like type. Bare <input> is also styled in classless mode.
<input class="input" type="text" placeholder="Text">
<input class="input" type="email" placeholder="Email">
<input class="input" type="date">
Textarea & Select
<textarea class="textarea" placeholder="Your message…"></textarea>
<select class="select">
<option>Free</option><option>Pro</option>
</select>
Sizes
Add .input-sm / .input-lg (and .select-sm / .select-lg).
<input class="input input-sm" placeholder="Small">
<input class="input" placeholder="Default">
<input class="input input-lg" placeholder="Large">
States
Disabled and read-only are handled natively; valid / invalid use the validation hooks below.
<input class="input" value="Disabled" disabled>
<input class="input" value="Read-only" readonly>
<input class="input is-valid" value="Looks good">
<input class="input is-invalid" value="Something off">
Checkbox, Radio & Switch
Native controls themed with accent-color, so they match every style automatically.
<div class="check"><input type="checkbox" id="c1"><label for="c1">Subscribe</label></div>
<div class="check"><input type="radio" name="plan" id="r1"><label for="r1">Monthly</label></div>
<label class="switch"><span>Notifications</span><input type="checkbox"><span class="track"></span></label>
File upload
<input type="file">
Input group
Join inputs with leading/trailing addons or buttons using .input-group + .input-addon. Radii and borders are handled on the ends, and it mirrors correctly in RTL.
<div class="input-group">
<span class="input-addon">@</span>
<input class="input" placeholder="username">
</div>
<div class="input-group">
<input class="input" placeholder="Search…">
<button class="btn btn-primary">Go</button>
</div>
Validation
LombokCSS layers two validation systems so you can use whichever fits:
1. Native, zero-JS
With required / type constraints, the browser sets :user-invalid after the user interacts. .field:has(:user-invalid) reveals the .error-text and hides .help automatically — no script. Type a bad email and click away:
<div class="field">
<label class="label" for="email">Email</label>
<input class="input" id="email" type="email" required>
<span class="help">We never share it.</span>
<span class="error-text">Please enter a valid email address.</span>
</div>
2. Manual hook
When validating in JS (e.g. server response), toggle .is-invalid / .is-valid on the control, or .is-invalid on the .field to force the error text open.
// after a failed server check
field.classList.add("is-invalid"); // shows .error-text
input.classList.add("is-invalid"); // red border + focus ring
// on success
input.classList.replace("is-invalid", "is-valid");
<div class="field is-invalid">
<input class="input is-invalid" value="EXPIRED2023">
<span class="error-text">This coupon has expired.</span>
</div>
Form layout
Compose multi-column forms with the grid utilities — no special form-grid classes needed.
<form class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="field">…first name…</div>
<div class="field">…last name…</div>
<div class="field col-span-full">…address…</div>
</form>
Accessibility notes
Always pair a <label for> with each control (or wrap the control in the label). Inputs show a visible :focus-visible ring derived from --lc-ring. For custom error messaging, link the message with aria-describedby and set aria-invalid="true" when you toggle the manual hook.