NAVIGATION

Floating Neon Navigation Bar

A futuristic floating navigation bar with a glowing active orb, smooth indicator movement, interactive icons and neon hover effects.

HTML
<div class="cr-floating-nav-demo">

  <nav class="cr-floating-nav">

    <div class="cr-nav-indicator"></div>


    <button class="cr-nav-item active" data-index="0" aria-label="Home">

      <span class="cr-nav-icon">
        <svg viewBox="0 0 24 24">
          <path d="M3 11.5L12 4l9 7.5"></path>
          <path d="M5.5 10v9h5v-5h3v5h5v-9"></path>
        </svg>
      </span>

      <span class="cr-nav-label">Home</span>

    </button>


    <button class="cr-nav-item" data-index="1" aria-label="Shopping">

      <span class="cr-nav-icon">
        <svg viewBox="0 0 24 24">
          <path d="M7 8h10l1 11H6L7 8z"></path>
          <path d="M9 8V6a3 3 0 0 1 6 0v2"></path>
        </svg>
      </span>

      <span class="cr-nav-label">Shop</span>

    </button>


    <button class="cr-nav-item" data-index="2" aria-label="Tools">

      <span class="cr-nav-icon">
        <svg viewBox="0 0 24 24">
          <path d="M14.5 6.5a4 4 0 0 0-5 5L4 17l3 3 5.5-5.5a4 4 0 0 0 5-5l-3 3-3-3 3-3z"></path>
        </svg>
      </span>

      <span class="cr-nav-label">Tools</span>

    </button>


    <button class="cr-nav-item" data-index="3" aria-label="Apps">

      <span class="cr-nav-icon">
        <svg viewBox="0 0 24 24">
          <rect x="4" y="4" width="6" height="6"></rect>
          <rect x="14" y="4" width="6" height="6"></rect>
          <rect x="4" y="14" width="6" height="6"></rect>
          <rect x="14" y="14" width="6" height="6"></rect>
        </svg>
      </span>

      <span class="cr-nav-label">Apps</span>

    </button>


    <button class="cr-nav-item" data-index="4" aria-label="Help">

      <span class="cr-nav-icon">
        <svg viewBox="0 0 24 24">
          <circle cx="12" cy="12" r="9"></circle>
          <path d="M9.7 9a2.5 2.5 0 1 1 3.7 2.2c-.9.5-1.4 1-1.4 2"></path>
          <path d="M12 17h.01"></path>
        </svg>
      </span>

      <span class="cr-nav-label">Help</span>

    </button>

  </nav>

</div>
CSS
*{
  box-sizing:border-box;
}

.cr-floating-nav-demo{
  width:100%;
  min-height:520px;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:40px 24px;
  background:
    radial-gradient(
      circle at 50% 58%,
      rgba(34,211,238,.10),
      transparent 24%
    ),
    radial-gradient(
      circle at 35% 35%,
      rgba(124,58,237,.08),
      transparent 28%
    ),
    #050914;
  font-family:Inter,Arial,sans-serif;
}

.cr-floating-nav{
  --active-index:0;
  position:relative;
  width:min(650px,100%);
  height:94px;
  display:grid;
  grid-template-columns:repeat(5,1fr);
  align-items:end;
  padding:0 12px 13px;
  background:
    linear-gradient(
      180deg,
      rgba(15,27,47,.96),
      rgba(7,15,29,.98)
    );
  border:1px solid rgba(95,126,165,.28);
  border-radius:28px;
  box-shadow:
    0 30px 70px rgba(0,0,0,.55),
    0 0 45px rgba(34,211,238,.06),
    inset 0 1px 0 rgba(255,255,255,.05);
  overflow:visible;
}

.cr-floating-nav::before{
  content:"";
  position:absolute;
  top:0;
  left:8%;
  width:84%;
  height:1px;
  background:
    linear-gradient(
      90deg,
      transparent,
      rgba(34,211,238,.55),
      rgba(168,85,247,.45),
      transparent
    );
}

.cr-floating-nav::after{
  content:"";
  position:absolute;
  z-index:0;
  left:calc(
    ((100% - 24px) / 5) * var(--active-index)
    + 12px
    + ((100% - 24px) / 10)
    - 55px
  );
  bottom:4px;
  width:110px;
  height:42px;
  border-radius:50%;
  background:
    radial-gradient(
      ellipse,
      rgba(34,211,238,.30) 0%,
      rgba(124,58,237,.14) 45%,
      transparent 72%
    );
  filter:blur(8px);
  transition:left .48s cubic-bezier(.2,.8,.2,1);
}

.cr-nav-indicator{
  position:absolute;
  z-index:2;
  top:-33px;
  left:calc(
    ((100% - 24px) / 5) * var(--active-index)
    + 12px
    + ((100% - 24px) / 10)
    - 35px
  );
  width:70px;
  height:70px;
  border-radius:50%;
  background:
    radial-gradient(
      circle at 32% 25%,
      rgba(255,255,255,.95),
      rgba(255,255,255,.12) 17%,
      transparent 18%
    ),
    linear-gradient(
      145deg,
      #22d3ee 0%,
      #3b82f6 45%,
      #8b5cf6 100%
    );
  border:1px solid rgba(255,255,255,.30);
  box-shadow:
    0 18px 35px rgba(0,0,0,.5),
    0 0 18px rgba(34,211,238,.7),
    0 0 38px rgba(124,58,237,.38),
    inset 0 1px 7px rgba(255,255,255,.35);
  transition:
    left .48s cubic-bezier(.16,.85,.2,1),
    transform .35s ease;
  animation:crOrbFloat 2.8s ease-in-out infinite;
}

.cr-nav-indicator::before{
  content:"";
  position:absolute;
  inset:-7px;
  border-radius:50%;
  border:1px solid rgba(34,211,238,.28);
  box-shadow:0 0 20px rgba(34,211,238,.22);
  animation:crRingPulse 1.8s ease-in-out infinite;
}

.cr-nav-indicator::after{
  content:"";
  position:absolute;
  left:50%;
  bottom:-29px;
  width:92px;
  height:30px;
  transform:translateX(-50%);
  border-radius:50%;
  background:
    radial-gradient(
      ellipse,
      rgba(34,211,238,.42),
      rgba(124,58,237,.18) 45%,
      transparent 72%
    );
  filter:blur(10px);
}

.cr-nav-item{
  position:relative;
  z-index:4;
  height:72px;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:flex-end;
  gap:5px;
  padding:0 6px 3px;
  border:0;
  outline:none;
  background:transparent;
  color:#8fa4c4;
  cursor:pointer;
  font-family:inherit;
  transition:
    color .3s ease,
    transform .3s ease,
    filter .3s ease;
}

.cr-nav-item::before{
  content:"";
  position:absolute;
  left:50%;
  bottom:5px;
  width:42px;
  height:14px;
  transform:
    translateX(-50%)
    scale(.65);
  border-radius:50%;
  background:
    radial-gradient(
      ellipse,
      rgba(34,211,238,.20),
      transparent 72%
    );
  filter:blur(7px);
  opacity:.20;
  transition:
    opacity .3s ease,
    transform .3s ease;
}

.cr-nav-icon{
  width:44px;
  height:44px;
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius:50%;
  color:#8fa6c8;
  filter:
    drop-shadow(0 0 5px rgba(59,130,246,.12));
  transition:
    transform .48s cubic-bezier(.16,.85,.2,1),
    color .3s ease,
    filter .3s ease;
}

.cr-nav-icon svg{
  width:26px;
  height:26px;
  display:block;
  fill:none;
  stroke:currentColor;
  stroke-width:2;
  stroke-linecap:round;
  stroke-linejoin:round;
  overflow:visible;
}

.cr-nav-label{
  font-size:13px;
  font-weight:700;
  letter-spacing:.3px;
  color:#7f93b1;
  opacity:.95;
  text-shadow:
    0 0 8px rgba(59,130,246,.08);
  transition:
    opacity .3s ease,
    transform .4s ease,
    color .3s ease,
    text-shadow .3s ease;
}

.cr-nav-item.active{
  color:#ffffff;
}

.cr-nav-item.active::before{
  opacity:1;
  transform:
    translateX(-50%)
    scale(1.35);
  background:
    radial-gradient(
      ellipse,
      rgba(34,211,238,.48),
      rgba(124,58,237,.18) 48%,
      transparent 75%
    );
}

.cr-nav-item.active .cr-nav-icon{
  transform:
    translateY(-42px)
    scale(1.12);
  color:#ffffff;
  filter:
    drop-shadow(0 0 5px rgba(255,255,255,.8))
    drop-shadow(0 0 12px rgba(34,211,238,.75))
    drop-shadow(0 0 22px rgba(124,58,237,.38));
}

.cr-nav-item.active .cr-nav-label{
  opacity:1;
  transform:translateY(-5px);
  color:#67e8f9;
  font-size:13px;
  font-weight:800;
  text-shadow:
    0 0 6px rgba(34,211,238,.8),
    0 0 16px rgba(34,211,238,.42),
    0 0 24px rgba(124,58,237,.22);
}

.cr-nav-item:not(.active):hover{
  color:#e5f1ff;
}

.cr-nav-item:not(.active):hover::before{
  opacity:.85;
  transform:
    translateX(-50%)
    scale(1.15);
}

.cr-nav-item:not(.active):hover .cr-nav-icon{
  transform:
    translateY(-7px)
    scale(1.08);
  color:#7dd3fc;
  filter:
    drop-shadow(0 0 6px rgba(34,211,238,.6))
    drop-shadow(0 0 15px rgba(99,102,241,.30));
}

.cr-nav-item:not(.active):hover .cr-nav-label{
  color:#d5e7fb;
  text-shadow:
    0 0 10px rgba(34,211,238,.30);
}

@keyframes crOrbFloat{
  0%,
  100%{
    transform:translateY(0);
  }

  50%{
    transform:translateY(-3px);
  }
}

@keyframes crRingPulse{
  0%,
  100%{
    opacity:.45;
    transform:scale(.96);
  }

  50%{
    opacity:1;
    transform:scale(1.06);
  }
}

@media(max-width:600px){

  .cr-floating-nav-demo{
    min-height:440px;
    padding:30px 14px;
  }

  .cr-floating-nav{
    height:88px;
    border-radius:22px;
  }

  .cr-nav-indicator{
    width:62px;
    height:62px;
    top:-29px;
    left:calc(
      ((100% - 24px) / 5) * var(--active-index)
      + 12px
      + ((100% - 24px) / 10)
      - 31px
    );
  }

  .cr-nav-icon{
    width:40px;
    height:40px;
  }

  .cr-nav-icon svg{
    width:22px;
    height:22px;
  }

  .cr-nav-label{
    font-size:10px;
  }

}
JavaScript
document.addEventListener(
  'DOMContentLoaded',
  function() {

    var nav =
      document.querySelector('.cr-floating-nav');

    if (!nav) {
      return;
    }

    var items =
      nav.querySelectorAll('.cr-nav-item');

    items.forEach(
      function(item) {

        item.addEventListener(
          'click',
          function() {

            items.forEach(
              function(navItem) {

                navItem.classList.remove(
                  'active'
                );

              }
            );

            item.classList.add(
              'active'
            );

            var index =
              item.getAttribute('data-index');

            nav.style.setProperty(
              '--active-index',
              index
            );

          }
        );

      }
    );

  }
);

How This Floating Neon Navigation Bar Works

The Floating Neon Navigation Bar uses a five-item layout for Home, Shop, Tools, Apps, and Help. Each navigation control is a button with a data-index value from 0 to 4, an accessible aria-label, an inline SVG icon, and a text label. The first button starts with the active class, so Home is selected when the component loads.

The main .cr-floating-nav container uses CSS Grid with grid-template-columns: repeat(5, 1fr), giving every navigation item an equal amount of horizontal space. Its width is limited to 650px while remaining responsive with width: min(650px, 100%). A dark linear gradient, subtle border, 28px corner radius, and layered shadows create the floating panel.

The neon effect is built mainly with gradients, shadows, and filters. A ::before pseudo-element adds a thin cyan-to-purple highlight along the top of the navigation bar. Another pseudo-element creates a blurred glow underneath the selected position. The separate .cr-nav-indicator is a 70px circular orb with cyan, blue, and purple gradients. Multiple box-shadow values produce its outer glow.

The indicator position is controlled by the custom CSS property --active-index. Its left calculation divides the available navigation width into five sections and moves the orb to the center of the active section. The same variable also positions the blurred glow beneath it. Both positions transition over .48s, using custom cubic-bezier timing functions for smooth movement. For more information about this mechanism, see the MDN CSS custom properties documentation.

The active icon moves upward by 42px and scales to 1.12, placing it visually over the glowing orb. Its color changes to white and several drop-shadow() filters create the neon appearance. The active label moves up by 5px and changes to #67e8f9, with cyan and purple text shadows. Inactive items also have hover feedback: their icons rise by 7px, scale slightly, and receive a lighter cyan glow.

Two keyframe animations add continuous motion. crOrbFloat moves the indicator upward by 3px at the midpoint of its 2.8-second cycle. crRingPulse animates the indicator’s surrounding ring between .96 and 1.06 scale over 1.8 seconds.

JavaScript handles the selection behavior. After DOMContentLoaded, the script finds .cr-floating-nav and attaches a click listener to every .cr-nav-item. Clicking an item removes active from all buttons, applies it to the clicked button, reads its data-index, and updates --active-index with style.setProperty(). CSS then handles the icon, label, indicator, and glow transitions.

A media query at 600px reduces the navigation height, indicator size, icon dimensions, and label font size. It also adjusts the indicator calculation so the orb remains centered correctly on smaller screens.

Customizing the Floating Neon Navigation Bar

Most of the component’s appearance can be adjusted directly in its existing CSS without changing how the JavaScript selection logic works.

  • Change the cyan #22d3ee, blue #3b82f6, and purple #8b5cf6 values to create a different neon color scheme.
  • Adjust the navigation bar’s 650px maximum width, 94px height, or 28px border radius to change its overall proportions.
  • Modify the .48s indicator and icon transitions to make selection movement faster or slower.
  • Change the 70px indicator width and height to make the glowing orb larger or smaller.
  • Adjust the 2.8s crOrbFloat duration or its translateY(-3px) value to control the floating movement.
  • Edit the SVG paths, labels, and aria-label values to represent different navigation destinations.
  • Change the 600px media-query breakpoint and mobile dimensions to match your layout.

Where to Use This Floating Neon Navigation Bar

This navigation style works best in interfaces where a small set of important destinations needs to remain visually distinct.

  • Mobile or compact web application navigation
  • Gaming dashboards with a dark interface
  • Developer tool interfaces
  • Portfolio or creative project navigation
  • Product dashboards with five primary sections
  • Experimental landing pages using neon UI styling

Because the component already combines icons, labels, active-state movement, and responsive sizing, it can serve as a compact primary navigation control. For a different navigation pattern with animated movement, the Animated Fly-In Navigation Menu is another related CodeRipple component to consider.

Frequently Asked Questions

Does the Floating Neon Navigation Bar use JavaScript?

Yes. JavaScript listens for clicks on the navigation buttons, removes the previous active class, activates the clicked item, and updates the --active-index CSS custom property.

How does the neon indicator move between navigation items?

Each button has a data-index. JavaScript copies that index into --active-index, and the indicator’s CSS left calculation uses the value to determine its new position. A .48s transition animates the movement.

Is the Floating Neon Navigation Bar responsive?

Yes. The navigation width can shrink to 100% of its available space, and a media query at 600px reduces the bar height, indicator size, icons, labels, and demo spacing.

Can I add more than five navigation items?

The current component is specifically calculated for five items. Its grid uses repeat(5, 1fr), while the indicator and glow position calculations also divide the available width by five. Adding more items therefore requires updating those CSS calculations as well.

The Floating Neon Navigation Bar combines a grid-based layout, animated CSS indicator, neon shadows, responsive adjustments, and a small JavaScript selection handler to create clear visual feedback without requiring a large script.

Scroll to Top