javascripthtmlcss

How to make a div the same width as the element above it without using relative positioning?


I have a form where I am trying to set up a dropdown menu below an input field. My issue is that I can't get the dropdown menu to be the same width as the input field above it.

If I set the dropdown menu to use relative positioning and I set it to 75% (the same width as the input field) then it works. But the issue then becomes that the dropdown menu pushes down the elements below it when it expands and that is not what I want. I want it to overlay the elements below it when it expands.

So, when I set the dropdown div to use relative positioning, the width is OK, but then it pushes down the elements, which is what I don't want. When I set it to use fixed positioning, it overlays the elements below it (which is what I want), but then I cannot get it to have the same width as the input above it.

How do I make this dropdown div both overlay the elements below it when it extends and also be the same exact width as the input field above it?

Here is a reference to the dropdown div and the input field above it

const input = document.getElementById("bizcategory");
const listContainer = document.getElementById("myList");


const words = ['option5', 'option6', 'option7', 'option8',
  'option9', 'option10', 'option11'
];

for (let i = 0; i < words.length; i++) {
  const newItem = document.createElement("li");
  newItem.textContent = words[i];
  newItem.style.listStyle = "none";
  listContainer.appendChild(newItem);

}



const listItems = listContainer.querySelectorAll("li");

input.addEventListener("focus", () => {
  listContainer.style.display = "block";
})

input.addEventListener("blur", () => {
  setTimeout(() => {
    listContainer.style.display = "none";
  }, 200);
});

listItems.forEach(i => i.addEventListener("click", function() {
  input.value = i.textContent;
  listContainer.style.display = "none";
}));
.signininput {
  height: 40px;
  width: 75%;
  box-sizing: border-box;
}


.list-container {
  display: none;
  border: 1px solid #ccc;
  background-color: white;
  width: 75%;
}

.list-container ul {
  list-style: none;
  padding: 0;
  margin: 0;
  width: 75%;
}

.list-container li {
  padding: 5px;
}

.list-container li:hover {
  background-color: #f0f0f0;
  cursor: pointer;
}
<input class="signininput"  type="text" id="bizcategory" name="bizcategory" placeholder="" maxlength="255" onblur="this.value=removeSpaces(this.value);"></input>
<div class="list-container" id="myList">
  <ul style="list-style: none;">
    <li>Option 1</li>
    <li>Option 2</li>
    <li>Option 3</li>
    <li>Option 4</li>
  </ul>
</div>


Solution

  • Here is some example code i drafted which has the behavior you want. I also recommend using JS events, like .addEventListener() or use mouse attributes like onclick, onmouseover, etc.

    const inputField = document.getElementById('inputField');
    const dropdownMenu = document.getElementById('dropdownMenu');
    
    
    inputField.addEventListener('focus', () => {
        dropdownMenu.classList.add('active');
    });
    
    // hide the dropdown when clicking outside for better user experience :D
    document.addEventListener('click', (event) => {
        if (!inputField.contains(event.target) && !dropdownMenu.contains(event.target)) {
            dropdownMenu.classList.remove('active');
        }
    });
    /* reset and styling for the .form-group */
    .form-group {
        position: relative;
        display: block;
    }
    
    /* styling for the input field */
    .input-field {
        width: 100%; /* makes the input take the full width of its container */
        padding: 8px;
        font-size: 16px;
        box-sizing: border-box;
    }
    
    /* styles for the dropdown menu */
    .dropdown {
        position: absolute;
        top: 100%;
        left: 0;
        width: 100%; /* matches the width of the input field */
        background-color: white;
        border: 1px solid #ccc;
        display: none;
        z-index: 1000;
    }
    
    .dropdown ul {
        list-style-type: none;
        margin: 0;
        padding: 0;
    }
    
    .dropdown li {
        padding: 8px;
        cursor: pointer;
    }
    
    /* and a dropdown to show it works */
    .dropdown.active {
        display: block;
    }
    <div class="form-group">
        <input type="text" id="inputField" class="input-field" placeholder="Enter input" />
        <div class="dropdown" id="dropdownMenu">
            <ul>
                <li>Option 1 :: Change me</li>
                <li>Option 2 :: Change me</li>
                <li>Option 3 :: Change me</li>
                <li>Stackoverflow :D</li>
            </ul>
        </div>
    </div>