skip to Main Content

Let’s say I have a navbar and going to render N number of anchor elements inside the navbar based on an array that I have (Type is like [text: string, href: string][])

What would be the best practice of detecting which of those elements are going to be overflowing (in the x axis) from the navbar, so that I can decide to render them somewhere else (like a More Links dropdown)?

2

Answers


  1. I add sample code below.

    import React, { useEffect, useRef, useState } from 'react';
    
    const Navbar = ({ links }) => {
      const navbarRef = useRef(null);
      const [overflowLinks, setOverflowLinks] = useState([]);
    
      useEffect(() => {
        const navbar = navbarRef.current;
        const linksArray = Array.from(navbar.getElementsByTagName('a'));
    
        const navbarWidth = navbar.offsetWidth;
        let currentWidth = 0;
        const overflowLinksArray = [];
    
        linksArray.forEach((link, index) => {
          const linkWidth = link.offsetWidth;
    
          if (currentWidth + linkWidth > navbarWidth) {
            overflowLinksArray.push(index);
          } else {
            currentWidth += linkWidth;
          }
        });
    
        setOverflowLinks(overflowLinksArray);
      }, [links]);
    
      return (
        <div>
          <div className="navbar" ref={navbarRef}>
            {links.map((link, index) => (overflowLinks.indexOf(index) == -1 ?
              <a key={index} href={link[1]}  style={{color:'green'}}>
                {link[0]}
              </a> : null
            ))}
          </div>
    
          {overflowLinks.length > 0 && (
            <div className="more-links-dropdown">
              {overflowLinks.map((index) => {
                const link = links[index];
                return <a key={index} href={link[1]} style={{color:'red'}}>
                  {link[0]}
                </a>
              })}
            </div>
          )}
        </div>
      );
    };
    
    // Example usage
    const App = () => {
      const linksArray = [
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        ['Link 1', '/link1'],
        ['Link 2', '/link2'],
        // Add more links as needed
      ];
    
      return <Navbar links={linksArray} />;
    };
    
    export default App;
    
    Login or Signup to reply.
  2. import React, { useRef, useEffect, useState } from 'react';
    
    const YourNavbar = ({ links }) => {
      const navbarRef = useRef(null);
      const [overflowingLinks, setOverflowingLinks] = useState([]);
    
      useEffect(() => {
        const navbarWidth = navbarRef.current.offsetWidth; // Get navbar width
    
        let totalWidth = 0;
        const overflowLinks = [];
    
        // Measure each anchor element and calculate total width
        links.forEach((link) => {
          const anchor = document.getElementById(link.href); // Get anchor element by ID
          if (anchor) {
            const { width } = anchor.getBoundingClientRect(); // Get width of anchor element
            totalWidth += width;
    
            if (totalWidth > navbarWidth) {
              overflowLinks.push(link); // Add overflowing links to a separate array
            }
          }
        });
    
        setOverflowingLinks(overflowLinks);
      }, [links]);
    
      return (
        <nav ref={navbarRef}>
          {links.map((link) => (
            <a key={link.href} id={link.href} href={link.href}>
              {link.text}
            </a>
          ))}
    
          {/* Render More Links dropdown */}
          {overflowingLinks.length > 0 && (
            <div className="more-links-dropdown">
              {overflowingLinks.map((link) => (
                <a key={link.href} href={link.href}>
                  {link.text}
                </a>
              ))}
            </div>
          )}
        </nav>
      );
    };
    
    export default YourNavbar;
    

    Explanation:
    This code measures the width of each anchor element within the navbar and compares it with the available space (navbarWidth).
    If the total width of the anchor elements exceeds the available space, it identifies which links are overflowing (overflowingLinks) and renders them within a "More Links" dropdown or a separate container.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search