Hamburger Button
An animated hamburger button that smoothly toggles between menu and close (X) states.
1. Copy the component file
Create a new file called hamburger-button.jsx in
your reusable components folder (for example
/src/components/) and paste the following code
into it.
hamburger-button.jsx
import { memo } from "react";
import styles from "./hamburger-button.module.css";
const HamburgerButton = (props) => {
const {
size = 24,
active = false,
className,
style,
...restProps
} = props;
const _size = Math.max(16, size);
return (
<button
aria-label="Toggle menu"
aria-expanded={active}
{...restProps}
className={[
className,
styles["hamburger-button"],
active ? styles["active"] : "",
].join(" ")}
style={{
...style,
"--size": `${_size}px`,
}}
>
<span aria-hidden={true} />
<span aria-hidden={true} />
<span aria-hidden={true} />
<span aria-hidden={true} />
<span aria-hidden={true} />
</button>
)
};
export default memo(HamburgerButton); 2. Copy the CSS module file
In the same folder, create a file called hamburger-button.module.css and paste the following CSS.
hamburger-button.module.css
.hamburger-button {
--background-color: #fbfbfb;
--border-color: #eeeeee;
--stroke-color: #111111;
--size: 24px;
@media (prefers-color-scheme: dark) {
--background-color: #1d1d1d;
--border-color: #222222;
--stroke-color: #f5f5f5;
}
position: relative;
width: var(--size);
height: var(--size);
background: var(--background-color);
border: 1px solid var(--border-color);
border-radius: 2px;
overflow: hidden;
cursor: pointer;
>span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 65%;
height: 2px;
background: var(--stroke-color);
&:nth-child(1) {
top: 30%;
transition: left 400ms ease 350ms;
}
&:nth-child(2) {
transition: left 400ms ease 250ms;
}
&:nth-child(3) {
transition: left 400ms ease 150ms;
top: 70%;
}
&:nth-child(4),
&:nth-child(5) {
transition:
left 250ms ease-in-out 0ms,
transform 250ms ease-in-out 0ms;
left: 150%;
}
}
&:disabled {
cursor: initial;
}
&.active {
span {
&:nth-child(1) {
left: -150%;
transition: left 400ms ease 300ms;
}
&:nth-child(2) {
left: -150%;
transition: left 400ms ease 200ms;
}
&:nth-child(3) {
left: -150%;
transition: left 400ms ease 100ms;
}
&:nth-child(4),
&:nth-child(5) {
left: 50%;
transition:
transform 300ms ease 350ms,
left 300ms ease 350ms;
}
&:nth-child(4) {
transform: translate(-50%, -50%) rotate(45deg);
}
&:nth-child(5) {
transform: translate(-50%, -50%) rotate(-45deg);
}
}
}
} 3. Use the component
Now you can import and use the component anywhere in your project.
hamburger-button-preview.jsx
import HamburgerButton from "@/components/interactions/hamburger-button/hamburger-button";
import { useState } from "react";
const HamburgerButtonPreview = () => {
const [active, setActive] = useState(false);
return (
<HamburgerButton
size={48}
active={active}
onClick={() => setActive(!active)}
/>
)
};
export default HamburgerButtonPreview; Props
Configure the component with the following props:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| size | number | No | 24 | Controls the width and height of the hamburger icon in pixels. |
| active | boolean | No | false | When true, the hamburger transforms into a a close (X) icon. |
| onClick | (event: React.MouseEvent) => void | No | — | Callback fired when the button is clicked. |
| disabled | boolean | No | false | Disables the button interaction. |
| aria-label | string | No | "Toggle menu" | Accessible label describing the button action for screen readers. |
| aria-controls | string | No | — | The id of the menu element that this button controls. |
| className | string | No | — | Optional CSS class names applied to the component for custom styling. |
| style | React.CSSProperties | No | — | Inline styles applied to the root element. |