Form Layout
Organize form fields with structured layouts using spacing utilities, grid systems, and responsive patterns.
Overview
Chassis CSS provides multiple layout options for organizing form elements. Since Chassis CSS applies display: block and width: 100% to form inputs by default, forms naturally stack vertically. You can implement various layout patterns using the classes and techniques described below.
Every group of form fields should reside in a <form> element. While Chassis CSS doesn't apply default styling to the <form> element itself, it's important to use proper semantic HTML:
- Always specify button types within forms (
type="submit",type="button", etc.) as browsers default totype="submit" - Use the
<fieldset>and<legend>elements to group related form controls - Include appropriate ARIA attributes and labels for accessibility
- For advanced form requirements, consult the MDN form documentation
Spacing utilities
The simplest way to add structure to forms is with spacing utilities. These utilities provide consistent spacing between form elements, including labels, controls, help text, and validation messages.
For consistency, Chassis CSS recommends:
- Using
margin-bottomutilities (mb-*) for vertical spacing - Applying the same spacing size throughout a single form
- Using the
mediumspacing value as a default starting point
<div class="mb-medium">
<label for="formGroupExampleInput" class="form-label">Example label</label>
<input type="text" class="form-input" id="formGroupExampleInput" placeholder="Example input placeholder">
</div>
<div class="mb-medium">
<label for="formGroupExampleInput2" class="form-label">Another label</label>
<input type="text" class="form-input" id="formGroupExampleInput2" placeholder="Another input placeholder">
</div> Grid-based layouts
Chassis CSS's grid system provides powerful options for creating complex form layouts with multiple columns, varied widths, and precise alignment control. The grid system offers several key advantages for form layouts:
- Responsive layouts that adapt to different screen sizes
- Flexible column configurations that can be mixed and matched
- Consistent spacing through the gutter system
- Vertical alignment control for aligning form elements
- Nesting capabilities for complex form structures
Note: Grid-based form layouts require the
$enable-grid-classesSass variable to be enabled (enabled by default).
Basic grid layout
Use the .row and .col classes to create evenly-spaced columns within a form:
<div class="row">
<div class="col">
<input type="text" class="form-input" placeholder="First name" aria-label="First name">
</div>
<div class="col">
<input type="text" class="form-input" placeholder="Last name" aria-label="Last name">
</div>
</div> Grid gutters
Control the spacing between columns by applying gutter modifier classes. Gutters provide consistent spacing between form elements and help create visual separation in dense layouts. The gutter system offers:
- Horizontal gutters with
.gx-*classes - Vertical gutters with
.gy-*classes - Combined gutters with
.g-*classes for both directions - Responsive variants that adapt to different viewports
For form layouts, medium-sized gutters (.g-medium) often provide the optimal spacing.
<div class="row g-medium">
<div class="col">
<input type="text" class="form-input" placeholder="First name" aria-label="First name">
</div>
<div class="col">
<input type="text" class="form-input" placeholder="Last name" aria-label="Last name">
</div>
</div> Complex grid layouts
Combine grid columns with different widths to create sophisticated form layouts:
<form class="row g-medium">
<div class="medium:col-6">
<label for="inputEmail4" class="form-label">Email</label>
<input type="email" class="form-input" id="inputEmail4">
</div>
<div class="medium:col-6">
<label for="inputPassword4" class="form-label">Password</label>
<input type="password" class="form-input" id="inputPassword4">
</div>
<div class="col-12">
<label for="inputAddress" class="form-label">Address</label>
<input type="text" class="form-input" id="inputAddress" placeholder="1234 Main St">
</div>
<div class="col-12">
<label for="inputAddress2" class="form-label">Address 2</label>
<input type="text" class="form-input" id="inputAddress2" placeholder="Apartment, studio, or floor">
</div>
<div class="medium:col-6">
<label for="inputCity" class="form-label">City</label>
<input type="text" class="form-input" id="inputCity">
</div>
<div class="medium:col-4">
<label for="inputState" class="form-label">State</label>
<select id="inputState" class="form-select">
<option selected>Choose...</option>
<option>...</option>
</select>
</div>
<div class="medium:col-2">
<label for="inputZip" class="form-label">Zip</label>
<input type="text" class="form-input" id="inputZip">
</div>
<div class="col-12">
<div class="form-check">
<input class="check-input" type="checkbox" id="gridCheck">
<label class="check-label" for="gridCheck">
Check me out
</label>
</div>
</div>
<div class="col-12">
<button type="submit" class="button primary">Sign in</button>
</div>
</form> Horizontal form
Create horizontal forms with the grid by adding the .row class to form groups and using the .col-*-* classes to specify the width of your labels and controls. Be sure to add .col-form-label to your <label>s as well so they’re vertically centered with their associated form inputs.
At times, you maybe need to use margin or padding utilities to create that perfect alignment you need. For example, we’ve removed the padding-top on our stacked radio inputs label to better align the text baseline.
<form>
<div class="row mb-medium">
<label for="inputEmail3" class="small:col-2 col-form-label">Email</label>
<div class="small:col-10">
<input type="email" class="form-input" id="inputEmail3">
</div>
</div>
<div class="row mb-medium">
<label for="inputPassword3" class="small:col-2 col-form-label">Password</label>
<div class="small:col-10">
<input type="password" class="form-input" id="inputPassword3">
</div>
</div>
<fieldset class="row mb-medium">
<legend class="col-form-label small:col-2 pt-0">Radios</legend>
<div class="small:col-10">
<div class="form-check">
<input class="check-input" type="radio" name="gridRadios" id="gridRadios1" value="option1" checked>
<label class="check-label" for="gridRadios1">
First radio
</label>
</div>
<div class="form-check">
<input class="check-input" type="radio" name="gridRadios" id="gridRadios2" value="option2">
<label class="check-label" for="gridRadios2">
Second radio
</label>
</div>
<div class="form-check disabled">
<input class="check-input" type="radio" name="gridRadios" id="gridRadios3" value="option3" disabled>
<label class="check-label" for="gridRadios3">
Third disabled radio
</label>
</div>
</div>
</fieldset>
<div class="row mb-medium">
<div class="small:col-10 small:offset-2">
<div class="form-check">
<input class="check-input" type="checkbox" id="gridCheck1">
<label class="check-label" for="gridCheck1">
Example checkbox
</label>
</div>
</div>
</div>
<button type="submit" class="button primary">Sign in</button>
</form> Horizontal label sizing
Match label sizes to corresponding input sizes using these modifier classes:
.col-form-label-smallfor aligning with small inputs (.form-input.small).col-form-label-largefor aligning with large inputs (.form-input.large)
These classes maintain proper vertical alignment between labels and inputs of different sizes. They adjust the font size, line height, and padding to create a cohesive look in your form layouts.
<div class="row mb-medium">
<label for="colFormLabelSm" class="small:col-2 col-form-label col-form-label-small">Email</label>
<div class="small:col-10">
<input type="email" class="form-input small" id="colFormLabelSm" placeholder="col-form-label-small">
</div>
</div>
<div class="row mb-medium">
<label for="colFormLabel" class="small:col-2 col-form-label">Email</label>
<div class="small:col-10">
<input type="email" class="form-input" id="colFormLabel" placeholder="col-form-label">
</div>
</div>
<div class="row">
<label for="colFormLabelLg" class="small:col-2 col-form-label col-form-label-large">Email</label>
<div class="small:col-10">
<input type="email" class="form-input large" id="colFormLabelLg" placeholder="col-form-label-large">
</div>
</div> Column sizing
As shown in the previous examples, our grid system allows you to place any number of .cols within a .row. They’ll split the available width equally between them. You may also pick a subset of your columns to take up more or less space, while the remaining .cols equally split the rest, with specific column classes like .small:col-7.
<div class="row g-medium">
<div class="small:col-7">
<input type="text" class="form-input" placeholder="City" aria-label="City">
</div>
<div class="small:col">
<input type="text" class="form-input" placeholder="State" aria-label="State">
</div>
<div class="small:col">
<input type="text" class="form-input" placeholder="Zip" aria-label="Zip">
</div>
</div> Auto-sizing
Auto-sizing allows form elements to adapt to their content's width rather than spanning fixed columns. The .col-auto class creates columns that only take up as much space as needed. This technique is particularly useful for:
- Forms with varying field lengths
- Layouts where field sizes should match their expected content
- Compact, space-efficient forms with minimal wasted space
- Input groups with add-ons or buttons that should be optimally sized
When combined with flexbox alignment utilities like .align-items-center, auto-sizing creates clean, professional form layouts.
<form class="row gy-small gx-medium align-items-center">
<div class="col-auto">
<label class="visually-hidden" for="autoSizingInput">Name</label>
<input type="text" class="form-input" id="autoSizingInput" placeholder="Jane Doe">
</div>
<div class="col-auto">
<label class="visually-hidden" for="autoSizingInputGroup">Username</label>
<div class="input-group">
<div class="input-addon">@</div>
<input type="text" class="form-input" id="autoSizingInputGroup" placeholder="Username">
</div>
</div>
<div class="col-auto">
<label class="visually-hidden" for="autoSizingSelect">Preference</label>
<select class="form-select" id="autoSizingSelect">
<option selected>Choose...</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
<div class="col-auto">
<div class="form-check">
<input class="check-input" type="checkbox" id="autoSizingCheck">
<label class="check-label" for="autoSizingCheck">
Remember me
</label>
</div>
</div>
<div class="col-auto">
<button type="submit" class="button primary">Submit</button>
</div>
</form> Auto-sizing can be combined with fixed-width columns for hybrid layouts:
<form class="row gx-medium gy-small align-items-center">
<div class="small:col-3">
<label class="visually-hidden" for="specificSizeInputName">Name</label>
<input type="text" class="form-input" id="specificSizeInputName" placeholder="Jane Doe">
</div>
<div class="small:col-3">
<label class="visually-hidden" for="specificSizeInputGroupUsername">Username</label>
<div class="input-group">
<div class="input-addon">@</div>
<input type="text" class="form-input" id="specificSizeInputGroupUsername" placeholder="Username">
</div>
</div>
<div class="small:col-3">
<label class="visually-hidden" for="specificSizeSelect">Preference</label>
<select class="form-select" id="specificSizeSelect">
<option selected>Choose...</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
<div class="col-auto">
<div class="form-check">
<input class="check-input" type="checkbox" id="autoSizingCheck2">
<label class="check-label" for="autoSizingCheck2">
Remember me
</label>
</div>
</div>
<div class="col-auto">
<button type="submit" class="button primary">Submit</button>
</div>
</form> Inline forms
Create responsive horizontal form layouts with the .row-cols-* classes. These layouts adapt to different screen sizes, stacking vertically on small screens and displaying horizontally on larger screens.
Key features of inline forms:
- Use
.large:row-cols-autofor responsive horizontal layouts - Add gutter classes for consistent spacing
- Apply
.col-12on mobile to stack elements - Use
.align-items-centerfor vertical alignment
<form class="row large:row-cols-auto g-medium align-items-center">
<div class="col-12">
<label class="visually-hidden" for="inlineFormInputGroupUsername">Username</label>
<div class="input-group">
<div class="input-addon">@</div>
<input type="text" class="form-input" id="inlineFormInputGroupUsername" placeholder="Username">
</div>
</div>
<div class="col-12">
<label class="visually-hidden" for="inlineFormSelectPref">Preference</label>
<select class="form-select" id="inlineFormSelectPref">
<option selected>Choose...</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
</div>
<div class="col-12">
<div class="form-check">
<input class="check-input" type="checkbox" id="inlineFormCheck">
<label class="check-label" for="inlineFormCheck">
Remember me
</label>
</div>
</div>
<div class="col-12">
<button type="submit" class="button primary">Submit</button>
</div>
</form> Accessibility considerations
When implementing form layouts, ensure your forms remain accessible:
- Always include proper labels or use the
.visually-hiddenclass for labels that should be visible to screen readers but not visually displayed - Maintain a logical tab order that follows the visual layout of the form
- Use semantic HTML elements like
<fieldset>and<legend>to group related form controls - Include appropriate ARIA attributes where needed (e.g.,
aria-describedbyfor form validation messages) - Test keyboard navigation flow to ensure all form controls are accessible without a mouse
- Ensure sufficient color contrast for form elements and labels
- For complex layouts, test with screen readers to verify the form is navigable
See the Form validation documentation for more information on creating accessible validation feedback.