DEV Community

Cover image for Creating a button menu using HTML, CSS and JavaScript
Andrew Baisden
Andrew Baisden

Posted on

Creating a button menu using HTML, CSS and JavaScript

You will be creating a button menu that has a hover state and also allows you to select a button when you click on it. The final project can be seen in this Codepen.

Step 1

Setup a project on your local computer and then open it in your code editor. In the root folder create files for index.html styles.css and index.js

Step 2

Copy and paste the code into their corresponding files


<!DOCTYPE html>
<html lang="en">
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Button Menu</title>
        <link rel="stylesheet" href="styles.css" />
            <div class="menu">
                <button class="btn-menu selected">One</button>
                <button class="btn-menu">Two</button>
                <button class="btn-menu">Three</button>
                <button class="btn-menu">Four</button>
                <button class="btn-menu">Five</button>

        <script src="index.js"></script>
Enter fullscreen mode Exit fullscreen mode


@import url(';700&display=swap');

:root {
    --main-bg: #EEEEEE;
    --menu-bg: #17C0EB;
    --menu-font-color: #FFFFFF;
    --menu-border: #25d3ff;
    --menu-bg-selected: #333333;
    --menu-bg-hover: #52dcff;
    --menu-bg-selected-chevron: #3cac1a;

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;

html {
    font-size: 62.5%;

body {
    font-size: 1.6rem;
    font-family: 'Asap Condensed', sans-serif;
    background: var(--main-bg);

main {
    margin: 5rem auto;

.menu {
    margin: 0 auto;
    display: flex;
    flex-flow: column wrap;
    width: 80rem;
    max-width: 100%;
    border-radius: 2rem;
    background: var(--menu-bg);

.btn-menu {
    position: relative;
    cursor: pointer;
    background: var(--menu-bg);
    border: none;
    padding: 2rem;
    color: var(--menu-font-color);
    font-weight: 700;
    border-top: 0.1rem solid var(--menu-border);
    border-bottom: 0.1rem solid var(--menu-border);
    transition: background 1s;

.btn-menu:hover {
    background: var(--menu-bg-hover);

.btn-menu:focus {
    outline: none;
    box-shadow: none;

.selected {
    background: var(--menu-bg-selected);

.selected::before {
    position: absolute;
    left: 0;
    top: 0;
    content: "";
    background: var(--menu-bg-selected-chevron);
    height: 5.6rem;
    width: 0.5rem;
Enter fullscreen mode Exit fullscreen mode


const btnMenu = Array.from(document.querySelectorAll('.btn-menu'));

btnMenu.forEach((btns) => {
    btns.addEventListener('click', () => {
        btnMenu.forEach((btns) => {
Enter fullscreen mode Exit fullscreen mode

Step 3

Open the index.html file in a web browser or if you are using Visual Studio Code you can use the Live Server extension to make it run on a server.

Discussion (4)

thinkverse profile image
Kim Hallberg

Nice, but if I could make one small suggestion, it would be to add a background color to the :focus state since if I'm using tab I cannot see which button I'm currently on. 🤔

:root {
    --menu-bg-focus: #14819c;

.btn-menu:focus {
    background: var(--menu-bg-focus);

Other than that small suggestion, really like the menu. 👍 🔥

andrewbaisden profile image
Andrew Baisden Author • Edited on

I tested your code it works however it appears to behave differently depending on the browser.

Chrome: Tabbing works however the background colour keeps the focus colour on the selected button unless you click somewhere on the page a second time.

Firefox: Tabbing seems to work properly

Safari: I don't know if the browser supports tabbing? I could only get it to go to the search bar?

thinkverse profile image
Kim Hallberg

Tabbing on safari works just fine for me might have something to do with the OS and accessibility settings, I've messed around with mine a bit, might've toggled something on or off that makes it work for me, haven't tested it with the native macOS VoiceOver but I know buttons have built-in roles that get read out, mainly mentioned it for visual indication, it's a good practice to keep in mind. 🙂

jayesht profile image

Good one. Thanks for sharing 😄