Dark CSS

Animated Navigation Menu Bar using Html CSS

Facebook
Twitter
WhatsApp

code preview

Folder Structure:

  • Firstly we will create a main folder for our project
  • Then inside it we will create a two files index.html and style.css

Introduction:

In this tutorial, we’ll create a sleek and an animated navigation menu bar using HTML  CSS. The menu will feature a sliding bar effect that dynamically highlights the selected menu option, providing a modern and polished look. We’ll use radio inputs and labels creatively to manage state changes without JavaScript. This approach ensures a lightweight design while maintaining an engaging user experience. Additionally, we’ll style the menu for smooth transitions and responsive behavior.

Animated navigation menu bar

Html Code:

....

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div class="wrappper">
        <input hidden="" class="radio-1" name="radio" id="radio-1" type="radio" checked="" />
        <label style="--index: 0;" class="label" for="radio-1"><span>Home</span></label>

        <input hidden="" class="radio-2" name="radio" id="radio-2" type="radio" />
        <label style="--index: 1;" class="label" for="radio-2"><span>Blog</span></label>

        <input hidden="" class="radio-3" name="radio" id="radio-3" type="radio" />
        <label style="--index: 2;" class="label" for="radio-3"><span>About us</span></label>

        <input hidden="" class="radio-4" name="radio" id="radio-4" type="radio" />
        <label style="--index: 3;" class="label" for="radio-4"><span>Contact</span></label>

        <div class="bar"></div>
        <div class="slidebar"></div>
    </div>
</body>

</html>
...

Explanation:

Inside <body>, a <div> with the class wrappper acts as the container for the navigation menu. Within this wrapper, four hidden <input> elements of type “radio” are used to create a state for each menu item.

These inputs are given unique IDs (radio-1, radio-2, etc.) and share the same name attribute, ensuring only one can be selected at a time.

Next, <label> elements represent the clickable menu items. Each label is associated with an input via the for attribute, which matches the ID of the corresponding radio button. Inline styles like --index: 0 are used to manage custom properties for animations or effects.

The <span> inside each label contains the text for the menu options, such as “Home,” “Blog,” “About us,” and “Contact.” Below the inputs and labels, two additional <div> elements, bar and slidebar, are added.

These are used to create the sliding effect and highlight the selected menu item. The bar acts as a decorative border, while the slidebar represents the main background of the selected option. Both are positioned absolutely to allow smooth transitions.

CSS Code:

....
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    font-family: Verdana, Geneva, Tahoma, sans-serif;
}

html,
body {
    display: grid;
    height: 100%;
    place-items: center;
    background-color: #212121;
}

/* main style */
.wrappper {
    display: flex;
    align-items: center;
    padding: 4px 8px;
    position: relative;
    background: #e8e8e8;
    border-radius: 10px;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    top: 0;
    z-index: 1;
}

.wrappper input {
    height: 0;
    width: 0;
    position: absolute;
    overflow: hidden;
    display: none;
    visibility: hidden;
}

.label {
    cursor: pointer;
    outline: none;
    font-size: 0.875rem;
    letter-spacing: initial;
    font-weight: 500;
    color: #212121;
    background: transparent;
    padding: 12px 16px;
    width: 100px;
    min-width: 100px;
    text-decoration: none;
    -webkit-user-select: none;
    user-select: none;
    transition: color 0.25s ease;
    outline-offset: -6px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 2;
    -webkit-tap-highlight-color: transparent;
}

.label span {
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
}

.wrappper input[class*="radio-"]:checked+label {
    color: #000;
}

.bar {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    position: absolute;
    transform-origin: 0 0 0;
    height: 100%;
    width: 100px;
    z-index: 0;
    transition: transform 0.5s cubic-bezier(0.33, 0.83, 0.99, 0.98);
}

.bar::before,
.bar::after {
    content: "";
    position: absolute;
    height: 4px;
    width: 100%;
    background: #212121;
}

.bar::before {
    top: 0;
    border-radius: 0 0 9999px 9999px;
}

.bar::after {
    bottom: 0;
    border-radius: 9999px 9999px 0 0;
}

.slidebar {
    position: absolute;
    height: calc(100% - (4px * 4));
    width: 100px;
    border-radius: calc(10px - 4px);
    background: #b8b8b8;
    transform-origin: 0 0 0;
    z-index: 0;
    transition: transform 0.5s cubic-bezier(0.33, 0.83, 0.99, 0.98);
}

.radio-1:checked~.bar,
.radio-1:checked~.slidebar,
.radio-1+label:hover~.slidebar {
    transform: translateX(0) scaleX(1);
}

.radio-2:checked~.bar,
.radio-2:checked~.slidebar,
.radio-2+label:hover~.slidebar {
    transform: translateX(100%) scaleX(1);
}

.radio-3:checked~.bar,
.radio-3:checked~.slidebar,
.radio-3+label:hover~.slidebar {
    transform: translateX(200%) scaleX(1);
}

.radio-4:checked~.bar,
.radio-4:checked~.slidebar,
.radio-4+label:hover~.slidebar {
    transform: translateX(300%) scaleX(1);
}

...

Explanation:

The CSS code begins with a universal selector *, which resets the default padding, margin, and box-sizing for all elements to ensure consistent styling across browsers.

The html and body elements are styled to display as a grid and center their content both vertically and horizontally, with a dark background color (#212121) for a modern look.

The .wrappper class is the container for the navigation menu. It uses flexbox to align its child elements and has padding and a light grey background (#e8e8e8). The border-radius: 10px gives it smooth, rounded corners, while overflow-x: auto and scrollbar-width: none ensure the menu remains responsive and scrollable without a visible scrollbar.

The hidden radio inputs inside .wrappper are completely removed from view using properties like height: 0, width: 0, and visibility: hidden. These inputs control the selected state of the navigation options.

The .label class styles each menu option. It gives the labels a pointer cursor for interactivity, sets a medium font size, and centers the text using flexbox. A padding of 12px 16px ensures spacing, and width: 100px standardizes the size of each label. Transitions are applied to color changes for a smooth hover and focus effect.

The .label span ensures that the text inside each label is displayed neatly in one line, even if it’s too long, by using -webkit-line-clamp and -webkit-box.

When a radio input is checked, the corresponding label is styled with color: #000, indicating the active state. This is achieved using the sibling selector input[class*="radio-"]:checked + label.

The .bar class creates a decorative top and bottom border around the navigation items. It uses ::before and ::after pseudo-elements to add these borders, each styled with height: 4px, a dark background (#212121), and rounded edges.

The .slidebar class defines the sliding highlight effect. It is positioned absolutely and matches the dimensions of the labels. Its background (#b8b8b8) contrasts slightly with the main container, and it transitions smoothly between positions using transform and cubic-bezier for a custom easing effect.

For each radio input (e.g., .radio-1, .radio-2), CSS transforms are used to shift the .bar and .slidebar to align with the selected label. For example, .radio-1 aligns the elements to the first label, .radio-2 to the second, and so on. The transition effects ensure a fluid animation as the user navigates between options.

Source Code:

Download “Animated-Navigation-Menu.zip” Animated-Navigation-Menu.zip – Downloaded 81 times – 1.83 KB

Conclusions:

In this project, we created a modern and interactive navigation menu using only HTML and CSS, showcasing a sleek sliding highlight effect. We used radio buttons to handle the state of menu selection without any JavaScript, keeping the implementation lightweight. Labels were styled as clickable menu options, linked to hidden inputs for seamless user interaction. A sliding bar and background element were added to enhance the visual appeal of the menu. Smooth transitions and responsive design ensured that the navigation works beautifully across different devices and screen sizes.