What You'll Build

In this tutorial you'll build two complementary UI components that demonstrate a wide range of CSS and JavaScript animation techniques in one compact, single-file project. The first component is a day/night theme toggle switch — a smooth, pill-shaped button with a sliding circular thumb. As the thumb travels across the track, a sun icon fades and shrinks out while a crescent moon icon scales and rotates in, giving the appearance of one icon morphing into the other. Meanwhile, the entire background of the scene transitions between a soft near-white and a deep navy, producing an immersive day-to-night feel.

The second component takes UI micro-interaction to a playful extreme: an animated logout button. When clicked, a stick figure character walks toward a door rendered in SVG, the door swings open, the figure passes through, the door slams shut, and — in a final comic flourish — the figure falls off screen while spinning. Every limb movement (arms, wrists, legs, calves) is driven by CSS custom properties that JavaScript updates in a carefully timed sequence, turning SVG groups into a surprisingly expressive walking puppet.

Together, these two components cover a foundational web animation skillset: CSS class-based theme switching, opacity and transform crossfades, CSS custom property animation, SVG layering and z-index composition, and sequential animation state machines in vanilla JavaScript.

💡 Who Is This For? The toggle switch is ideal for beginners who want their first taste of practical theme switching. The logout button is well-suited for intermediate developers who want to explore CSS custom property animation and JavaScript-driven SVG state sequencing — no animation library required.

Key Features of This Toggle & Logout Button UI

🌗
Smooth Day / Night Toggle
A pill-shaped switch whose thumb slides between two positions with a cubic-bezier spring easing for a satisfying snap feel.
☀️
Sun / Moon Icon Crossfade
Two Boxicons icons stacked in the thumb — the sun fades and spins out while the moon scales and rotates in using independent CSS opacity and transform transitions.
🎨
Full Scene Background Transition
The entire .scene container smoothly shifts between a light near-white (#f4f7ff) and a deep navy (#1f2335) over 0.5s with a single CSS transition.
🚶
Walking Stick Figure Animation
An inline SVG figure whose arms, wrists, legs, and calves are animated through two distinct walking poses via CSS custom properties updated by JavaScript.
🚪
Door Open & Slam Sequence
The door SVG rotates open with rotateY on click, waits for the figure to walk through, then snaps shut with a timed CSS class addition and transition-delay.
😵
Comedic Falling Exit
After the door slams, the figure transitions its bottom position off-screen, runs a spin keyframe, and fades out — a three-stage falling animation that delights users.
🎭
Theme-Aware Button Colors
The logout button, door, and doorway SVG fills invert automatically between themes using .light-mode and .dark-mode CSS selectors, so the component always looks correct in both states.
⚙️
CSS Custom Property State Machine
A states object in JavaScript maps named animation states to CSS custom property values. Switching states is one function call — clean, readable, and trivially extensible.

Full Source Code (Free)

Both components live together in a single index.html file. The CSS defines all transitions and animation states. The JavaScript consists of two independent blocks: one click listener for the theme toggle, and one state-machine-style sequence of setTimeout calls for the logout button animation. Use the tabs below to explore the HTML structure, CSS styles, and JavaScript logic separately.

HTML — index.html
CSS — style.css
JS — script.js

🔓 Full Source Code unlocks in

05

Hosted on GitHub Gist — free, no sign-up required

💡 Quick Start: Copy all code into a single index.html file and add a Boxicons CDN link in the <head>. Open it in any modern browser — no build tools, no npm, no configuration needed.

How It Works — Step by Step

Here's a deep dive into the eight core techniques powering both the theme toggle and the animated logout button, from the scene setup to the stick figure's dramatic exit.

01

The Scene Container & Theme Classes

A .scene div wraps both components and starts with the light-mode class applied. A transition: background 0.5s ease on .scene ensures that every time the class swaps between light-mode and dark-mode, the background color blends smoothly rather than cutting instantly. This single container-level class is the control point for both the toggle visuals and the button color inversions.

02

The Toggle Switch — Track & Thumb

The toggle is a <button> with a fixed pill shape (width: 54px; height: 28px; border-radius: 14px). Inside it, a .thumb div acts as the sliding indicator. In light mode, .light-mode .thumb sets transform: translateX(0); in dark mode, .dark-mode .thumb sets transform: translateX(26px). The transition: all 0.4s cubic-bezier(.34, 1.56, .64, 1) on the thumb gives the slide a slight overshoot that feels springy and tactile.

03

Sun / Moon Icon Crossfade Inside the Thumb

Two <span> elements — .icon-sun and .icon-moon — are positioned absolutely on top of each other inside the thumb. Each gets its own transition: opacity 0.3s, transform 0.4s. In light mode the sun is at opacity: 1; transform: scale(1) rotate(0deg) and the moon is hidden at opacity: 0; transform: scale(0.5) rotate(-90deg). In dark mode these values flip. The result is a smooth icon morph that looks like one animated icon rather than two swapping images.

04

The JavaScript Theme Toggle — One Line of Logic

A click listener on #themeBtn flips a local dark boolean and sets scene.className to either 'scene dark-mode' or 'scene light-mode'. That's the entirety of the JavaScript for the toggle — every visual change cascades from CSS selectors targeting the theme class. Storing the boolean in JavaScript (rather than checking the DOM class) makes it easy to read, extend, or connect to localStorage for persistence.

05

SVG Layering for the Logout Button

The logout button contains three inline SVG elements, all absolutely positioned and stacked by z-index. The first (.doorway, z-index 3) is the static doorframe background. The second (.figure, z-index 4) is the animated stick figure. The third (.door, z-index 5) sits in front of the figure by default so it visually "covers" the figure when closed — then the figure appears to step behind it and through it as the door opens.

06

CSS Custom Properties as Animation Targets

Each limb group in the SVG figure — .arm1, .wrist1, .leg2, .calf2, and so on — has transform: var(--transform-arm1) and a matching transition: transform calc(var(--walking-duration)*1ms) ease-in-out. JavaScript defines a states object where each key is a named animation state and each value is a map of CSS custom property names to target values. The update(s) function iterates that map and calls button.style.setProperty(k, v), which triggers all the CSS transitions simultaneously.

07

The Click Sequence — Walk, Door, and Slam

Clicking the button while in the default or hover state begins a setTimeout chain. First, 'clicked' is added and the figure advances to the walking1 state. After its --figure-duration elapses, 'door-slammed' is added and the figure transitions to walking2. The door's rotateY(35deg) open state then snaps back to rotateY(0) via a delayed transition, simulating a slam. Finally the falling sequence begins.

08

The Falling Exit Animation

When the falling class is added, the figure transitions from bottom: 5px to bottom: -1080px over the --figure-duration with a cubic-bezier(0.7, 0.1, 1, 1) acceleration curve — mimicking gravity. At the same time, animation: spin 1000ms infinite linear makes the figure tumble. Opacity fades to 0 at 75% of the duration. After a final 1-second wait, all classes are removed and the component resets to its default state ready for the next click.

⚠️ Timing Chain Tip: The setTimeout durations in the click handler are derived from the CSS custom property values defined in the states object (e.g. states['walking1']['--figure-duration'] * 1). If you adjust the walking speed, always update the value in the states object — the timer will follow automatically. Never hard-code the delay separately or the animation will desync.

Customization Ideas

Both components are deliberately minimal at their core, making them easy to drop into existing projects or extend with new behavior. Here are practical ideas for both the toggle and the logout button.

Theming the Toggle Switch

  • Persist the preference — After toggling, save the current mode to localStorage.setItem('theme', dark ? 'dark' : 'light') and read it on page load to restore the user's last choice automatically.
  • Extend to CSS custom properties — Move the theme change from the .scene element to document.documentElement (the :root) and define color tokens like --bg, --text, and --border under both theme classes. Every styled element on the page will then automatically recolor on toggle.
  • System preference detection — Initialize the dark variable using window.matchMedia('(prefers-color-scheme: dark)').matches so the component respects the user's OS-level setting on first load.
  • Change the accent colors — The light scene uses #f4f7ff and the dark scene uses #1f2335. Swap these for any two contrasting colors to theme the toggle for your own brand palette.

Extending the Logout Button

  • Replace the label text — Change "Log Out" to any action label like "Exit", "Leave Room", or "Disconnect". The figure animation is content-agnostic and will work with any verb.
  • Add a confirmation step — On first click, show a small tooltip or popover asking "Are you sure?" and only begin the walk animation on a second confirmation click. This keeps the comedic exit for the final action.
  • Change the figure fill color — The stick figure uses fill: #4371f7. Replace this with any brand color, a gradient defined in an SVG <defs>, or even an animated color via a CSS keyframe on the fill property.
  • Add more walking states — Insert additional entries into the states object to make the figure pause, wave, or stumble before reaching the door. The --figure-duration custom property controls how long the transition takes, so you can make intermediate states as brief or dramatic as you want.
  • Swap the exit animation — Instead of falling, make the figure shrink to zero with transform: scale(0) or teleport away with a flash keyframe on the .bang SVG paths already included in the markup.
💡 Tip: The hover and mouse-leave states on the logout button already provide a subtle "ready to walk" pose. This pattern — previewing the upcoming animation on hover — is a UX technique called an anticipation animation and is widely used in game UI and interactive product design to hint that something interesting will happen.

Browser Compatibility

Every technique in this project — CSS transitions, keyframe animations, CSS custom properties, transform on SVG elements, and classList manipulation — is fully supported across all modern browsers with no vendor prefixes required.

Browser CSS Transitions & Custom Props SVG Transform Animation Overall Support
Chrome / Edge Yes Yes Full
Firefox Yes Yes Full
Safari (macOS & iOS) Yes Yes Full
Samsung Internet Yes Yes Full
Internet Explorer 11 No (custom props) Partial Not supported
💡 Note: Internet Explorer 11 does not support CSS custom properties (CSS variables), which are central to both the theme switching and the logout button's limb animation system. As IE11 is effectively retired as of 2022, this is not a practical concern for any new project in 2026.

Performance & Responsiveness

Both components are exceptionally lightweight. There are no external animation libraries, no CSS preprocessors, and no runtime dependencies beyond a Boxicons CDN link for the sun and moon icons.

  • GPU-composited properties only: The toggle thumb uses transform: translateX() and the icons use opacity and transform — the browser promotes these to their own compositor layer and animates them entirely on the GPU, avoiding layout recalculation entirely.
  • SVG over raster: The logout button figure and door are inline SVG, meaning they scale crisply to any display density (including HiDPI / Retina screens) with zero additional HTTP requests and zero image file weight.
  • Minimal scripting footprint: The entire JavaScript for both components is under 60 lines. There are two event listeners and a handful of setTimeout calls — essentially no CPU overhead during idle states.
  • Instant first paint: Both components render with CSS only (no JS needed for their initial visual state), so they appear correctly even before the JavaScript event listeners are attached.
  • Responsive by default: The toggle and button are sized in fixed pixels that work well across viewports. For mobile use, wrap them in a flex or grid container to reflow as needed. The -webkit-tap-highlight-color: transparent property is already set on both interactive elements to remove the default mobile tap flash.
💡 Key Takeaway: Using CSS custom properties as the animation target instead of directly animating SVG attributes means the browser handles interpolation natively via CSS transitions — this is significantly more performant than updating SVG attributes frame by frame with JavaScript and requestAnimationFrame.

Frequently Asked Questions

How does the day/night toggle switch work with CSS?
The toggle switch is a pill-shaped button containing a circular thumb. When clicked, a JavaScript listener toggles between the light-mode and dark-mode classes on the parent .scene element. CSS selectors like .dark-mode .thumb then change the thumb's translateX position from 0 to 26px, the scene background color, and the opacity and scale of the sun and moon icons — all driven by CSS transitions, with no extra JavaScript needed for the visuals.
How do the sun and moon icons animate when switching themes?
Both icons sit stacked inside the .thumb element using position: absolute. In light mode, the sun has opacity: 1 and scale(1) rotate(0deg) while the moon has opacity: 0 and scale(0.5) rotate(-90deg). When dark mode activates, the CSS rules reverse: the sun fades out and rotates away while the moon scales up and rotates into position. Both transitions run simultaneously via transition: opacity 0.3s, transform 0.4s on each icon, creating a seamless cross-fade swap effect.
How is the animated logout button built without a JavaScript animation library?
The logout button uses three inline SVG layers — a static doorway, an animated stick figure, and an interactive door — all stacked with absolute positioning. The figure's limb movements are controlled by CSS custom properties like --transform-arm1 and --transform-leg1. JavaScript updates these properties in sequence via a states object and setTimeout chains, simulating a walking cycle, door interaction, and falling exit — no animation library required. The CSS transition on each limb's transform handles all the smooth interpolation automatically.
Can I use this day/night toggle in a real project to switch themes?
Absolutely. To use it for full-page theming, move the light-mode and dark-mode class swap from .scene to document.documentElement (the html element) and define your CSS custom properties — colors, backgrounds, borders — under .dark-mode and .light-mode selectors. The toggle button logic stays identical. Add a localStorage read on page load to remember the user's preference between visits.
What CSS techniques are used to animate the stick figure's limbs?
Each limb group (.arm1, .wrist1, .leg2, etc.) is an SVG <g> element with transform: var(--transform-arm1) and a corresponding transition: transform calc(var(--walking-duration)*1ms) ease-in-out. JavaScript updates the custom property value via button.style.setProperty(k, v). Because CSS transitions watch for changes to the computed transform value, each limb smoothly animates to its new position without any Web Animations API or GSAP calls. Every pose is defined as a named entry in the states object, making it easy to add or modify poses.
Is this project beginner-friendly?
The theme toggle is one of the best beginner CSS exercises — it teaches class toggling, CSS transitions, and the cascade in a visual and immediately satisfying way. The logout button is more advanced due to its SVG structure and sequential animation states, but the core pattern (setting CSS custom properties with JavaScript to drive transitions) is easy to grasp once you've traced through the states object and the update() function. Both components are fully self-contained in a single HTML file with no build tools, so beginners can open the file directly in a browser and see results instantly.

Conclusion

This project packs two complete, production-quality UI components into a single HTML file and demonstrates just how expressive pure CSS and vanilla JavaScript can be without reaching for a framework. The day/night toggle shows how a single class swap cascades into a full-page visual transformation — a pattern that scales from simple prototypes to complex design systems. The animated logout button pushes further, turning inline SVG and CSS custom properties into a mini animation engine capable of sequenced, character-driven motion.

The underlying patterns here — theme-class cascades, CSS custom property animation, SVG z-index layering, and timed state transitions — are reusable building blocks. You'll find variations of all of them in dark mode toggles for full apps, animated onboarding sequences, interactive data visualizations, and character-driven loading screens.

Want to go deeper into CSS animation? Check out the Animated Floating Action Button Menu for staggered keyframe sequencing, or the Advanced JavaScript Image Slider for GSAP-powered transitions.

Found this useful? Explore more HTML CSS JavaScript projects in the sidebar →