Creating an engaging user interface (UI) often involves using visually appealing and interactive components. One such component is an animated radial menu, a circular menu that radiates out from a central point, making it both functional and stylish. This article will guide you through the process of creating an animated radial menu using HTML, CSS, and JavaScript. The aim is to provide a clear, detailed explanation so you can easily understand and replicate this feature in your projects.

Table of Contents

Adding Animation with CSS

To animate the items spreading out in a radial pattern, we need to calculate the positions of each item.

In this CSS snippet:

Each menu item is positioned using the calc function to determine its x and y coordinates based on trigonometric functions cos and sin.

The angles (0deg, 72deg, 144deg, 216deg, 288deg) ensure that the items are evenly spaced around a circle.

Making It Interactive with JavaScript

Now, let’s add JavaScript to toggle the menu’s open state.

In this JavaScript snippet:

An event listener is added to the menu button.

When the button is clicked, it toggles the open class on the menu div, triggering the CSS transitions.

Combining Everything for the Final Product

Let’s combine all the pieces to see the final product in action.

HTML

HTML: Defines the structure.

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

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Animated Radial Octagon Menu </title>
  <!-- Font-Awesome CDN -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
  <!-- CSS File -->
  <link rel="stylesheet" href="./style.css" />
</head>

<body>
  <ul class="menu">
    <div class="menuToggle">
      <i class="fa-solid fa-plus"></i>
    </div>
    <li style="--i: 0; --clr: #0059E7">
      <a href="#">
        <i class="fa-brands fa-discord"></i>
      </a>
    </li>
    <li style="--i: 1; --clr: #fee800">
      <a href="#">
        <i class="fa-brands fa-facebook"></i> </a>
    </li>
    <li style="--i: 2; --clr: #04fc43">
      <a href="#">
        <i class="fa-brands fa-python"></i>
      </a>
    </li>
    <li style="--i: 3; --clr: #fe00f1">
      <a href="#">
        <i class="fa-brands fa-css3-alt"></i>
      </a>
    </li>
    <li style="--i: 4; --clr: #00b0fe">
      <a href="#">
        <i class="fa-brands fa-react"></i>
      </a>
    </li>
    <li style="--i: 5; --clr: #fea600">
      <a href="#">
        <i class="fa-brands fa-html5"></i>
      </a>
    </li>
    <li style="--i: 6; --clr: #a529ff">
      <a href="#">
        <i class="fa-brands fa-php"></i>
      </a>
    </li>
    <li style="--i: 7; --clr: #01bdab">
      <a href="#">
        <i class="fa-brands fa-youtube"></i> </a>
    </li>
  </ul>

  <!-- Js File -->
  <script src="./app.js"></script>
</body>

</html>

CSS

CSS: Styles and animates the elements.

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

body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: #0e1a34;
}

.menu {
  position: relative;
  width: 260px;
  height: 260px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.menu li {
  position: absolute;
  left: 0;
  list-style: none;
  transform-origin: 130px;
  transition: 0.5s;
  -webkit-transition: 0.5s;
  -moz-transition: 0.5s;
  -ms-transition: 0.5s;
  -o-transition: 0.5s;
  transition-delay: calc(0.1s * var(--i));
  transform: rotate(0deg) translateX(100px);
  -webkit-transform: rotate(0deg) translateX(100px);
  -moz-transform: rotate(0deg) translateX(100px);
  -ms-transform: rotate(0deg) translateX(100px);
  -o-transform: rotate(0deg) translateX(100px);
}

.menu.active li {
  transform: rotate(calc(360deg / 8 * var(--i)));
  -webkit-transform: rotate(calc(360deg / 8 * var(--i)));
  -moz-transform: rotate(calc(360deg / 8 * var(--i)));
  -ms-transform: rotate(calc(360deg / 8 * var(--i)));
  -o-transform: rotate(calc(360deg / 8 * var(--i)));
}

.menu li a {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 60px;
  text-decoration: none;
  height: 60px;
  font-size: 1.5em;
  border-radius: 50%;
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  -ms-border-radius: 50%;
  -o-border-radius: 50%;
  transform: rotate(calc(360deg / -8 * var(--i)));
  -webkit-transform: rotate(calc(360deg / -8 * var(--i)));
  -moz-transform: rotate(calc(360deg / -8 * var(--i)));
  -ms-transform: rotate(calc(360deg / -8 * var(--i)));
  -o-transform: rotate(calc(360deg / -8 * var(--i)));
  color: transparent;
  transition: 1s;
  -webkit-transition: 1s;
  -moz-transition: 1s;
  -ms-transition: 1s;
  -o-transition: 1s;
  transition-delay: 0.5s;
}

.menu.active li a {
  color: var(--clr);
}

.menu li a::before {
  content: "";
  position: absolute;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  -webkit-border-radius: 2px;
  -moz-border-radius: 2px;
  -ms-border-radius: 2px;
  -o-border-radius: 2px;
  background: #fff;
  transform: rotate(calc(var(--i) * 90deg)) translate(0, 25px);
  -webkit-transform: rotate(calc(var(--i) * 90deg)) translate(0, 25px);
  -moz-transform: rotate(calc(var(--i) * 90deg)) translate(0, 25px);
  -ms-transform: rotate(calc(var(--i) * 90deg)) translate(0, 25px);
  -o-transform: rotate(calc(var(--i) * 90deg)) translate(0, 25px);
  transition: height 0.5s, width 0.5s, transform 0.5s;
  -webkit-transition: height 0.5s, width 0.5s, transform 0.5s;
  -moz-transition: height 0.5s, width 0.5s, transform 0.5s;
  -ms-transition: height 0.5s, width 0.5s, transform 0.5s;
  -o-transition: height 0.5s, width 0.5s, transform 0.5s;
  transition-delay: 0s, 0s, 0s;
}

.menu.active li a::before {
  width: 60px;
  height: 60px;
  border: 2px solid var(--clr);
  box-sizing: border-box;
  background: #102344;
  border-radius: 50px;
  z-index: -1;
  transform: rotate(calc(var(--i) * 90deg)) translate(0px, 0px);
  -webkit-transform: rotate(calc(var(--i) * 90deg)) translate(0px, 0px);
  -moz-transform: rotate(calc(var(--i) * 90deg)) translate(0px, 0px);
  -ms-transform: rotate(calc(var(--i) * 90deg)) translate(0px, 0px);
  -o-transform: rotate(calc(var(--i) * 90deg)) translate(0px, 0px);
  transition: transform 0.5s, height 0.5s, width 0.5s;
  -webkit-transition: transform 0.5s, height 0.5s, width 0.5s;
  -moz-transition: transform 0.5s, height 0.5s, width 0.5s;
  -ms-transition: transform 0.5s, height 0.5s, width 0.5s;
  -o-transition: transform 0.5s, height 0.5s, width 0.5s;
  transition-delay: 1s, 1.5s, 1.5s;
  rotate: 135deg;
}

.menu.active li:hover a::before {
  background: var(--clr);
  color: #fff;
  box-shadow: 0 0 10px var(--clr), 0 0 30px var(--clr), 0 0 50px var(--clr);
}

.menu li a::after {
  content: "";
  position: absolute;
  left: 50px;
  width: 20px;
  height: 2px;
  background: #fff;
  z-index: -2;
  transform: rotate(calc(var(--i) * 0deg)) translate(15px, 0px);
  -webkit-transform: rotate(calc(var(--i) * 0deg)) translate(15px, 0px);
  -moz-transform: rotate(calc(var(--i) * 0deg)) translate(15px, 0px);
  -ms-transform: rotate(calc(var(--i) * 0deg)) translate(15px, 0px);
  -o-transform: rotate(calc(var(--i) * 0deg)) translate(15px, 0px);
  transition: 0.5s;
  -webkit-transition: 0.5s;
  -moz-transition: 0.5s;
  -ms-transition: 0.5s;
  -o-transition: 0.5s;
  transition-delay: 0.5s;
}

.menu.active li a::after {
  left: 10px;
  width: 40px;
  background: var(--clr);
  transform: rotate(calc(var(--i) * 45deg)) translate(50px, 0px);
  -webkit-transform: rotate(calc(var(--i) * 45deg)) translate(50px, 0px);
  -moz-transform: rotate(calc(var(--i) * 45deg)) translate(50px, 0px);
  -ms-transform: rotate(calc(var(--i) * 45deg)) translate(50px, 0px);
  -o-transform: rotate(calc(var(--i) * 45deg)) translate(50px, 0px);
  transition-delay: 0.5s;
}

.menu.active li:hover a i {
  position: relative;
  color: #fff;
  z-index: 1000000;
}

.menuToggle {
  position: absolute;
  width: 60px;
  height: 60px;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
  border-radius: 50%;
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  -ms-border-radius: 50%;
  -o-border-radius: 50%;
  cursor: pointer;
  font-size: 2rem;
  transition: transform 1.5s;
  -webkit-transition: transform 1.5s;
  -moz-transition: transform 1.5s;
  -ms-transition: transform 1.5s;
  -o-transition: transform 1.5s;
}

.menu.active .menuToggle {
  transform: rotate(315deg);
  -webkit-transform: rotate(315deg);
  -moz-transform: rotate(315deg);
  -ms-transform: rotate(315deg);
  -o-transform: rotate(315deg);
}

JavaScript

JavaScript: Adds interactivity to toggle the menu.

let menuToggle = document.querySelector(".menuToggle");
let menu = document.querySelector(".menu");

menuToggle.onclick = function () {
  menu.classList.toggle("active");
};

Customization Tips

Once you have the basic radial menu working, you can customize it to suit your needs better:

Change Colors: Modify the background and text colors to match your site’s theme.

Adjust Sizes: Increase or decrease the size of the menu button and items to fit your layout.

Add Icons: Replace text with icons for a more visually appealing menu.

Modify Animation: Tweak the transition duration or use different CSS animations for a unique effect.

Following these steps and tips, you now have a fully functional and customizable animated radial menu. This feature can add a dynamic and interactive element to your web projects, enhancing user experience and engagement.

If you want to get the source code for free in this way then you can check out many pages on which I have written posts.

If you’re encountering any errors, be sure to address them. To help you out, I’ve created a folder inside the ZIP file that you can download from the link below. A special thanks to James Bush for this. Here’s the link for you to download the file.

Author

Telegram Group Join Now
WhatsApp Group Join Now
Instagram Group Join Now

By aczone

Leave a Reply

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