Animating Burger Nav Icon
Transform a hamburger menu icon into an X (close) icon using pure CSS transitions and the checkbox hack — no JavaScript needed.
Animating Burger Nav Icon
The hamburger menu icon (three horizontal lines) is one of the most common UI elements on the web. In this episode you will learn how to animate it into an X (close) icon using only CSS — no JavaScript required.
The Checkbox Hack
Since CSS cannot track "click" events, we use a hidden checkbox to toggle state. When the checkbox is checked, CSS sibling selectors transform the burger lines into an X.
<input type="checkbox" id="burger-toggle" class="burger-checkbox">
<label for="burger-toggle" class="burger">
<span class="burger-line"></span>
</label>
We only need one <span> for the middle line. The top and bottom lines will be created with ::before and ::after pseudo-elements.
Hiding the Checkbox
.burger-checkbox {
display: none;
}
The checkbox is visually hidden but still functional. Clicking the <label> toggles its checked state.
Styling the Burger Icon
.burger {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
cursor: pointer;
position: relative;
}
.burger-line {
width: 30px;
height: 3px;
background: #333;
border-radius: 2px;
position: relative;
transition: background 0.3s ease;
}
/* Top line */
.burger-line::before {
content: "";
position: absolute;
width: 30px;
height: 3px;
background: #333;
border-radius: 2px;
top: -9px;
left: 0;
transition: top 0.3s ease, transform 0.3s ease;
}
/* Bottom line */
.burger-line::after {
content: "";
position: absolute;
width: 30px;
height: 3px;
background: #333;
border-radius: 2px;
top: 9px;
left: 0;
transition: top 0.3s ease, transform 0.3s ease;
}
The three lines are the ::before pseudo-element (top), the .burger-line span (middle), and the ::after pseudo-element (bottom). They are spaced 9px apart using absolute positioning.
The X Transform on Checked
/* Hide middle line */
.burger-checkbox:checked + .burger .burger-line {
background: transparent;
}
/* Rotate top line to form one half of the X */
.burger-checkbox:checked + .burger .burger-line::before {
top: 0;
transform: rotate(45deg);
}
/* Rotate bottom line to form the other half of the X */
.burger-checkbox:checked + .burger .burger-line::after {
top: 0;
transform: rotate(-45deg);
}
When the checkbox is checked, three things happen simultaneously. The middle line fades out by becoming transparent. The top line moves down to center (top: 0) and rotates 45 degrees clockwise. The bottom line moves up to center (top: 0) and rotates 45 degrees counter-clockwise. Together they form an X shape.
How the CSS Selectors Work
| Selector | Meaning |
|---|---|
.burger-checkbox:checked | When the hidden checkbox is toggled on |
+ | Adjacent sibling combinator — selects the next sibling element |
.burger .burger-line | The span inside the label |
::before / ::after | The top and bottom lines created with pseudo-elements |
Adding a Smooth Transition
The transition properties we set earlier on .burger-line, ::before, and ::after handle the smooth animation. The key transitions are:
| Property | What It Animates |
|---|---|
top | Lines sliding to center before rotating |
transform | Lines rotating into the X shape |
background | Middle line fading to transparent |
All transitions use 0.3s ease for a snappy but smooth feel.
Optional: Adding Color Change on Active
.burger-checkbox:checked + .burger .burger-line::before,
.burger-checkbox:checked + .burger .burger-line::after {
background: #e74c3c;
}
This changes the X color to red when active, giving the user a visual cue that closing will happen.
Integrating with a Navigation Menu
<input type="checkbox" id="burger-toggle" class="burger-checkbox">
<label for="burger-toggle" class="burger">
<span class="burger-line"></span>
</label>
<nav class="mobile-nav">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</nav>
.mobile-nav {
max-height: 0;
overflow: hidden;
transition: max-height 0.4s ease;
}
.burger-checkbox:checked ~ .mobile-nav {
max-height: 300px;
}
Using the general sibling combinator (~), the same checkbox that toggles the burger icon also slides open the navigation menu.
Key Takeaways
- The checkbox hack uses a hidden
<input type="checkbox">and a<label>to create toggle behavior without JavaScript - Pseudo-elements
::beforeand::aftercreate the top and bottom lines from a single<span> - The
:checkedpseudo-class combined with sibling selectors (+and~) drives the entire animation - Transitioning
topandtransformseparately creates a two-step animation — lines slide to center, then rotate - The same checkbox can control both the icon animation and a slide-out navigation menu