← Back to all tutorials

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

SelectorMeaning
.burger-checkbox:checkedWhen the hidden checkbox is toggled on
+Adjacent sibling combinator — selects the next sibling element
.burger .burger-lineThe span inside the label
::before / ::afterThe 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:

PropertyWhat It Animates
topLines sliding to center before rotating
transformLines rotating into the X shape
backgroundMiddle 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 ::before and ::after create the top and bottom lines from a single <span>
  • The :checked pseudo-class combined with sibling selectors (+ and ~) drives the entire animation
  • Transitioning top and transform separately 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