Tips on automating the process of moving overflowing elements into a dropdown menu

Challenge Description

In need of a dynamic navigation bar, I faced the problem of displaying only the first X items on one line and have the remaining items hidden in a "Show more" dropdown. The challenge was to calculate the width of each item accurately without rendering all elements at once for performance reasons.

Potential Approach

To address this issue, I devised a method to measure the width of each item by considering text length and button padding. By comparing the total width of items with the screen width, I could determine which items should be shown on the initial display line. However, the difficulty lay in measuring the text width without rendering all items simultaneously, as it would impact performance negatively.

Answer №1

When determining the width of each item, it is necessary for the browser to render them first. Trying to find a workaround where items are not rendered initially may seem like premature optimization. Unless your menu contains thousands of top-level items, the rendering time is minimal compared to what an alternative scripting solution would require.

The JavaScript logic in the code below is straightforward and should not have a significant impact on performance. The loop iterates through the list of top-level items just once.

window.addEventListener( 'DOMContentLoaded', () => {
    const menu = document.querySelector( '#menu' )
    const items = menu.querySelectorAll( '.item' )
    const viewMore = menu.querySelector( '.view-more' )
    const overflow = menu.querySelector( '#overflow-menu' )
    
    const maxWidth = menu.offsetWidth
    let accumulator = viewMore.offsetWidth
    let c = 0
    
    while ( accumulator <= maxWidth && c < items.length - 1 ) {
        accumulator += items[c].offsetWidth
        c++
    }
    
    for ( c--; c < items.length; c++ ) {
        if ( ! items[c].classList.contains( 'view-more' ) ) {
            overflow.appendChild(items[c]);
        }
    }
    
    viewMore.addEventListener( 'click', () => {
        overflow.classList.toggle( 'visible' ) 
    } )
} )
#menu {
    display: flex;
}
.item {
    padding: 5px 10px;
    cursor: pointer;
    white-space: nowrap;
    color: black;
}
.item.view-more {
    background-color: black;
    color: white;
    border-radius: 5px;
    position: relative;
}
#overflow-menu {
    position: absolute;
    top: 100%;
    right: 0;
    display: none;
    flex-direction: column;
    background-color: white;
    box-shadow: 0 0 10px black;
}
#overflow-menu.visible {
    display: flex;
}
<div id="menu">
  <div class="item">Text</div>
  <div class="item">Of Varying</div>
  <div class="item">Lengths</div>
  <div class="item">That The Browser</div>
  <div class="item">Must</div>
  <div class="item">Render</div>
  <div class="item">In</div>
  <div class="item">Order To</div>
  <div class="item">Determine</div>
  <div class="item">The</div>
  <div class="item">Final Width</div>
  <div class="item">:)</div>
  
  <div class="item view-more">
      View More
      <div id="overflow-menu"></div>
  </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Submitting a form using an anchor tag in Angular 8: A step-by-step guide

I have a question about how to submit form data using hidden input fields when a user clicks on an <a> tag. <form action="/submit/form/link"> <input type="hidden" [attr.value]="orderNumber.id" /> <input type="hidden" [attr.value]= ...

`How can I effectively test a React.js page utilizing both Context and useEffect?`

I'm struggling with testing a page that uses Context and useEffect with Jest and Testing-library, can you offer any assistance? REPOSITORY: https://github.com/jefferson1104/padawan Context File: src/context/personContext.tsx import { createContext, ...

Unable to modify language settings in DatePicker - Material UI

<LocalizationProvider dateAdapter={AdapterDateFns} locale={plLocale}> <div style={{ display: 'flex', alignItems: 'center', marginTop: 30 }}> <DatePicker label="Start Date" ...

When I adjust the size of my browser, the elements on my HTML page shift around

I'm facing an issue where all my elements move when I resize my browser, and I cannot figure out why. How can I ensure that they stay in their respective positions even when the browser is resized? Is there a CSS solution for this? Thank you! body ...

Guide on exporting a dynamically imported class instance using ES6 modules in NodeJS

Currently, I am engrossed in a book on NodeJS that illustrates a simple web application example. In this example, the prerequisite is to have various data store classes housed in their respective modules and dynamically selecting the data store by configur ...

What's the trick to efficiently managing multiple checkboxes in an array state?

I have a lengthy collection of checkboxes that is not well optimized. I am trying to obtain the checked ones and store them in an array state. However, I am uncertain about how to handle this situation and I would appreciate some assistance. It should also ...

Text box content does not refresh unless the page is reloaded

My text box (tbAdresse) is initially empty. I'm using the following JavaScript code to set its value: origin = document.getElementById("tbAdresse").value; if (origin == "") origin = <%=this.GetFormatStringCoordonnees("Paris")% ...

What is the process of declaring a react-icons icon in TypeScript?

Having a dilemma with declaring the icon in my array that contains name and icon. export const SidebarMenuList: SidebarMenu[] = [ { name: "Discover", icon: <AiOutlineHome />, id: SidebarCategory.Discover, }, ] The SidebarMe ...

Troubleshooting the issue: Unable to shift a div to the left in a Rails app using jQuery and CSS when a mouseover event occurs

Hey there, I'm working on a div that contains a map. My goal is to have the width of the div change from 80% to 50% when a user hovers over it. This will create space on the right side for an image to appear. I've been looking up examples of jqu ...

Configuring IP Whitelisting for Firebase Cloud Functions with MongoDB Cluster

What is the process for including my Firebase Cloud Functions in the IP whitelist of my MongoDB cluster? Error Message: ...

Expanding Your jQuery Library from a Content Delivery Network

As of now, I have a jQuery hosted on my FTP along with other web files. YSlow recommends using a CDN for jQuery. However, I am wondering how I can extend that jQuery. Is it possible to add custom functions to it without being able to edit the original co ...

How can one save a text value element from a cascading list in ASP.NET MVC?

I have recently started learning about javascript, jquery, and ajax. In my model, I have defined the following classes: namespace hiophop.Models { public class CarMake { public class Category { public int CategoryID { g ...

What is the best way to make a default selection in a headless-ui combobox?

How can I set the first option as selected by default in a dropdown using the Combobox Component? Combobox Component import { useState } from 'react' import { CheckIcon, ChevronUpDownIcon } from '@heroicons/react/20/solid' import { Com ...

Analyzing string values in Cypress

When attempting to compare two values within a page and make an assertion, my goal is to retrieve the value of one text element and compare it with another value on the same page. While I find this process straightforward in Java/selenium, achieving the ...

Replace the function if it is specified in the object, otherwise use the default functionality

Having a calendar widget written in TypeScript, I am able to bind a listener to a separate function. However, I desire this separate function to have default functionality until someone overrides it in the config object passed to the constructor. Within th ...

How to Perfectly Align a Gif

I'm trying to understand the functionality behind this code snippet. Can anyone shed some light on it? img{ display:block; margin:auto; } I attempted to center a gif using this code block after my teacher suggested trying align:center; without succe ...

Regular expression: Identify all instances of double quotes within a given string and insert a comma

Is there a way to transform a string similar to the following: ' query: "help me" distance: "25" count: "50" ' Into either a JavaScript object or a JSON string that resembles this: '{ query: "help me", distance: "25", count: "50" }' ...

Looking for a particular root node in a tree structure?

I am currently working on converting docx files to xml and using DOM to locate the parent node of a specific element. For instance <chapter> <title> <label>Chapter 1 </label> </title> ...

My component is displaying a warning message that advises to provide a unique "key" prop for each child in a list during rendering

I need help resolving a warning in my react app: Warning: Each child in a list should have a unique "key" prop. Check the render method of `SettingRadioButtonGroup`. See https://reactjs.org/link/warning-keys for more information. at div ...

jQuery.get() function is limited to specific types of webpages

I have successfully combined multiple weather APIs on my website, which can be found here. Recently, I started using the weather.gov API and it has been quite effective. However, there are certain data points that I need to extract which the weather.gov A ...