What You'll Build

In this tutorial, you'll build an animated floating action button (FAB) menu using nothing but HTML, CSS, and a single line of JavaScript. The button sits in the corner of the screen as a glowing circle with a hamburger-style icon. When clicked, the icon smoothly morphs into a close (X) symbol, a pulsing ring radiates outward, and a card-style list of actions — Settings, Copy, Share, and Delete — scales and fades into view with a staggered cascade effect.

This is a classic CSS expandable circle menu pattern used widely in mobile apps, admin dashboards, and design systems for quick contextual actions. The entire interaction state — open or closed — is controlled by toggling a single active class on the parent container, while CSS transitions, transforms, and keyframes handle every visual change.

It's an excellent project for practicing transform-origin, animation-delay staggering, icon morphing with rotation, and box-shadow pulse effects — all without reaching for a JavaScript animation library.

💡 Who Is This For? This project is ideal for beginners who want a real, reusable UI component to add to their portfolio, and for intermediate developers looking to sharpen their understanding of CSS transitions, transforms, and keyframe sequencing without any external dependencies.

Key Features of This Floating Action Button Menu

🔵
Circular FAB Button
A glowing circular button with a soft box-shadow halo that intensifies on hover and focus for clear interactive feedback.
✖️
Hamburger-to-X Morph
Three stacked lines rotate and shift using CSS transform to seamlessly turn into a close icon when active.
💫
Pulse Ring Animation
A one-shot onePulse keyframe animates the button's box-shadow outward and back, drawing the eye on activation.
📜
Scale & Fade Reveal
The menu list scales from 0 to 1 with transform-origin: bottom right, anchoring it visually to the button.
🪄
Staggered List Items
Each menu item fades in and slides from the left with progressively longer animation-delay values for a cascading effect.
🎯
Single JS Toggle
Only one event listener is used — it simply toggles the active class on the container, leaving all visuals to CSS.
🗑️
Destructive Action Styling
The Delete item has its own hover transition — expanding to full width with a red background to visually flag a dangerous action.
🪶
Lightweight Feather Icons
Inline SVG icons (Feather-style) for Settings, Copy, Share, and Delete — no icon font or extra HTTP request needed.

Full Source Code (Free)

The project lives in a single HTML file. The CSS handles the FAB's glow, the icon morph, the pulse ring, and the staggered list reveal. The JavaScript is a single click listener that toggles the active class — every visual change is then driven entirely by CSS selectors targeting .active. Use the tabs to explore each section.

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. No libraries, no build tools — open the file in any modern browser and the menu works immediately.

How It Works — Step by Step

Here's a breakdown of the eight core techniques behind this animated floating action button menu, from the base markup to the staggered reveal animation.

01

Container & Trigger Button Structure

A .list-container with position: relative wraps the whole component. Inside it sits the circular .more-button, which contains a .menu-icon-wrapper with three short .menu-icon-line divs — the classic hamburger icon built from pure CSS rectangles.

02

Hidden List Menu Positioning

The ul.more-button-list is positioned absolutely with right: 24px; bottom: 0;, anchoring it next to the button. By default it's invisible: opacity: 0 and transform: scale(0), with transform-origin: bottom right so it grows outward from the button's corner rather than from its own center.

03

The Single JavaScript Toggle

A click listener on .more-button simply calls classList.toggle('active') on .list-container. That's the only JavaScript in the entire project — every visual state change from here on is driven purely by the presence or absence of the active class.

04

Revealing the Menu with Scale & Opacity

When .list-container.active is present, the .more-button-list rule sets opacity: 1 and transform: scale(1). Combined with the transition: all 0.3s ease 0.1s defined on the base class, the menu smoothly grows from a single point into a full card.

05

Staggering the List Items with fadeInItem

Each .more-button-list-item starts at opacity: 0 and transform: translateX(-10px). When active, the fadeInItem keyframe animation runs on every item with a base delay of 0.2s, while nth-child(2) through nth-child(4) override the delay to 0.4s, 0.6s, and 0.8s — producing the cascading entrance.

06

Morphing the Hamburger into an X

On activation, .menu-icon-wrapper rotates -45deg. At the same time, .menu-icon-line.first rotates -90deg with translateX(1px), and .menu-icon-line.last rotates -90deg with translateX(-1px). The combined rotations realign the three short lines into a clean X shape.

07

The onePulse Glow Animation

The onePulse keyframe animates the button's box-shadow in three stages: it starts at the resting glow, expands to a much larger and more transparent ring at 50%, then settles back to the resting glow at 100%. It runs once, forwards linear, only when .active is applied — giving a satisfying "ping" feedback when the menu opens.

08

Hover States & the Delete Action

Regular menu items change color to the brand blue on hover and use an ::after pseudo-element as a subtle divider line between items (hidden on the last item). The #Delete item gets its own 300ms transition, growing to width: 100% with a translucent red background on hover to clearly mark it as a destructive action.

⚠️ Transform Origin Matters: If you change the position of .more-button-list (for example, anchoring it to the top-left instead of the bottom-right of the button), make sure to update transform-origin to match. Otherwise the scale animation will grow from the wrong corner and look visually broken.

Customization Ideas

This floating action button menu is intentionally simple at its core, which makes it easy to adapt. Here are some practical ways to extend it for your own projects.

  • Change the accent color — Replace #5c67ff in .more-button and its box-shadow rules with your own brand color to instantly re-theme the component.
  • Add or remove menu items — Each .more-button-list-item is independent. Add new <li> elements with an icon and label, and increase .more-button-list's height to fit them. Remember to add a matching :nth-child() delay rule for the new item to keep the stagger smooth.
  • Anchor the FAB to the viewport — Wrap .list-container in a wrapper with position: fixed; bottom: 24px; right: 24px; to pin the button to the corner of the screen like a true mobile FAB.
  • Swap the icons — The inline SVGs use the Feather icon style. Replace the <path> data with icons from Boxicons or any other SVG icon set while keeping the same width, height, and stroke attributes.
  • Adjust the pulse intensity — Tweak the spread values inside the onePulse keyframe (e.g. 0px 0px 0px 12px) to make the ring larger, smaller, or more/less transparent.
  • Slow down or speed up the stagger — Increase or decrease the animation-delay values on each :nth-child() selector to make the cascade feel snappier or more dramatic.
  • Style the destructive action differently — Instead of an expanding red background on #Delete, try a shake animation or an icon color change to signal danger.
💡 Tip: Because the entire open/close state lives in one CSS class, you can reuse this exact pattern for tooltips, dropdown filters, or notification panels — just change what's inside .more-button-list.

Browser Compatibility

Every technique used in this floating action button menu — CSS transforms, transitions, keyframe animations, pseudo-elements, and classList.toggle() — is well-established and supported across all modern browsers.

Browser CSS Transforms & Transitions Keyframe Animations 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 Partial No Limited
💡 Note: The project relies on standard CSS3 properties only — no vendor prefixes are needed for any current browser version. Internet Explorer 11 is effectively obsolete and not a practical target for new projects in 2026.

Performance & Responsiveness

Because every animation in this component is handled by CSS — and specifically by properties the browser can composite on the GPU — it remains smooth even on lower-end devices.

  • GPU-friendly properties: transform and opacity drive the scale, fade, and rotation animations. These don't trigger layout recalculation or repaint, so the menu opens and closes at a consistent frame rate.
  • Minimal JavaScript: A single event listener with one line of code means there's virtually no scripting overhead — the browser's CSS engine does all the heavy lifting.
  • Small footprint: No external animation libraries or icon fonts are loaded; the icons are inline SVG, keeping the total page weight tiny.
  • Responsive by design: Because the component is sized in pixels relative to its container and anchored with absolute positioning, it scales predictably across mobile, tablet, and desktop viewports without extra media queries — though you can add a position: fixed wrapper for true mobile FAB behavior as described in the customization section.
  • Touch-friendly target size: The 50×50px button meets common accessibility guidelines for minimum touch target sizes, making it comfortable to tap on mobile screens.
💡 Key Takeaway: Sticking to transform, opacity, and box-shadow for animations — instead of properties like width, height, or top/left — is one of the most reliable ways to keep CSS animations smooth across devices.

Frequently Asked Questions

How do I create a floating action button that expands into a menu using CSS?
Position a circular button inside a relatively positioned container, then place an absolutely positioned list next to it with transform: scale(0) and opacity: 0 by default. Toggle an active class on the container with JavaScript when the button is clicked, and target .active .more-button-list in CSS to set transform: scale(1) and opacity: 1 with a transition. Full source code is in the tabs above.
How does the hamburger icon morph into a close (X) icon?
The menu icon is built from three short divs (lines) inside a wrapper. On the active state, the wrapper rotates -45deg, the first line rotates -90deg and shifts slightly via translateX, and the last line rotates -90deg in the opposite translateX direction. Combined, the three lines visually rearrange into an X shape — the classic hamburger-to-close animation, without swapping icons.
What is the staggered fade-in animation for the list items and how does it work?
Each list item starts with opacity: 0 and is shifted -10px horizontally via transform: translateX(-10px). When the container becomes active, the fadeInItem keyframe animation runs on every item, animating it to translateX(0) and opacity: 1. By giving each nth-child item a longer animation-delay (0.2s, 0.4s, 0.6s, 0.8s), the items appear to cascade in one after another rather than all at once.
What creates the pulsing ring effect around the button?
The onePulse keyframe animation runs once on .more-button when the container becomes active. It animates the box-shadow from the button's resting glow, out to a much larger, more transparent ring at the 50% mark, and back to the resting glow at 100%. Because box-shadow is animatable, this creates a quick radar-style pulse that draws attention to the button as the menu opens.
Is this floating action button menu suitable for beginners?
Yes. The entire interaction relies on a single JavaScript line that toggles a CSS class — everything else is CSS transitions, transforms, and keyframes. It's an excellent project for beginners who already understand basic CSS positioning and want to practice transform-origin, transitions, and animation-delay in a real, reusable UI component.
Can I use this floating action button menu in a real project?
Absolutely. This pattern is common in mobile apps and admin dashboards for quick actions like Settings, Copy, Share, and Delete. To customize it, change the SVG icons, adjust the .more-button-list width/height to fit more or fewer items, update the color variables (#5c67ff for the primary color and the red hover for destructive actions), and reposition .list-container using position: fixed to anchor it to a corner of the viewport.

Conclusion

This animated floating action button menu proves how far pure CSS can go with just a single line of JavaScript as a trigger. By combining transform-based icon morphing, a box-shadow pulse, scale-and-fade reveals, and staggered keyframe delays, you get a polished, production-ready UI component that feels every bit as smooth as one built with a JavaScript animation library.

The patterns here — toggling a single state class, anchoring transforms with transform-origin, and layering animation-delay for cascading effects — are reusable building blocks for dropdowns, tooltips, notification trays, and countless other small interactive components.

Want to keep exploring CSS animation techniques? Check out the Neon Cursor Animation for advanced pointer effects, or the Animated Button with Star Effects for more GSAP-powered micro-interactions.

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