z-index inside `overflow: scroll` div not working

Viewed 328

I want to show a customized dropdown inside a scroll-box (overflow-y: scroll). But the dropdown options is hidden at the bottom of the scroll-box. I also tried setting z-index to the dropdown-options and its parents, but still not working. How can I show the dropdown-options over the layer of the scroll-box and its surroundings?

enter image description here

function findAll_fakeDropdownBtn() {
  return document.querySelectorAll('.nts-fakeDropdownBtn');
}
function findAll_fakeDropdownOptionsContainer() {
  return document.querySelectorAll('.nts-fakeDropdownOptionsContainer');
}
window.onload = function () {
  findAll_fakeDropdownBtn().forEach(function(fakeDropdownBtn) {
    fakeDropdownBtn.addEventListener('click', function(event) {
      var ddocId = fakeDropdownBtn.dataset.ddocId;
      var fakeDropdownOptionsContainer = document.querySelector('#'+ddocId);
      var isDisplaying = fakeDropdownOptionsContainer.classList.contains('nts-fakeDropdownOptionsContainer-displaying');
      // Show/Hide the one target dropdown.
      if (isDisplaying) {
        fakeDropdownOptionsContainer.classList.remove('nts-fakeDropdownOptionsContainer-displaying');
      } else {
        fakeDropdownOptionsContainer.classList.add('nts-fakeDropdownOptionsContainer-displaying');
      }
    });
  });
  findAll_fakeDropdownOptionsContainer().forEach(function(fakeDropdownOptionsContainer) {
    fakeDropdownOptionsContainer.querySelectorAll('.nts-dropdown-option').forEach(function(dropdownOptionElm) {
      dropdownOptionElm.addEventListener('click', function(event) {
        dropdownOptionElm.classList.toggle('nts-dropdown-option-selected');
      });
    });
  });
}
.nts-fakeDropdownOptionsContainer-displaying {
  display: block !important;
}
.nts-dropdown-option:hover {
  background-color: orange !important;
}
.nts-dropdown-option-selected {
  background-color: red !important;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body style="background-color: tan;">
<div>
  <div style="margin-left: 50px; background-color: coral;">
    <div style="height: 150px; overflow-y: scroll; width: 300px; background-color: papayawhip;">
      <div><span>Some text..</span></div>
      <div><span>Some text..</span></div>
      <div><span>Some text..</span></div>
      <div><span>Some text..</span></div>
      <div style="position: relative;">
        <span>Some text..</span>
        <div id="elmId-fakeDropdownBtn-2"
             class="nts-fakeDropdownBtn"
             data-ddoc-id="elmId-fakeDropdownOptionsContainer-2"
             style="background-color: green; width: 150px; height: 20px;">DropdownBtn</div>
        <div id="elmId-fakeDropdownOptionsContainer-2"
             class="is-ddconpart nts-fakeDropdownOptionsContainer"
             style="position: absolute; background-color: lightseagreen; width: 100px; display: none;">
          <div class="is-ddconpart nts-dropdown-option">Option-A</div>
          <div class="is-ddconpart nts-dropdown-option">Option-B</div>
          <div class="is-ddconpart nts-dropdown-option">Option-C</div>
          <div class="is-ddconpart nts-dropdown-option">Option-D</div>
          <div class="is-ddconpart nts-dropdown-option">Option-E</div>
        </div>
      </div>
      <div><span>Some text..</span></div>
      <div><span>Some text..</span></div>
      <div><span>Some text..</span></div>
      <div><span>Some text..</span></div>
      <div><span>Some text..</span></div>
      <div><span>Some text..</span></div>
    </div>
  </div>
</div>
</body>
</html>

1 Answers

You've to show dropdown from outside of scrollable area. As you've used overflow:y scroll and it takes a specific height to crop the area. Z-index will not solve this issue. I've written some js code. It might help you to understand the concept of showing dropdown area outside of scrollable area.

Note: Read the comments of JS

window.onload = function () {

    /**
     * 
     * 
     * Custom dropdown Handler function
     * @param selector this selector is the dropdown button
     * @description selector must be a class without dot sign
     */ 
    const nts_dropdown_handler = (selector) => {
        const dropdown_btn = document.querySelectorAll( `.${selector}` );
        
        // listen to click event
        dropdown_btn.forEach( btn => {
            btn.addEventListener('click', ev => {

                const target    = ev.target;
                const rect      = ev.target.getBoundingClientRect();
                
                if( target.classList.contains(selector) && !target.classList.contains('show') ) {
                    // get selector data
                    const dropdown_id   = target.dataset.ddocId;
                    const dropdown_area = document.getElementById( dropdown_id ).cloneNode(true);
                    // apply necessary style
                    dropdown_area.style.top     = rect.top + rect.height + 'px',
                    dropdown_area.style.left    = rect.left + 'px',
                    // apply necessary classes
                    dropdown_area.classList.add(`show-${selector}`);
                    dropdown_area.classList.add('nts-fakeDropdownOptionsContainer-displaying');
                    dropdown_area.classList.add('dropdown-displayed');
                    target.classList.add( 'show' );
                    // append into dom
                    document.body.appendChild( dropdown_area );
    
                } else {
                    target.classList.remove( 'show' );
                    const dropdown_area = document.querySelector(`.show-${selector}`);
                    document.body.removeChild(dropdown_area)
                }
    
            })
        } )
    }

    /*
    * ========================================
    * Pass selector
    * the selector must be a class without (.) dot sign
    * ========================================
    */ 
    nts_dropdown_handler('nts-fakeDropdownBtn')


}
.nts-fakeDropdownOptionsContainer-displaying {
    display: block !important;
  }
  .nts-dropdown-option:hover {
    background-color: orange !important;
  }
  .nts-dropdown-option-selected {
    background-color: red !important;
  }
<body style="background-color: tan;">
    <div>
      <div style="margin-left: 50px; background-color: coral;">
        <div style="height: 150px; overflow-y: scroll; width: 300px; background-color: papayawhip;">
          <div><span>Some text..</span></div>
          <div><span>Some text..</span></div>
          <div><span>Some text..</span></div>
          <div><span>Some text..</span></div>
          
          <div style="position: relative;">
            <span>Some text..</span>
            <div id="elmId-fakeDropdownBtn-2"
                 class="nts-fakeDropdownBtn"
                 data-ddoc-id="elmId-fakeDropdownOptionsContainer-2"
                 style="background-color: green; width: 150px; height: 20px;">DropdownBtn</div>
                 
            <div id="elmId-fakeDropdownOptionsContainer-2"
                 class="is-ddconpart nts-fakeDropdownOptionsContainer"
                 style="position: absolute; background-color: lightseagreen; width: 100px; display: none;">
              <div class="is-ddconpart nts-dropdown-option">Option-A</div>
              <div class="is-ddconpart nts-dropdown-option">Option-B</div>
              <div class="is-ddconpart nts-dropdown-option">Option-C</div>
              <div class="is-ddconpart nts-dropdown-option">Option-D</div>
              <div class="is-ddconpart nts-dropdown-option">Option-E</div>
            </div>

          </div>
          

          <div><span>Some text..</span></div>
          <div><span>Some text..</span></div>
          <div><span>Some text..</span></div>
          <div><span>Some text..</span></div>
          <div><span>Some text..</span></div>
          <div><span>Some text..</span></div>
        </div>
      </div>
    </div>
    </body>

Related