No animations match your search in this category.
The code for all 6 ui feedback, 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.
Toast Slide-In
The standard confirmation pattern — slides in with a slight overshoot so it feels placed, not teleported. Remove the element (or add a fade-out class) after ~2.5s.
Markup
<div class="fh-toast">✓ Changes saved</div>
CSS
.fh-toast {
display: inline-block;
padding: 12px 20px;
background: #101828;
border: 1px solid rgba(16, 185, 129, 0.5);
border-radius: 10px;
color: #10b981;
font-weight: 600;
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
animation: fh-toastIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes fh-toastIn {
from { opacity: 0; transform: translateY(16px) scale(0.95); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
Modal Pop-In
Dialog scales up as the backdrop fades — the pair reads as one motion. In production use the native
Markup
<div class="fh-modal-backdrop">
<div class="fh-modal">…dialog content…</div>
</div>
CSS
.fh-modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.55);
display: grid;
place-items: center;
animation: fh-backdropIn 0.25s ease both;
}
.fh-modal {
background: #101828;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 14px;
padding: 22px 26px;
color: inherit;
font-weight: 600;
box-shadow: 0 24px 60px -12px rgba(0, 0, 0, 0.6);
animation: fh-modalIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes fh-backdropIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fh-modalIn {
from { opacity: 0; transform: translateY(14px) scale(0.9); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
/* demo-only helpers */
.fh-modal-row { display: flex; gap: 8px; margin-top: 12px; }
.fh-modal-ok, .fh-modal-no {
font-size: 0.75em;
padding: 6px 12px;
border-radius: 7px;
}
.fh-modal-ok { background: #06b6d4; color: #001018; }
.fh-modal-no { border: 1px solid #3a4358; }
Tooltip Fade
The short delay (0.15s) is deliberate — tooltips that appear instantly flicker annoyingly as the cursor crosses the page. The arrow is a rotated square.
Markup
<div class="fh-tip-wrap">
<button>Delete</button>
<span class="fh-tooltip">This cannot be undone</span>
</div>
CSS
.fh-tip-wrap {
position: relative;
display: inline-block;
}
.fh-tooltip {
position: absolute;
bottom: calc(100% + 9px);
left: 50%;
translate: -50% 4px;
background: #101828;
border: 1px solid #3a4358;
border-radius: 8px;
padding: 7px 12px;
font-size: 0.75em;
white-space: nowrap;
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: opacity 0.25s ease 0.15s, translate 0.25s ease 0.15s, visibility 0.25s 0.15s;
}
.fh-tooltip::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
margin-top: -5px;
width: 10px;
height: 10px;
background: #101828;
border-right: 1px solid #3a4358;
border-bottom: 1px solid #3a4358;
transform: rotate(45deg);
}
.fh-tip-wrap:hover .fh-tooltip,
.fh-tip-wrap:focus-within .fh-tooltip {
opacity: 1;
visibility: visible;
translate: -50% 0;
}
Tab Underline Slide
Each tab carries its own scaling underline — hover any tab and the line grows from centre. Swap the .active class in JS for the selected state.
Markup
<nav class="fh-tabs">
<a class="fh-tab active" href="#">Overview</a>
<a class="fh-tab" href="#">Pricing</a>
</nav>
CSS
.fh-tabs {
display: flex;
gap: 4px;
}
.fh-tab {
position: relative;
padding: 10px 16px;
font-weight: 600;
color: #94a3b8;
cursor: pointer;
transition: color 0.2s ease;
}
.fh-tab::after {
content: '';
position: absolute;
left: 12px;
right: 12px;
bottom: 4px;
height: 2px;
border-radius: 2px;
background: #06b6d4;
transform: scaleX(0);
transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
.fh-tab:hover,
.fh-tab.active { color: inherit; }
.fh-tab:hover::after,
.fh-tab.active::after { transform: scaleX(1); }
Progress Bar Fill
The fill animates to a CSS variable, so JavaScript only sets --target and the easing is pure CSS. Great for onboarding steps and upload progress.
Markup
<div class="fh-progress">
<div class="fh-progress-fill" style="--target: 72%"></div>
</div>
CSS
.fh-progress {
width: 170px;
height: 10px;
border-radius: 5px;
background: rgba(255, 255, 255, 0.08);
overflow: hidden;
}
.fh-progress-fill {
--target: 72%;
height: 100%;
width: var(--target);
border-radius: 5px;
background: linear-gradient(90deg, #8b5cf6, #06b6d4);
animation: fh-progressFill 1.1s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes fh-progressFill {
from { width: 0; }
}
Notification Ping
The unread-notification dot with a radiating ping — impossible to miss without being loud. The ::after ring animates; the dot itself stays still.
Markup
<button class="fh-bell">
🔔
<span class="fh-badge-ping"></span>
</button>
CSS
.fh-bell {
position: relative;
display: inline-grid;
place-content: center;
width: 46px;
height: 46px;
border: 1px solid #3a4358;
border-radius: 12px;
}
.fh-badge-ping {
position: absolute;
top: 9px;
right: 9px;
width: 9px;
height: 9px;
border-radius: 50%;
background: #ef4444;
}
.fh-badge-ping::after {
content: '';
position: absolute;
inset: 0;
border-radius: 50%;
background: #ef4444;
animation: fh-badgePing 1.4s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes fh-badgePing {
from { transform: scale(1); opacity: 0.8; }
to { transform: scale(2.6); opacity: 0; }
}
Feedback animation has a job to do
Every animation in this category answers a question: did that work? where did this come from? how much longer? That makes them the most functional animations on the site — and the ones where getting the timing right matters most.
Confirmation feedback should appear immediately after the action, within about 100ms, or the user stops associating the two. A toast that arrives half a second after clicking Save feels disconnected from the click.
Toasts, and announcing them properly
A toast that only appears visually is invisible to screen reader users — who then have no confirmation their action succeeded. Put toast messages in a container with aria-live="polite" so assistive technology announces them without interrupting, exactly as this site does for its copy confirmations.
Keep them on screen long enough to read — roughly 4 to 6 seconds for a short message — and never put an essential action inside a toast that disappears. Anything the user must act on belongs in a persistent element.
Modals: the hardest pattern to get right
The pop-in animation is the easy part. The accessibility requirements are what most implementations miss: focus must move into the dialog when it opens, be trapped inside while it's open, and return to the triggering element on close. Escape must dismiss it, and content behind it should be inert.
The native <dialog> element with showModal() handles focus trapping, Escape and inertness for you, and is now well supported. Use it and apply this animation on open rather than rebuilding all of that from scratch.
Progress and tooltips
The progress bar animates to a CSS custom property, so JavaScript only sets --target and the easing stays in CSS. For accessibility, use a real role="progressbar" with aria-valuenow so the value is exposed, not just drawn.
Tooltips use a deliberate short delay before appearing — without it they flicker distractingly as the cursor crosses the page. Never put essential information in a tooltip alone: it's unreachable on touch devices and easy to miss.