No animations match your search in this category.
The code for all 6 forms & inputs, explained
Every effect above, with the markup to use and the complete CSS. Each one is self-contained: paste the CSS once, add the class, done.
Focus Glow
The soft ring makes focus unmistakable without an harsh outline. Never remove focus styling — replace it with something better, like this.
Markup
<input type="text" class="fh-input-glow" placeholder="Your email" />
CSS
.fh-input-glow {
border: 1px solid #3a4358;
border-radius: 10px;
padding: 12px 16px;
background: transparent;
color: inherit;
outline: none;
transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
.fh-input-glow:focus {
border-color: #06b6d4;
box-shadow: 0 0 0 4px rgba(6, 182, 212, 0.15);
}
Floating Label
The placeholder=" " (one space) is the trick — :placeholder-shown can then detect whether the field is empty, no JavaScript needed.
Markup
<div class="fh-float-field">
<input type="text" placeholder=" " />
<label>Email address</label>
</div>
CSS
.fh-float-field {
position: relative;
}
.fh-float-field input {
width: 100%;
border: 1px solid #3a4358;
border-radius: 10px;
padding: 18px 14px 6px;
background: transparent;
color: inherit;
outline: none;
}
.fh-float-field input:focus { border-color: #06b6d4; }
.fh-float-field label {
position: absolute;
left: 14px;
top: 50%;
translate: 0 -50%;
color: #94a3b8;
pointer-events: none;
text-transform: none;
transition: all 0.2s ease;
}
.fh-float-field input:focus + label,
.fh-float-field input:not(:placeholder-shown) + label {
top: 10px;
translate: 0 0;
font-size: 0.68em;
color: #06b6d4;
}
Toggle Switch
A real checkbox restyled — so keyboard, forms and screen readers all keep working. The springy easing sells the flip.
Markup
<input type="checkbox" class="fh-toggle" />
CSS
.fh-toggle {
appearance: none;
width: 52px;
height: 28px;
padding: 0;
border: none;
border-radius: 14px;
background: #3a4358;
position: relative;
cursor: pointer;
transition: background 0.25s ease;
}
.fh-toggle::before {
content: '';
position: absolute;
top: 3px;
left: 3px;
width: 22px;
height: 22px;
border-radius: 50%;
background: #fff;
transition: left 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.fh-toggle:checked { background: #06b6d4; }
.fh-toggle:checked::before { left: 27px; }
Checkbox Pop
The tick scales in with an overshoot — the same pattern used by the checklists on this site's Dev Essentials page.
Markup
<input type="checkbox" class="fh-check" />
CSS
.fh-check {
appearance: none;
width: 26px;
height: 26px;
padding: 0;
border: 2px solid #3a4358;
border-radius: 8px;
cursor: pointer;
display: grid;
place-content: center;
transition: background 0.2s ease, border-color 0.2s ease;
}
.fh-check::before {
content: '';
width: 12px;
height: 12px;
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
background: #04110b;
transform: scale(0);
transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.fh-check:checked { background: #10b981; border-color: #10b981; }
.fh-check:checked::before { transform: scale(1); }
Button Press
The :active state compresses the button and flattens its shadow — a 120ms cue that the click registered. Tactile feedback, zero JavaScript.
Markup
<button class="fh-btn-press">Save changes</button>
CSS
.fh-btn-press {
padding: 12px 26px;
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 10px;
background: linear-gradient(135deg, #8b5cf6, #06b6d4);
color: #fff;
font-weight: 600;
cursor: pointer;
box-shadow: 0 6px 16px -6px rgba(139, 92, 246, 0.5);
transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.fh-btn-press:hover { transform: translateY(-1px); }
.fh-btn-press:active {
transform: translateY(1px) scale(0.97);
box-shadow: 0 2px 6px -2px rgba(139, 92, 246, 0.4);
}
Validation Shake
Add the class from JavaScript when validation fails, and remove it on the animationend event so it can shake again next time.
Markup
<input class="fh-field-error" /> <!-- add the class on failed validation -->
CSS
.fh-field-error {
border: 1px solid #ef4444;
box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.12);
animation: fh-fieldShake 0.4s ease-in-out;
}
@keyframes fh-fieldShake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-6px); }
50% { transform: translateX(6px); }
75% { transform: translateX(-3px); }
}
Style real controls, never replace them
Every effect here restyles a genuine <input> — the toggle switch is a checkbox, the animated tick is a checkbox, the shake is applied to a text field. That matters enormously: a real input arrives with keyboard operability, form submission, screen reader semantics and browser autofill already working.
The common alternative — building a "toggle" from divs and click handlers — throws all of that away and then requires re-implementing it badly with ARIA. appearance: none lets you strip a control's native styling while keeping its native behaviour, and that's the technique underpinning this whole category.
Focus styling is not optional
The single most damaging thing done to forms is outline: none with nothing to replace it. It removes the only indication of where a keyboard user is, turning a form into an invisible maze. If you dislike the default outline, replace it — a focus ring built from box-shadow, as the focus-glow effect here does, is both attractive and compliant.
Use :focus-visible rather than :focus so the ring appears for keyboard navigation but not on mouse clicks, which is the behaviour most designers actually want.
Floating labels and the placeholder trap
The floating-label effect uses a pure-CSS trick: a placeholder of a single space makes :placeholder-shown a reliable test for whether the field is empty, so the label can move without JavaScript.
What it must never do is replace the label entirely. Placeholder-only fields lose their description the moment the user types, fail contrast requirements at default styling, and confuse screen readers. Floating labels work precisely because the label persists — it moves rather than disappearing.
Validation feedback that helps
The shake animation signals a problem instantly, but motion alone isn't enough: colour and movement are not accessible signals on their own. Pair the shake with a text message describing what's wrong and how to fix it, associate it with the field using aria-describedby, and set aria-invalid. Add the shake class on failed submission and remove it on animationend so it can fire again next time.