Radial App Menu
Radial App Menu

Hy Everyone, In this tutorial, we will create a Radial App Menu. Here we will use HTML, CSS, and JavaScript to create our Radial App Menu.

The menu is used for navigation inside an app or website. It makes navigation easier. Here we are creating Radial Menu, It will be in a circle shape.

Table of Contents

Radial App Menu

We will create our Radial App Menu using HTML, CSS, and JavaScript as we mentioned earlier, so we will need three files called index.html, style.css, and script.js. Let’s start with our index.html file.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="style.css" />
    <title>Icon Animation Using CSS</title>
    <script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
    <script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@types/[email protected]/index.d.ts"></script>
    <script src="https://unpkg.com/@types/[email protected]/index.d.ts"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/classnames/2.3.1/index.min.js"></script>
    <script src="https://kit.fontawesome.com/86933bf68b.js"></script>

  </head>
  <body>
    <div id="root"></div>
    <script type="text/javascript" src="script.js"></script>
  </body>
</html>

style.css

body {
  margin: 0px;
  overflow: hidden;
  padding: 0px;
}
body input, body h1, body h2, body h3, body a {
  font-family: "Rubik", sans-serif;
  font-weight: 400;
  margin: 0px;
  padding: 0px;
}

#app {
  background-color: #2d3240;
  height: 100vh;
  overflow: hidden;
  width: 100vw;
}
#app #menu-toggle {
  background-color: white;
  border: none;
  border-radius: 8vh;
  bottom: 0px;
  box-shadow: 0px 0px 10px 4px rgba(0, 0, 0, 0.08);
  cursor: pointer;
  height: 8vh;
  left: 0px;
  margin: 2vh;
  position: fixed;
  width: 8vh;
  z-index: 3;
}
#app #menu-toggle:hover {
  background-color: #f0f0f0;
}
#app #menu-toggle i {
  color: #64b5f6;
  font-size: 2vh;
  height: 3vh;
  line-height: 3vh;
  text-align: center;
  width: 3vh;
}
#app #menu {
  height: 100vh;
  opacity: 0;
  position: absolute;
  transform: translateX(-50%);
  transition: opacity 250ms, transform 250ms;
  transition-delay: 300ms;
  width: 40vh;
}
#app #menu.toggled {
  opacity: 1;
  transform: translateX(0%);
  transition-delay: 0ms;
}
#app #menu.toggled #menu-quick-options .menu-quick-option {
  opacity: 1;
  transform: translateX(0%);
}
#app #menu.toggled #menu-quick-options .menu-quick-option:first-of-type, #app #menu.toggled #menu-quick-options .menu-quick-option:last-of-type {
  transform: translateX(-50%);
}
#app #menu.toggled #menu-full-options .menu-full-option {
  opacity: 1;
  transform: translateX(-0.5vh);
}
#app #menu.toggled #menu-full-options .menu-full-option:first-of-type, #app #menu.toggled #menu-full-options .menu-full-option:last-of-type {
  transform: translateX(-4vh);
}
#app #menu.toggled #menu-full-options .menu-full-option:nth-of-type(2), #app #menu.toggled #menu-full-options .menu-full-option:nth-of-type(4) {
  transform: translateX(-2vh);
}
#app #menu.toggled #menu-background-wrapper #menu-background:before {
  transform: translate(-50%, -50%);
  transition-delay: 200ms;
}
#app #menu #menu-background-wrapper {
  height: 100vh;
  left: 0px;
  position: absolute;
  top: 0px;
  width: 40vh;
  z-index: 1;
}
#app #menu #menu-background-wrapper #menu-background {
  background-color: #64b5f6;
  border-bottom-right-radius: 100%;
  border-top-right-radius: 100%;
  box-shadow: 0px 0px 20px 4px rgba(0, 0, 0, 0.15);
  height: 200vh;
  position: absolute;
  right: 0px;
  top: -50vh;
  width: 200vh;
}
#app #menu #menu-background-wrapper #menu-background:before {
  background-color: rgba(100, 181, 246, 0.05);
  border: 1px solid rgba(100, 181, 246, 0.2);
  border-bottom-right-radius: 100%;
  border-top-right-radius: 100%;
  content: "";
  height: 120%;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-100%, -50%);
  transition: transform 250ms;
  width: 120%;
  z-index: -1;
}
#app #menu #menu-profile-image {
  border-radius: 500px;
  box-shadow: 0px 0px 20px 4px rgba(0, 0, 0, 0.15);
  display: block;
  height: 40vh;
  left: 0px;
  object-fit: cover;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 40vh;
  z-index: 2;
}
#app #menu #menu-quick-options {
  align-items: center;
  display: flex;
  flex-direction: column;
  height: 40vh;
  justify-content: space-around;
  position: absolute;
  top: 50%;
  transform: translate(100%, -50%);
  width: 20vh;
  z-index: 3;
}
#app #menu #menu-quick-options .menu-quick-option {
  align-items: center;
  background-color: white;
  border: none;
  border-radius: 8vh;
  box-shadow: 0px 0px 10px 4px rgba(0, 0, 0, 0.08);
  cursor: pointer;
  display: flex;
  height: 8vh;
  justify-content: center;
  opacity: 0;
  padding: 0px;
  transform: translateX(-30%) scale(0.25);
  transition: opacity 150ms, transform 150ms;
  width: 8vh;
}
#app #menu #menu-quick-options .menu-quick-option:hover {
  background-color: #f0f0f0;
}
#app #menu #menu-quick-options .menu-quick-option:hover .tooltip {
  opacity: 1;
  transform: translateX(100%);
}
#app #menu #menu-quick-options .menu-quick-option:first-of-type {
  transform: translate(-80%, 30%) scale(0.5);
}
#app #menu #menu-quick-options .menu-quick-option:last-of-type {
  transform: translate(-80%, -30%) scale(0.5);
}
#app #menu #menu-quick-options .menu-quick-option i {
  color: #64b5f6;
  font-size: 2vh;
  height: 3vh;
  line-height: 3vh;
  text-align: center;
  width: 3vh;
}
#app #menu #menu-quick-options .menu-quick-option .tooltip {
  background-color: #1e1e1e;
  border-radius: 0.5vh;
  box-shadow: 0px 0px 1vh 0.25vh rgba(0, 0, 0, 0.08);
  color: white;
  font-size: 1em;
  opacity: 0;
  padding: 1vh;
  pointer-events: none;
  position: absolute;
  right: -1vh;
  transform: translateX(90%);
  transition: opacity 250ms, transform 250ms;
}
#app #menu #menu-full-options {
  align-items: flex-start;
  display: flex;
  flex-direction: column;
  height: 60vh;
  justify-content: space-around;
  left: 44vh;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 20vh;
  z-index: 2;
}
#app #menu #menu-full-options .menu-full-option {
  align-items: center;
  background-color: transparent;
  border: none;
  border-radius: 0.5vh;
  cursor: pointer;
  display: flex;
  gap: 1vh;
  opacity: 0;
  padding: 1vh;
  transform: translateX(-2vh);
  transition: opacity 150ms, transform 150ms;
}
#app #menu #menu-full-options .menu-full-option:hover {
  background-color: rgba(255, 255, 255, 0.05);
}
#app #menu #menu-full-options .menu-full-option:first-of-type, #app #menu #menu-full-options .menu-full-option:last-of-type {
  transform: translateX(-6vh);
}
#app #menu #menu-full-options .menu-full-option:nth-of-type(2), #app #menu #menu-full-options .menu-full-option:nth-of-type(4) {
  transform: translateX(-4vh);
}
#app #menu #menu-full-options .menu-full-option i, #app #menu #menu-full-options .menu-full-option h3 {
  color: white;
  font-size: 1.5vh;
  height: 2vh;
  line-height: 2vh;
}

@media (max-width: 1200px) {
  #app #menu {
    width: 30vh;
  }
  #app #menu #menu-background-wrapper {
    width: 30vh;
  }
  #app #menu #menu-profile-image {
    height: 30vh;
    width: 30vh;
  }
  #app #menu #menu-quick-options {
    width: 15vh;
  }
  #app #menu #menu-full-options {
    left: 34vh;
  }
}
@media (max-width: 800px) {
  #app #menu {
    width: 25vh;
  }
  #app #menu #menu-background-wrapper {
    width: 25vh;
  }
  #app #menu #menu-profile-image {
    height: 25vh;
    width: 25vh;
  }
  #app #menu #menu-quick-options {
    width: 12.5vh;
  }
  #app #menu #menu-quick-options .menu-quick-option {
    height: 7vh;
    width: 7vh;
  }
  #app #menu #menu-full-options {
    left: 29vh;
  }
}
@media (prefers-reduced-motion) {
  #app #menu {
    transition: none;
  }
  #app #menu #menu-quick-options .menu-quick-option {
    transition: none;
  }
  #app #menu #menu-full-options .menu-full-option {
    transition: none;
  }
  #app #menu #menu-background-wrapper #menu-background:before {
    transition: none;
  }
}

script.js

"use strict";
const MenuOption = (props) => {
    const { toggled } = React.useContext(AppContext);
    const className = `menu-${props.type}-option`, delay = toggled ? 200 : 0;
    const styles = {
        transitionDelay: `${delay + (50 * props.index)}ms`
    };
    return (React.createElement("button", { type: "button", className: className, disabled: !toggled, style: styles },
        React.createElement("i", { className: props.icon }),
        React.createElement("h3", { className: props.type === "quick" ? "tooltip" : "label" }, props.label)));
};
const Menu = () => {
    const { toggled } = React.useContext(AppContext);
    const profileImage = "https://images.unsplash.com/photo-1614027164847-1b28cfe1df60?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8M3x8bGlvbnxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60";
    const getOptions = (options, type) => {
        return options.map((option, index) => (React.createElement(MenuOption, { key: option.label, icon: option.icon, index: index, label: option.label, type: type })));
    };
    const getQuickOptions = () => {
        return getOptions([{
                icon: "fa-solid fa-bell", label: "Notifications"
            }, {
                icon: "fa-solid fa-gear", label: "Settings"
            }, {
                icon: "fa-solid fa-moon", label: "Theme"
            }], "quick");
    };
    const getFullOptions = () => {
        return getOptions([{
                icon: "fa-solid fa-house", label: "Home"
            }, {
                icon: "fa-solid fa-user", label: "Profile"
            }, {
                icon: "fa-solid fa-chart-line", label: "Dashboard"
            }, {
                icon: "fa-solid fa-heart", label: "Subscriptions"
            }, {
                icon: "fa-solid fa-wallet", label: "Wallet"
            }], "full");
    };
    return (React.createElement("div", { id: "menu", className: classNames({ toggled }) },
        React.createElement("div", { id: "menu-background-wrapper" },
            React.createElement("div", { id: "menu-background" })),
        React.createElement("img", { id: "menu-profile-image", src: profileImage }),
        React.createElement("div", { id: "menu-quick-options" }, getQuickOptions()),
        React.createElement("div", { id: "menu-full-options" }, getFullOptions())));
};
const AppContext = React.createContext(null);
const App = () => {
    const [toggled, setToggledTo] = React.useState(false);
    React.useEffect(() => {
        setTimeout(() => setToggledTo(true), 1000);
    }, []);
    const handleOnClick = () => setToggledTo(!toggled);
    return (React.createElement(AppContext.Provider, { value: { toggled } },
        React.createElement("div", { id: "app" },
            React.createElement(Menu, null),
            React.createElement("button", { id: "menu-toggle", type: "button", onClick: handleOnClick },
                React.createElement("i", { className: toggled ? "fa-solid fa-xmark-large" : "fa-solid fa-bars-staggered" })))));
};
ReactDOM.render(React.createElement(App, null), document.getElementById("root"));

If you are having any issues with the code, then you can visit our GitHub Account. Click Here!

You Might Like This:

Our Courses:

HTML – Beginner to Advance

CSS – Beginner to Advance

Click to rate this post!
[Total: 0 Average: 0]

Oh, hi there 👋 It’s nice to meet you.

Sign up to receive awesome content in your inbox, every week.

We don’t spam! Read our privacy policy for more info.

Leave a Reply