DEV Community

Seppe Gadeyne
Seppe Gadeyne

Posted on • Updated on

Crafting a mobile menu with Tailwind CSS without JavaScript

Welcome to this blog post, where I'll walk you through building a mobile menu using only Tailwind CSS and HTML, without JavaScript. This approach is excellent for enhancing website performance, as minimizing the use of JavaScript can help your site load faster. You can check out a live example of this technique on my website. Let's get started!

Using peer-* from Tailwind CSS for animations and state

To create the animations for our mobile menu, we'll utilize the peer-* utility from Tailwind CSS. This allows us to control the state of a sibling element, like an <input> element of the type checkbox. By placing all HTML elements within the <label> element, we can make them dependent on the state of the <input> element. We will then hide the <input> element and make the <label> element respond to touch or cursor.

<label class="relative z-40 cursor-pointer px-3 py-6" for="mobile-menu">
   <input class="peer hidden" type="checkbox" id="mobile-menu" />
</label>
Enter fullscreen mode Exit fullscreen mode

Creating the hamburger icon with before: and after: pseudo-elements

To craft the hamburger icon, we'll use the before: and after: pseudo-elements. We'll start with a <div> element with a height of 1px and a width equal to the w-7 value. In this example, the middle line is set to transparent, so we only see the lines from before: and after:

<label class="relative z-40 cursor-pointer px-3 py-6" for="mobile-menu">
    <input class="peer hidden" type="checkbox" id="mobile-menu" />
    <div
        class="relative z-50 block h-[1px] w-7 bg-black bg-transparent content-[''] before:absolute before:top-[-0.35rem] before:z-50 before:block before:h-full before:w-full before:bg-black before:transition-all before:duration-200 before:ease-out before:content-[''] after:absolute after:right-0 after:bottom-[-0.35rem] after:block after:h-full after:w-full after:bg-black after:transition-all after:duration-200 after:ease-out after:content-[''] peer-checked:bg-transparent before:peer-checked:top-0 before:peer-checked:w-full before:peer-checked:rotate-45 before:peer-checked:transform after:peer-checked:bottom-0 after:peer-checked:w-full after:peer-checked:-rotate-45 after:peer-checked:transform"
    >
    </div>
</label>
Enter fullscreen mode Exit fullscreen mode

Completing the mobile menu with additional elements

Now, let's add more elements to complete the mobile menu:

  • A full-screen background with a backdrop blur filter
  • A <div> element for the menu items with an animation, which scrolls the menu from right to left
  • The menu itself, using a <menu> element (which functions like a <ul> element, but is better for semantics in HTML)
<label class="relative z-40 cursor-pointer px-3 py-6" for="mobile-menu">
    <input class="peer hidden" type="checkbox" id="mobile-menu" />
    <div
        class="relative z-50 block h-[1px] w-7 bg-black bg-transparent content-[''] before:absolute before:top-[-0.35rem] before:z-50 before:block before:h-full before:w-full before:bg-black before:transition-all before:duration-200 before:ease-out before:content-[''] after:absolute after:right-0 after:bottom-[-0.35rem] after:block after:h-full after:w-full after:bg-black after:transition-all after:duration-200 after:ease-out after:content-[''] peer-checked:bg-transparent before:peer-checked:top-0 before:peer-checked:w-full before:peer-checked:rotate-45 before:peer-checked:transform after:peer-checked:bottom-0 after:peer-checked:w-full after:peer-checked:-rotate-45 after:peer-checked:transform"
    >
    </div>
    <div
        class="fixed inset-0 z-40 hidden h-full w-full bg-black/50 backdrop-blur-sm peer-checked:block"
    >
        &nbsp;
    </div>
    <div
        class="fixed top-0 right-0 z-40 h-full w-full translate-x-full overflow-y-auto overscroll-y-none transition duration-500 peer-checked:translate-x-0"
    >
        <div class="float-right min-h-full w-[85%] bg-white px-6 pt-12 shadow-2xl">
            <menu>
                <li><a href="/">Home</a></li>
                <li><a href="/contact">Contact</a></li>
            </menu>
        </div>
    </div>
</label>
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this blog post, we've successfully built a lightweight mobile menu using Tailwind CSS and HTML without JavaScript. This approach is crucial for optimizing your website's load speed and ranking higher in search engines. So try and experience the benefits of a more performant, JavaScript-free mobile menu.

Top comments (7)

Collapse
 
stankukucka profile image
Stan Kukučka

@seppegadeyne great tutorial. I was looking for a non-js solution in Tailwind. Is it possible to modify the menu the way it will act the same as here: web3templates.com/preview/astroshi...?

Collapse
 
seppegadeyne profile image
Seppe Gadeyne

Hi @stankukucka, thank you for your feedback. It is also possible. I will make an example and add it to the tutorial later.

Collapse
 
godfreymutebi profile image
Mutebi Godfrey

if i want to change the background color from black to white . I want it to be white before and black after click.

Collapse
 
seppegadeyne profile image
Seppe Gadeyne

Hi @godfreymutebi, If you have three lines, you can do so by adjusting the background color of the before and after content + background color. So before the click, white = before:bg-white bg-white after:bg-white and then black after click = before:peer-checked:bg-black peer-checked:bg-black after:peer-checked:bg-black. I hope this can help you.

Collapse
 
godfreymutebi profile image
Mutebi Godfrey

thanks, its what i deed

Collapse
 
andberry profile image
Andrea Berardi

Thank you so much for sharing this, great post!

Collapse
 
vtuz profile image
Valeriy

Very nice solution. I'm thinking of use similar not only for menu but to separate screens of content in mobile devices.