Forms

Forms are one of the most critical parts of any interface. The FrontAlign form system is designed as a complete, production-ready engine: clean base controls, semantic validation states, floating labels, input groups, icon slots, file controls, switches, range sliders, and server feedback patterns — all driven by design tokens.

The goal is simple: write predictable HTML, get a professional UI layer in return.

Key Features

FrontAlign forms are built on a unified visual language. Every control — input, textarea, select, file, range, checkbox, radio, and switch — shares the same token-driven style, so they look right next to each other without extra effort.

Validation works two ways. Native mode adds .validated to the form after submit and lets browser :valid / :invalid states drive the UI. Manual mode lets you apply .input-invalid, .select-valid, .checkbox-invalid, and similar classes directly from JavaScript or server logic — useful for async checks, server-side responses, and staged forms.

Validation icons appear automatically on text inputs, textareas, selects, and file fields in valid and invalid states. For select fields, the dropdown arrow and the validation icon coexist cleanly.

Server feedback is supported through .form-feedback.from-server with .with-success and .with-error modifiers, so backend responses integrate without relying on HTML5 validation at all.

Input groups combine addons, buttons, selects, and inputs in one seamless horizontal unit. Icon inputs place icons or action buttons inside the input bounds without breaking layout. Floating labels work with inputs, textareas, selects, autofill, and validation colors.

Size variantsis-medium, and is-large — are available across every control type.

Dark mode is fully supported. All colors use FrontAlign tokens such as --form-control, --form-control-text, --form-control-border, --accent, --success, and --danger.

Getting Started

Wrap every control in .group. Place .form-label above the control and optional helper text below using .form-text.

<div class="group">
  <label class="form-label" for="email">Email address</label>
  <input
    class="form-input"
    id="email"
    type="email"
    placeholder="you@example.com"
  />
  <small class="form-text">We will never share your email.</small>
</div>
We will never share your email.

Control Reference

ControlClassPurpose
Input.form-input

Text, email, password, search, number, date, color, and other input types.

Textarea.form-textarea

Multi-line text area with vertical resize and optional height helpers.

Select.form-select

Native select with custom arrow, focus ring, multiple support, and validation icons.

File.form-file

Native file input or hidden file input inside a custom .group-file upload button.

Range.form-range

Token-styled slider with filled track via --range-track-fill.

Checkbox.form-checkbox

Custom checkbox with checked SVG, focus ring, disabled state, and validation.

Radio.form-radioCustom radio button with accent-colored selected state.
Switch.group-switch > .form-checkboxToggle switch built on a checkbox input with animated thumb.

Wrapper Reference

WrapperPurpose
.group

Standard vertical spacing wrapper for a label + control + feedback stack.

.group-input

Horizontal group that fuses inputs, addons, selects, and buttons into one unit.

.group-input-icon

Positions start and end icon slots inside an input without affecting its layout.

.group-checkbox

Spacing and alignment wrapper for checkbox controls and their labels.

.group-radio

Spacing and alignment wrapper for radio controls and their labels.

.group-switchWrapper that transforms a checkbox into a toggle switch.
.group-file

Custom upload button pattern using a hidden file input and a styled label.

.group-range

For the use of modern range form elements with a JS backend label.

.floating-label

Modifier on .group that enables floating label behavior on inputs, textareas, and selects.

Text Input

.form-input handles every text-like input type: text, email, password, search, number, date, datetime-local, month, time, url, tel, and color.

<div class="group">
  <label class="form-label" for="name">Full name</label>
  <input
    class="form-input"
    id="name"
    type="text"
    placeholder="Enter full name"
  />
</div>

<div class="group">
  <label class="form-label" for="email">Email address</label>
  <input
    class="form-input"
    id="email"
    type="email"
    placeholder="you@example.com"
  />
</div>

<div class="group">
  <label class="form-label" for="password">Password</label>
  <input
    class="form-input"
    id="password"
    type="password"
    placeholder="Enter password"
  />
</div>

<div class="group">
  <label class="form-label" for="date">Date</label>
  <input class="form-input" id="date" type="date" />
</div>

Textarea

.form-textarea is the multi-line counterpart to .form-input. It resizes vertically by default. Use size-md or size-lg when the field needs more vertical space.

<!-- Default height -->
<div class="group">
  <label class="form-label" for="message">Message</label>
  <textarea
    class="form-textarea"
    id="message"
    placeholder="Write your message"
  ></textarea>
</div>

<!-- Medium height -->
<div class="group">
  <label class="form-label" for="bio">Bio</label>
  <textarea
    class="form-textarea size-md"
    id="bio"
    placeholder="Short profile bio"
  ></textarea>
</div>

<!-- Large height -->
<div class="group">
  <label class="form-label" for="description">Description</label>
  <textarea
    class="form-textarea size-lg"
    id="description"
    placeholder="Detailed description"
  ></textarea>
</div>

Native Select

.form-select applies a custom dropdown arrow, token-based background, focus ring, and validation state support on top of the native <select> element.

<div class="group">
  <label class="form-label" for="framework">Framework</label>
  <select class="form-select" id="framework">
    <option value="">Select</option>
    <option>Angular</option>
    <option>Vue</option>
    <option>React</option>
  </select>
</div>

Multiple Select

When multiple or size is used, the native arrow is removed automatically so it does not conflict with the scrollable list.

<div class="group">
  <label class="form-label" for="skills">Skills</label>
  <select class="form-select" id="skills" multiple size="4">
    <option>UI Design</option>
    <option>Frontend</option>
    <option>Backend</option>
    <option>DevOps</option>
  </select>
</div>

Color Input

Use type="color" on .form-input for a token-styled color picker. The swatch inside is automatically rounded to match the framework's radius scale.

<div class="group">
  <label class="form-label" for="brand-color">Brand color</label>
  <input class="form-input" id="brand-color" type="color" value="#3b82f6" />
</div>

FrontAlign