twbs / bootstrap

The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.
https://getbootstrap.com
MIT License
170.65k stars 78.86k forks source link

Dropdown position relatively to body with boundary option in BS5 #35774

Open harnishdesign opened 2 years ago

harnishdesign commented 2 years ago

I have a Bootstrap 5 dropdown menu inside owl-carousel. but dropdown is being cut off because has outer div overflow:hidden in owl-carousel.

enter image description here

Complete snippet here: jsfiddle

So, I have try to position a dropdown relatively to body, not parent with boundary option from Bootstrap Docs,

Bootstrap docs says that can only be done via javascript (not via data attributes), so I have try below two methods code. but no luck.

Where I'm going wrong. can you please suggest proper solution.

1st try via JavaScript:

var dropdownElementList = [].slice.call(document.querySelectorAll('.dropdown-toggle'))
    var dropdownList = dropdownElementList.map(function (dropdownToggleEl) {
      return new bootstrap.Dropdown(dropdownToggleEl, {
        boundary: document.querySelector('#main-wrapper')
      })
    })

2nd try Using function with popperConfig. Find from here

var dropdown = new bootstrap.Dropdown('.dropdown-toggle', {
  popperConfig: function (defaultBsPopperConfig) {

return new bootstrap.Dropdown(dropdownTriggerEl, {
            popperConfig: {
                strategy: "fixed"
            }
        }); 
  }
})

Our HTML Code:

<div id="main-wrapper">
<div class="owl-carousel owl-theme">
  <div class="item">
    <div class="d-flex align-items-center">
      <h4>Shilipp Sotocnik</h4>

      <div class="dropdown dropdown-lg d-inline-block ms-auto"> 
      <a href="#" role="button" id="dropdownMenu1" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fas fa-ellipsis-h"></i></a>
        <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="dropdownMenu1">
          <li><a class="dropdown-item" href="#">Link 1</a></li>
          <li><a class="dropdown-item" href="#">Link 2</a></li>
          <li><a class="dropdown-item" href="#">Link 3</a></li>
          <li><a class="dropdown-item" href="#">Link 4</a></li>
        </ul>
      </div>

    </div>
  </div>
</div>
</div>
GeoSot commented 2 years ago

Hey @harnishdesign . Can you please include and a codepen demo?

harnishdesign commented 2 years ago

Hey @harnishdesign . Can you please include and a codepen demo?

Please check it out here: https://jsfiddle.net/harnishdesign/obg7favd/9/

GeoSot commented 2 years ago

Did some testing there and found out that position:fixed at least is set properly. But seems that it is not enough to bypass owl overflow:hidden :/

image

harnishdesign commented 2 years ago

@GeoSot Yes, i know. So, I want to dropdown position relatively to body instead of parent element. and, It works to with v4.5 with html attribute data-boundary="window". But I couldn't make it work with v5. The Bootstrap 5 documentation says that can only be done via javascript (not via data attributes), so I have try some javascript (as mention in question). but, no luck. So, I have to looking for correct javascript.

FirstVertex commented 2 years ago

I want to know also, how to append Bootstrap Dropdown to body. It was standard concept for all previous versions of Bootstrap. This is a blocker for our application to move to Bootstrap 5, as we have conditions where a Popover must have a Dropdown.

Here is my post to Stack Overflow asking for help https://stackoverflow.com/questions/72031591/popper-js-2-append-to-body

What's puzzling is Popper.js v2 doc has some tiny mention about it's possible to append to body, but there is no example anywhere how to do that. https://popper.js.org/docs/v2/performance/#attaching-elements-to-the-dom

I discovered ngBootstrap implementation which makes it's own createPopper() implementation. https://github.com/ng-bootstrap/ng-bootstrap/blob/1ab5d2113007c52f7832b0898abc54b5a684bdc4/src/util/positioning.ts this seems like a huge amount of effort to get the Dropdown into the body. In all previous Bootstrap versions it was just an input switch. position: fixed strategy has lots of problems and is not a substitute for append to body.

jfmdev commented 2 years ago

I'm having the same problem, I'm doing:

import { Dropdown } from "bootstrap";
...
new Dropdown(document.getElementById('my-dropdown'), { 
  boundary: document.querySelector('body')
});

But the boundary parameter is completely ignored.

Codepen example: https://codepen.io/jfmdev/pen/oNEYdBr

nicped commented 2 years ago

Ran into the same issue and by adding position-fixed to the dropdown-menu element, the dropdown does not get hidden by its scrolling parent

https://codepen.io/nicped/pen/oNEVVNw

sairexes commented 2 years ago

Ran into the same issue and by adding position-fixed to the dropdown-menu element, the dropdown does not get hidden by its scrolling parent

https://codepen.io/nicped/pen/oNEVVNw

This works! thank you!

jfmdev commented 2 years ago

If adding position-fixed don't works, you can use the strategy: "fixed" option, as suggested on https://github.com/twbs/bootstrap/issues/36358#issuecomment-1162479957

new Dropdown(document.getElementById('my-dropdown'), { 
  boundary: document.querySelector('body'),
  popperConfig: function (defaultBsPopperConfig) {
            return { ...defaultBsPopperConfig, strategy: "fixed"};
        }
});
GreathostRo commented 1 year ago

After more than a few hours and various attempts I found the working version:

const dropdowns = document.querySelectorAll('.dropdown-toggle')
const dropdown = [...dropdowns].map((dropdownToggleEl) => new bootstrap.Dropdown(dropdownToggleEl, {
    popperConfig(defaultBsPopperConfig) {
        return { ...defaultBsPopperConfig, strategy: 'fixed' };
    }
}));
ahmeti commented 1 year ago

Ran into the same issue and by adding position-fixed to the dropdown-menu element, the dropdown does not get hidden by its scrolling parent

https://codepen.io/nicped/pen/oNEVVNw

Thanks for the trick... The "position-fixed" class you specified makes an incorrect positioning in table. I recommend using the "position-absolute" class as a workaround.

gsartori commented 1 year ago

Same problem here, we have dropdowns into table rows. How can we avoid the table clipping? Using "position-fixed" or "position-absolute" is not helping. We are on Bootstrap 5.3 with popper 2.11.6 using data-bs-boundary="body" in a button with class="dropdown-toggle".

What's the correct way to have dropdowns in a table row?

nicped commented 1 year ago

What's the correct way to have dropdowns in a table row?

Try to create a codepen with the issue - then maybe I can come up with a solution

humbertleonardo commented 1 year ago

After more than a few hours and various attempts I found the working version:

const dropdowns = document.querySelectorAll('.dropdown-toggle')
const dropdown = [...dropdowns].map((dropdownToggleEl) => new bootstrap.Dropdown(dropdownToggleEl, {
    popperConfig(defaultBsPopperConfig) {
        return { ...defaultBsPopperConfig, strategy: 'fixed' };
    }
}));

It solved my problem, thanks