Form
All form elements are fully responsive with pure semantic HTML, enabling forms to scale gracefully across devices and viewports.
@use '@natachah/vanilla-frontend/scss/components/form'Syntax
The form is using the native <label>, <input> and co. tags.
<label for="demoInput">Input</label>
<input type="text" id="demoInput" name="input" placeholder="My input" aria-describedby="demoInputDescription">
<small id="demoInputDescription">
Must be at least 8 characters.
</small>--form-color
--form-background
--form-border-size
--form-border-style
--form-border-color
--form-border-radius
--form-padding-inline
--form-padding-block
--form-transition
--form-decorationInputs
<input type="text" name="text" placeholder="Some text">
<input type="search" name="search" placeholder="Enter some keyword">
<input type="email" name="email" placeholder="info@something.com">
<input type="url" name="url" placeholder="http://www.google.com">
<input type="tel" name="tel" placeholder="021 922 00 00">
<input type="number" name="number" placeholder="42">
<input type="password" name="password" placeholder="123456">The type file come with a default icon and no button.
<input type="file" name="file" accept="image/png, image/jpeg">--icon-fileThe type date, time and datetime-local come with default icon.
<input type="date" name="date">
<input type="time" name="time">
<input type="datetime-local" name="datetime">--icon-date
--icon-timeThe type color is also consistent with the other input types.
<input type="color" name="color">The range field look more like a progress bar.
<input type="range" name="range" min="0" max="10">Textarea
The native <textarea> is styled like the input for consistency.
By default you only can resize the height.
<textarea name="textarea" rows="5" cols="33">It was a dark and stormy night...</textarea>Select
The native <select> is styled like the input for consistency.
<select name="select">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
</select>--icon-selectRadio
The radio field must be inside a <fieldset>.
<fieldset>
<legend>Radio</legend>
<input type="radio" id="radioA" name="radio" checked> <label for="radioA">Option A</label>
<input type="radio" id="radioB" name="radio"> <label for="radioB">Option B</label>
<input type="radio" id="radioC" name="radio"> <label for="radioC">Option C</label>
</fieldset>--icon-radio
--form-active-background
--form-active-border-colorTo display the element into the vertical, surround the <input> and the <label> by a <div> tag.
<fieldset>
<legend>Radio</legend>
<div>
<input type="radio" id="radioD" name="radio" checked> <label for="radioD">Option D</label>
</div>
<div>
<input type="radio" id="radioE" name="radio"> <label for="radioE">Option E</label>
</div>
<div>
<input type="radio" id="radioF" name="radio"> <label for="radioF">Option F</label>
</div>
</fieldset>Checkbox
The checkbox field must be inside a <fieldset>.
<fieldset>
<legend>Checkbox</legend>
<input type="checkbox" id="checkboxA" name="checkboxA" checked> <label for="checkboxA">Option A</label>
<input type="checkbox" id="checkboxB" name="checkboxB"> <label for="checkboxB">Option B</label>
<input type="checkbox" id="checkboxC" name="checkboxC"> <label for="checkboxC">Option C</label>
</fieldset>--icon-check
--form-active-background
--form-active-border-colorTo display the element into the vertical, surround the <input> and the <label> by a <div> tag.
<fieldset>
<legend>Radio</legend>
<div>
<input type="checkbox" id="checkboxD" name="checkbox" checked> <label for="checkboxD">Option D</label>
</div>
<div>
<input type="checkbox" id="checkboxE" name="checkbox"> <label for="checkboxE">Option E</label>
</div>
<div>
<input type="checkbox" id="checkboxF" name="checkbox"> <label for="checkboxF">Option F</label>
</div>
</fieldset>Switch
The checkbox with the role="switch" attribute will render a switch component.
<input type="checkbox" role="switch" id="switch" name="switch" value="true">
<label for="switch">I agree to the terms</label>--icon-switch
--form-active-background
--form-active-border-colorStates
The form can have the :focus, :disabled, :readonly and :validation states.
Focus
The form use a default focus style, but you can customize it with :
--form-focus-color
--form-focus-background
--form-focus-border-colorYou can also customize the outline :
--form-outline-size
--form-outline-style
--form-outline-color
--form-outline-offsetDisabled
Apply the disabled attribute on <input>, <textarea> or <select> tags to display the disabled style.
<input type="text" value="My value" disabled>
<select type="text" disabled>
<option value="--">--</option>
</select>
<textarea disabled>It was a dark and stormy night...</textarea>
<input type="checkbox" disabled> <input type="checkbox" disabled checked> <input type="radio" disabled> <input type="radio" disabled checked> <input type="checkbox" role="switch" disabled> <input type="checkbox" role="switch" disabled checked>--form-disabled-opacityReadonly
Apply the readonly attribute on <input> or <textarea> tags to display the readonly style.
<input type="text" value="My value" readonly>
<textarea readonly>It was a dark and stormy night...</textarea>Validation
Use the aria-invalid attribute to display the element as in/valid and use aria-describedby attribute with a <small> tag to display the information.
As every design is different, there is not too much default style for in/valid elements. But for accessibility don't forget to add icons to show the errors.
<div>
<label for="invalidInput">Invalid input</label>
<input id="invalidInput" type="text" aria-describedby="invalidMsg" aria-invalid="true" value="My bad value">
<small id="invalidMsg" >
<span aria-live="assertive">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"></path><path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0M7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0z"></path></svg>
Incorrect value !
</span>
</small>
</div>
<div>
<label for="validInput">Valid input</label>
<input id="validInput" type="text" aria-describedby="validMsg" aria-invalid="false" value="My good value">
<small id="validMsg">
<span aria-live="assertive">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"></path><path d="m10.97 4.97-.02.022-3.473 4.425-2.093-2.094a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-1.071-1.05"></path></svg>
All good !
</span>
</small>
</div>form div {
&:has([aria-invalid=true]) {
[aria-live] {
color: var(--color-error);
}
}
&:has([aria-invalid=false]) {
[aria-live] {
color: var(--color-success);
}
}
}Variants
Group
You can group some fields by putting them in a <div> with the class .group.
<fieldset>
<legend>Price</legend>
<div class="group">
<label>Before</label>
<select>
<option value="A">CHF</option>
<option value="B">€</option>
<option value="C">$</option>
</select>
<input type="number" value="110">
<label>After</label>
<button>Send</button>
</div>
</fieldset>@use '@natachah/vanilla-frontend/scss/components/group';