Raddy Website Design & Development Tutorials

How to re-create Apple’s mobile menu

By Raddy in CSS / JavaScript ·

In this tutorial, you will learn how to re-creat Apple’s drop-down menu using HTML5, JS & CSS3. The menu is not identical, but super close to the original.

To centre the logo properly you might want to create three columns and centre align the logo in the middle.

If you have any questions please don’t hesitate to ask.

See the Pen Re-create Apple’s Mobile Menu by Radoslav Angelov (@Raddy) on CodePen.

Html + JS

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" media="all" href="/css/style.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>
</head>
<body>
    
    <header>
  
        <div class="row container">

            <div class="col-6">
                <div class="menu">
                    <a href="#">
                    <span>Menu</span>
                    </a>
                </div>
            </div>

            <div class="col-6 logo">
                <a href="#"><img src="images/logo.svg" alt="Logo"></a>
            </div>
   
            <ul class="dropdown">
                <li><a href="#">Mac</a></li> 
                <li><a href="#">iPad</a></li>
                <li><a href="#">iPhone</a></li>
                <li><a href="#">Watch</a></li>
                <li><a href="#">TV</a></li>
                <li><a href="#">Music</a></li>
                <li><a href="#">Support</a></li>
            </ul>

        </div>
    </header>

    <main>
        <img src="/images/undraw_noted_pc9f.svg" alt="Undraw">
    </main>

    <script>

    document.querySelector(".menu").addEventListener("click", toggleMenu);
    let menuLink = document.querySelector(".menu a");
    let dropDown = document.querySelector('ul.dropdown');
    let header = document.querySelector("header");
    let isOpen = 0;

    function toggleMenu() {
        if(isOpen == 0) {
            menuLink.classList.toggle("active");
            header.classList.add("black");
            isOpen++;
        }
        else {
            menuLink.classList.toggle("active");
            header.classList.remove("black");
            isOpen--;
        }
    }

    </script>
</body>
</html>

SCSS

@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro&display=swap');

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    background: #fff;
    color:#fff;
    font-size: 17px;
    font-family: 'Source Sans Pro', sans-serif;
}

.col-6 {
    float: left;
    text-align: left;
    width: 50%;
}

.row::after {
    content: "";
    clear: both;
    display: table;
}

img {
    width: 100%;
    height: auto;
    max-width: 600px;
}

header{
    max-width: 1920px;
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 1;
    background: #313131;
    height: 44px;
    overflow: hidden;
    transition: all 350ms ease-in;

    &.black {
        background-color: #000;
        height: 400px;

    }

    .logo {
        padding: 6px;
        img {
            max-width: 15.67px;
        }

    } 

    .container {
        position: relative;
        margin: 0 auto;
        width: auto;
        max-width: 1190px;
    }

    .menu {
        position: relative;
        padding: 18px 15px 0;
        float: left;
        a{
            width: 20px;
            height: 20px;
            display: block;
            position: relative;
            span {
     
                width: 100%;
                position: absolute;
                text-indent: -9999em;
                transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
   
                &:before, &:after {
                    content: '';
                    height: 1px;
                    background: #fff;
                    width: 100%;
                    position: absolute;
                    top: 0px;
                    left: 0;
                    transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
                }
                &:after {
                    top: 6px;
                }
            }
            &.active span {
                background-color: transparent;
                &:before {
                    transform: translateY(4px) translateX(1px) rotate(45deg);
                  }
                  &:after {
                    transform: translateY(-2px) translateX(1px) rotate(-45deg);
                  }
            }
        }
    }

    ul.dropdown {
        width: 100%;
        margin: 0;
        list-style: none;
        height: 0;
        clear: both;
        padding: 30px;
        
        li {
            width: 100%;
            height: 44px;
            a {
                font-size: 1em;
                color:#fff;
                text-decoration: none;
            }
        }

        li:not(:last-child) {
            border-bottom: 1px solid #232323;
        }
    }

}

main {
    text-align: center;
    padding: 4em;
    background-color: #FAFAFA;
}
  1. Martinfdez says:

    Congrats! Loved it. Is it possible to add a line in the JS code in order to close the menu when a link is clicked?

    1. Raddy says:

      The way I was looking at it is if you click on one of the links it will open another page and then the menu will be closed anyway. I guess you are doing a single page application?

  2. Martinfdez says:

    Yes, Raddy! The menu link to different sections in the same page.

    1. Raddy says:

      Maybe you can add an event listener to the dropdown like this:

      document.getElementsByClassName(“dropdown”)[0].addEventListener(“click”, toggleMenu);

  3. Martinfdez says:

    It worked!
    document.querySelector(“.dropdown”).addEventListener(“click”, toggleMenu);
    //document.getElementsByClassName(“dropdown”)[0].addEventListener(“click”, toggleMenu);

    Thank you!

    1. Raddy says:

      I am glad that it worked! Thank you for visiting my blog 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.