SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/slide-in-animations

7 CSS Slide In Animations

2 Pure CSS5 with JSPublished 2026-10-05Free · no sign-up

Seven slide-in templates: a list that enters from the left, a toast from the corner, a filter drawer and a mobile bottom sheet built on the native dialog element, a notice that drops from the top, feature rows that alternate sides and a headline whose lines slide up in turn.

01. List Items Slide In from the Left

SlideStagger

Navigation or feature items slide in from the left with a short stagger as the page loads. One keyframe moves each item 24px and fades it in, and an index custom property spaces the delays, so the list can grow without new CSS.

View code
<ul class="si1"><li style="--i:0">Dashboard</li><li style="--i:1">Orders</li><li style="--i:2">Customers</li><li style="--i:3">Reports</li></ul>
.si1 { display: grid; gap: 6px; width: 220px; max-width: 100%; margin: 0; padding: 0; list-style: none; font: 600 15px Inter, system-ui, sans-serif; }
.si1 li { padding: 12px 14px; border-radius: 10px; background: #fff; border: 1px solid #e4e7ec; color: #101828; animation: si1 .5s cubic-bezier(.2,.8,.2,1) both; animation-delay: calc(var(--i) * 80ms + .1s); }
@keyframes si1 { from { opacity: 0; transform: translateX(-24px); } }
@media (prefers-reduced-motion: reduce) { .si1 li { animation: none; } }

02. Toast Sliding In from the Corner

SlideToast

A toast slides in from the bottom right, waits, then slides back out. It lives in a role="status" region that already exists on the page, which is the reliable way to get toasts announced, and it can be dismissed early with its close button.

View code
<div class="si2"><button class="go">Save draft</button><div class="zone" role="status"></div></div>
.si2 { position: relative; width: 300px; max-width: 100%; height: 220px; border-radius: 14px; background: #121828; font-family: Inter, system-ui, sans-serif; overflow: hidden; }
.si2 .go { margin: 16px; padding: 10px 16px; border: 0; border-radius: 8px; background: #e2e8f0; color: #0f172a; font: 700 14px Inter, system-ui, sans-serif; cursor: pointer; }
.si2 .zone { position: absolute; right: 12px; bottom: 12px; left: 12px; display: flex; justify-content: flex-end; }
.si2 .t { display: flex; align-items: center; gap: 10px; padding: 12px 12px 12px 14px; border-radius: 10px; background: #f8fafc; color: #0f172a; font-size: 14px; font-weight: 600; box-shadow: 0 10px 24px -8px #000; animation: si2 .35s cubic-bezier(.2,.8,.2,1) both; }
.si2 .t.out { animation: si2o .25s ease-in both; }
.si2 .t button { width: 28px; height: 28px; border: 0; border-radius: 6px; background: transparent; color: #475467; font-size: 18px; cursor: pointer; }
.si2 button:focus-visible { outline: 2px solid #93c5fd; outline-offset: 2px; }
@keyframes si2 { from { opacity: 0; transform: translateX(110%); } }
@keyframes si2o { to { opacity: 0; transform: translateX(110%); } }
@media (prefers-reduced-motion: reduce) { .si2 .t, .si2 .t.out { animation: none; } }
var zone = document.querySelector('.si2 .zone');
document.querySelector('.si2 .go').onclick = function () {
  zone.innerHTML = '<div class="t">Draft saved <button aria-label="Dismiss">&times;</button></div>';
  var t = zone.firstChild, gone = function () { t.classList.add('out'); setTimeout(function () { if (t.parentNode) t.remove(); }, 260); };
  t.querySelector('button').onclick = gone; setTimeout(gone, 4000);
};

03. Side Drawer with dialog

SlideDialog

A filter drawer that slides in from the right using the native dialog element, which brings focus trapping, Escape to close and an inert page behind it for free. The slide uses @starting-style and allow-discrete so it animates both in and out.

View code
<div class="si3"><button class="open">Filters</button><dialog aria-labelledby="si3h"><h3 id="si3h">Filters</h3><label><input type="checkbox" checked> In stock</label><label><input type="checkbox"> On sale</label><button class="close">Apply</button></dialog></div>
.si3 { font-family: Inter, system-ui, sans-serif; }
.si3 .open { padding: 10px 16px; border: 1px solid #d0d5dd; border-radius: 8px; background: #fff; font: 600 14px Inter, system-ui, sans-serif; cursor: pointer; }
.si3 dialog { position: fixed; inset: 0 0 0 auto; width: min(260px, 80vw); height: 100%; max-height: none; margin: 0; padding: 20px; box-sizing: border-box; border: 0; background: #fff; color: #101828; transform: translateX(100%); transition: transform .3s cubic-bezier(.2,.8,.2,1), overlay .3s allow-discrete, display .3s allow-discrete; }
.si3 dialog[open] { display: grid; align-content: start; gap: 12px; transform: none; }
@starting-style { .si3 dialog[open] { transform: translateX(100%); } }
.si3 dialog::backdrop { background: rgba(16,24,40,0); transition: background .3s, overlay .3s allow-discrete, display .3s allow-discrete; }
.si3 dialog[open]::backdrop { background: rgba(16,24,40,.45); }
@starting-style { .si3 dialog[open]::backdrop { background: rgba(16,24,40,0); } }
.si3 h3 { margin: 0; } .si3 label { display: flex; gap: 8px; align-items: center; font-size: 14px; }
.si3 .close { padding: 10px; border: 0; border-radius: 8px; background: #101828; color: #fff; font: 700 14px Inter, system-ui, sans-serif; cursor: pointer; }
.si3 button:focus-visible { outline: 3px solid #84adff; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .si3 dialog, .si3 dialog::backdrop { transition: none; } }
var d = document.querySelector('.si3 dialog');
document.querySelector('.si3 .open').onclick = function () { d.showModal(); };
document.querySelector('.si3 .close').onclick = function () { d.close(); };

04. Banner Sliding Down from the Top

SlideBanner

A notice slides down from the top edge after a short delay, so it does not compete with the first look at the page. It pushes nothing around because it is absolutely positioned, and the dismiss button removes it with a reverse slide.

View code
<div class="si4"><div class="bn" role="region" aria-label="Notice"><p>Our studio is closed 24-26 December.</p><button aria-label="Dismiss notice">&times;</button></div><p class="pg">Page content.</p></div>
.si4 { position: relative; width: 300px; max-width: 100%; height: 190px; border-radius: 14px; background: #0f172a; overflow: hidden; font-family: Inter, system-ui, sans-serif; }
.si4 .bn { position: absolute; top: 0; left: 0; right: 0; display: flex; align-items: center; gap: 8px; padding: 10px 10px 10px 14px; background: #fde047; color: #422006; font-size: 13px; font-weight: 600; animation: si4 .45s cubic-bezier(.2,.8,.2,1) .6s both; }
.si4 .bn.out { animation: si4o .3s ease-in both; }
.si4 .bn p { flex: 1; margin: 0; }
.si4 button { width: 28px; height: 28px; border: 0; border-radius: 6px; background: rgba(0,0,0,.1); color: #422006; font-size: 16px; cursor: pointer; }
.si4 button:focus-visible { outline: 2px solid #422006; outline-offset: 1px; }
.si4 .pg { margin: 0; padding: 70px 16px; color: #94a3b8; }
@keyframes si4 { from { transform: translateY(-100%); } }
@keyframes si4o { to { transform: translateY(-100%); } }
@media (prefers-reduced-motion: reduce) { .si4 .bn, .si4 .bn.out { animation: none; } }
var bn = document.querySelector('.si4 .bn');
bn.querySelector('button').onclick = function () { bn.classList.add('out'); setTimeout(function () { bn.remove(); }, 310); };

05. Features Sliding In from Both Sides

SlideLayout

Feature rows slide in alternately from the left and right as they enter the scroll panel. Odd and even rows pick a direction with :nth-child, and one IntersectionObserver adds the class that starts each row's transition.

View code
<div class="si5" tabindex="0" role="region" aria-label="Features, scroll"><p class="h">Scroll ↓</p><div class="r">Unlimited projects</div><div class="r">Team permissions</div><div class="r">Audit history</div><div class="r">Priority support</div></div>
.si5 { width: 270px; max-width: 100%; height: 280px; overflow-y: auto; overflow-x: hidden; padding: 14px; box-sizing: border-box; border: 1px solid #e4e7ec; border-radius: 16px; background: #fff; font: 700 15px Inter, system-ui, sans-serif; }
.si5:focus-visible { outline: 3px solid #84adff; outline-offset: 2px; }
.si5 .h { height: 200px; margin: 0; color: #475467; font-weight: 500; font-size: 14px; }
.si5 .r { margin-bottom: 60px; padding: 18px; border-radius: 12px; background: #ecfdf3; color: #054f31; }
.si5 .r:nth-child(odd) { background: #eff8ff; color: #194185; }
.si5.js .r { opacity: 0; transition: opacity .5s ease, transform .5s ease; }
.si5.js .r:nth-child(even) { transform: translateX(-40px); } .si5.js .r:nth-child(odd) { transform: translateX(40px); }
.si5.js .r.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .si5.js .r { opacity: 1; transform: none !important; transition: none; } }
var box = document.querySelector('.si5'); box.classList.add('js');
var io = new IntersectionObserver(function (es) { es.forEach(function (e) { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } }); }, { root: box, threshold: .4 });
box.querySelectorAll('.r').forEach(function (r) { io.observe(r); });

06. Headline Lines Slide Up

SlideTypography

A three-line headline where each line slides up from below its own baseline in turn. Each line is a block with overflow: hidden and its inner span moves, so the line wraps stay where the designer put them with explicit line breaks.

View code
<h3 class="si6"><span><span style="--i:0">Furniture</span></span><span><span style="--i:1">made to</span></span><span><span style="--i:2">outlast trends.</span></span></h3>
.si6 { display: grid; margin: 0; color: #f8fafc; font: 800 32px/1.15 Inter, system-ui, sans-serif; }
.si6 > span { display: block; overflow: hidden; }
.si6 > span > span { display: block; animation: si6 .8s cubic-bezier(.2,.8,.2,1) both; animation-delay: calc(var(--i) * 140ms + .2s); }
.si6 > span:last-child > span { color: #fb923c; }
@keyframes si6 { from { transform: translateY(100%); } }
@media (prefers-reduced-motion: reduce) { .si6 span span { animation: none; } }

07. Mobile Bottom Sheet

SlideMobile

A share sheet slides up from the bottom of a phone frame with a drag handle at the top. It is a modal dialog, so focus moves into it and Escape closes it, and the sheet's slide uses the same @starting-style technique as the drawer.

View code
<div class="si7"><button class="open">Share</button><dialog aria-labelledby="si7h"><span class="grab" aria-hidden="true"></span><h3 id="si7h">Share this recipe</h3><div class="opts"><button>Copy link</button><button>Email</button><button>Message</button></div><button class="close">Cancel</button></dialog></div>
.si7 { font-family: Inter, system-ui, sans-serif; }
.si7 .open { padding: 10px 16px; border: 0; border-radius: 8px; background: #101828; color: #fff; font: 700 14px Inter, system-ui, sans-serif; cursor: pointer; }
.si7 dialog { position: fixed; inset: auto 0 0 0; width: 100%; max-width: 100%; margin: 0; padding: 10px 18px 18px; box-sizing: border-box; border: 0; border-radius: 18px 18px 0 0; background: #fff; color: #101828; transform: translateY(100%); transition: transform .35s cubic-bezier(.2,.8,.2,1), overlay .35s allow-discrete, display .35s allow-discrete; }
.si7 dialog[open] { transform: none; }
@starting-style { .si7 dialog[open] { transform: translateY(100%); } }
.si7 dialog::backdrop { background: rgba(16,24,40,.4); }
.si7 .grab { display: block; width: 40px; height: 5px; margin: 0 auto 10px; border-radius: 3px; background: #d0d5dd; }
.si7 h3 { margin: 0 0 12px; font-size: 16px; }
.si7 .opts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 10px; }
.si7 .opts button { padding: 12px 4px; border: 0; border-radius: 10px; background: #f2f4f7; font: 600 13px Inter, system-ui, sans-serif; cursor: pointer; }
.si7 .close { width: 100%; padding: 12px; border: 1px solid #d0d5dd; border-radius: 10px; background: #fff; font: 700 14px Inter, system-ui, sans-serif; cursor: pointer; }
.si7 button:focus-visible { outline: 3px solid #84adff; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .si7 dialog { transition: none; } }
var d = document.querySelector('.si7 dialog');
document.querySelector('.si7 .open').onclick = function () { d.showModal(); };
d.querySelectorAll('button').forEach(function (b) { b.onclick = function () { d.close(); }; });

About these CSS Slide In Animations

Slide from where it lives

Drawers slide from the edge they attach to, toasts from the corner they sit in, sheets from the bottom. Matching the direction to the position tells people where the element came from and where it will go.

dialog plus @starting-style

The native <dialog> traps focus, closes on Escape and makes the page inert. Add a transform transition, an @starting-style for the opening frame and overlay and display with allow-discrete so it also animates out.

Announce toasts properly

Put a role="status" container on the page from the start and insert toasts into it. Live regions added at the same moment as their text are often not announced.

Out is faster than in

Enter over 300 to 450ms with an ease-out curve; leave over about 250ms with ease-in. Lingering exits feel sluggish.

Frequently asked questions

Do the drawer and sheet work without the animation?

Yes. In browsers without @starting-style they open and close instantly with the same behaviour.

Should toasts disappear on their own?

Short confirmations can, after several seconds; anything with an action or an error should stay until dismissed.

Why not slide with left or margin?

Transform moves the element without recalculating layout, so it stays smooth on phones.