[javascript] Bootstrap button drop-down inside responsive table not visible because of scroll

I have a problem with drop-down buttons inside tables when are responsive and scroll active because the drop-down is not visible because of overflow: auto; property. How can I fix that in order to show drop-down option of button when this is collapsed? I can use some jQuery but after I have problems with scroll left-right so I decided to find another solution. I have attached a photo to understand better.enter image description here

Here is a small js fiddle:

This question is related to javascript jquery css twitter-bootstrap overflow

The answer is


I'd took a different approach, I had detached the element from the parent and set it with position absolute by jQuery

Working JS fidle: http://jsfiddle.net/s270Lyrd/

enter image description here

The JS solution I am using.

//fix menu overflow under the responsive table 
// hide menu on click... (This is a must because when we open a menu )
$(document).click(function (event) {
    //hide all our dropdowns
    $('.dropdown-menu[data-parent]').hide();

});
$(document).on('click', '.table-responsive [data-toggle="dropdown"]', function () {
    // if the button is inside a modal
    if ($('body').hasClass('modal-open')) {
        throw new Error("This solution is not working inside a responsive table inside a modal, you need to find out a way to calculate the modal Z-index and add it to the element")
        return true;
    }

    $buttonGroup = $(this).parent();
    if (!$buttonGroup.attr('data-attachedUl')) {
        var ts = +new Date;
        $ul = $(this).siblings('ul');
        $ul.attr('data-parent', ts);
        $buttonGroup.attr('data-attachedUl', ts);
        $(window).resize(function () {
            $ul.css('display', 'none').data('top');
        });
    } else {
        $ul = $('[data-parent=' + $buttonGroup.attr('data-attachedUl') + ']');
    }
    if (!$buttonGroup.hasClass('open')) {
        $ul.css('display', 'none');
        return;
    }
    dropDownFixPosition($(this).parent(), $ul);
    function dropDownFixPosition(button, dropdown) {
        var dropDownTop = button.offset().top + button.outerHeight();
        dropdown.css('top', dropDownTop + "px");
        dropdown.css('left', button.offset().left + "px");
        dropdown.css('position', "absolute");

        dropdown.css('width', dropdown.width());
        dropdown.css('heigt', dropdown.height());
        dropdown.css('display', 'block');
        dropdown.appendTo('body');
    }
});

For reference, it's 2018 and I'm using BS4.1

Try adding data-boundary="viewport" to the button that toggles the dropdown (the one with the class dropdown-toggle). See https://getbootstrap.com/docs/4.1/components/dropdowns/#options


We solved this issue here at work by applying a .dropup class to the dropdown when the dropdown is close to the bottom of a table.enter image description here


This worked for me in Bootstrap 4 since it has different breakpoints than v3:

@media (min-width: 992px) {
    .table-responsive {
        overflow: inherit;
    }
}

Simply Use This

.table-responsive {
    overflow: inherit;
}

It works on Chrome, but not IE10 or Edge because inherit property is not supported


Well, reading the top answer, i saw that it really dont works when you are seeing the scroll bar and the toggle button was on last column (in my case) or other column that is unseen

pic-error

But, if you change 'inherit' for 'hidden' it will work.

$('.table-responsive').on('show.bs.dropdown', function () {
    $('.table-responsive').css( "overflow", "hidden" );
}).on('hide.bs.dropdown', function () {
    $('.table-responsive').css( "overflow", "auto" );
})

enter image description here

Try to do that way.


This could be useful for someone else. I'm using DatatablesJS. I add 500px to the current height of the table. I do this because Datatables allow you to use 10, 20, etc pages in your table. So I need to calculate dinamically the table's height.
When dropdown is shown, I add extra height.
When dropdown is hiden, I reset original table's height.

$(document).ready(function() {
    $('.table-responsive .dropdown').on('shown.bs.dropdown', function () {
          console.log($('#table-responsive-cliente').height() + 500)
          $("#table-responsive-cliente").css("height",$('#table-responsive-cliente').height() + 500 );
    })

    $('.table-responsive .dropdown').on('hide.bs.dropdown', function () {
           $("#table-responsive-cliente").css("height","auto");
    })
})

And the HTML

<div class="table-responsive" id="table-responsive-cliente">
    <table class="table-striped table-hover">
     ....

     ....
    </table>
</div>

Before: enter image description here

After dropdown is shown: enter image description here


my 2ยข quick global fix:

// drop down in responsive table

(function () {
  $('.table-responsive').on('shown.bs.dropdown', function (e) {
    var $table = $(this),
        $menu = $(e.target).find('.dropdown-menu'),
        tableOffsetHeight = $table.offset().top + $table.height(),
        menuOffsetHeight = $menu.offset().top + $menu.outerHeight(true);

    if (menuOffsetHeight > tableOffsetHeight)
      $table.css("padding-bottom", menuOffsetHeight - tableOffsetHeight);
  });

  $('.table-responsive').on('hide.bs.dropdown', function () {
    $(this).css("padding-bottom", 0);
  })
})();

Explications: When a dropdown-menu inside a '.table-responsive' is shown, it calculate the height of the table and expand it (with padding) to match the height required to display the menu. The menu can be any size.

In my case, this is not the table that has the '.table-responsive' class, it's a wrapping div:

<div class="table-responsive" style="overflow:auto;">
    <table class="table table-hover table-bordered table-condensed server-sort">

So the $table var in the script is actually a div! (just to be clear... or not) :)

Note: I wrap it in a function so my IDE can collapse function ;) but it's not mandatory!


Based on the accepted answer and the answer of @LeoCaseiro here is what I ended up using in my case :

@media (max-width: 767px) {
    .table-responsive{
        overflow-x: auto;
        overflow-y: auto;
    }
}
@media (min-width: 767px) {
    .table-responsive{
        overflow: inherit !important; /* Sometimes needs !important */
    }
}

on big screens the dropdown won't be hidden behind the reponsive-table and in small screen it will be hidden but it's ok because there is scrolls bar in mobile anyway.

Hope this help someone.


I have a solution using only CSS, just use position relative for dropdowns inside the table-responsive:

@media (max-width: 767px) {
  .table-responsive .dropdown-menu {
    position: relative; /* Sometimes needs !important */
  }
}

https://codepen.io/leocaseiro/full/rKxmpz/


Define this properties. Good Luck!

data-toggle="dropdown" data-boundary="window"

Try it once. after 1 hour of research on net I found Best Solution for this Problem.

Solution:- just add script

(function () {
    // hold onto the drop down menu                                             
    var dropdownMenu;

    // and when you show it, move it to the body                                     
    $(window).on('show.bs.dropdown', function (e) {

    // grab the menu        
    dropdownMenu = $(e.target).find('.dropdown-menu');

    // detach it and append it to the body
    $('body').append(dropdownMenu.detach());

    // grab the new offset position
    var eOffset = $(e.target).offset();

    // make sure to place it where it would normally go (this could be improved)
    dropdownMenu.css({
        'display': 'block',
            'top': eOffset.top + $(e.target).outerHeight(),
            'left': eOffset.left
       });
    });

    // and when you hide it, reattach the drop down, and hide it normally                                                   
    $(window).on('hide.bs.dropdown', function (e) {
        $(e.target).append(dropdownMenu.detach());
        dropdownMenu.hide();
    });
})();

OUTPUT:- Solution


This solution worked great for me :

@media (max-width: 767px) {
    .table-responsive .dropdown-menu {
        position: static !important;
    }
}
@media (min-width: 768px) {
    .table-responsive {
        overflow: visible;
    }
}

More detail: https://github.com/twbs/bootstrap/issues/15374


This has been fixed in Bootstrap v4.1 and above by adding data-boundary="viewport" (Bootstrap Dropdowns Docs)

But for earlier versions (v4.0 and below), I found this javascript snippet that works perfectly. It works for small tables and scrolling tables:

$('.table-responsive').on('shown.bs.dropdown', function (e) {
    var t = $(this),
        m = $(e.target).find('.dropdown-menu'),
        tb = t.offset().top + t.height(),
        mb = m.offset().top + m.outerHeight(true),
        d = 20; // Space for shadow + scrollbar.
    if (t[0].scrollWidth > t.innerWidth()) {
        if (mb + d > tb) {
            t.css('padding-bottom', ((mb + d) - tb));
        }
    }
    else {
        t.css('overflow', 'visible');
    }
}).on('hidden.bs.dropdown', function () {
    $(this).css({'padding-bottom': '', 'overflow': ''});
});

Inside bootstrap.css search the next code:

.fixed-table-body {
  overflow-x: auto;
  overflow-y: auto;
  height: 100%;
}

...and update with this:

.fixed-table-body {
  overflow-x: visible;
  overflow-y: visible;
  height: 100%;
}

The recommended and chosen solution, is not always the best solution. Unfortunately its the solution linkedin recently used and it creates multiple scrollbars on the page based on the situation.

My method was slightly different.

I contained the table-responsive div in another div. Then I applied height 100%, width:100%, display block and position absolute so the height and width is based on the page size, and set overflow to hidden.

Then on the table responsive div I added a min-height of 100%

<div class="table_container" 
    style="height: 100%; width: 100%; display: block;position: absolute;overflow: hidden;">
<div class="table-responsive" style="min-height:100%;">

As you can see in the working example below, no added scroll bars, no funny behavior, and practically as its using percentages - it should work regardless of screen size. I have not testing this for that however. If that fails for some reason, one can replace 100% with 100vh and 100vw respectively.

_x000D_
_x000D_
<!-- Latest compiled and minified CSS -->_x000D_
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">_x000D_
_x000D_
<!-- Optional theme -->_x000D_
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">_x000D_
_x000D_
            <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>_x000D_
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>_x000D_
_x000D_
_x000D_
<div class="table_container" style="height: 100%; width: 100%; display: block;position: absolute;overflow: hidden;">_x000D_
<div class="table-responsive" style="min-height:100%;">_x000D_
                <table class="table">_x000D_
                    <thead>_x000D_
                        <tr>_x000D_
                            <th>Value1</th>_x000D_
                            <th>Value2</th>_x000D_
                            <th>Value3</th>_x000D_
                            <th>Value4</th>_x000D_
                        </tr>_x000D_
                    </thead>_x000D_
                    <tbody>_x000D_
                        <tr>_x000D_
                            <td>_x000D_
                                DATA_x000D_
                                <div class="btn-group btn-group-rounded">_x000D_
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">_x000D_
                                        <span class="caret"></span>_x000D_
                                    </button>_x000D_
                                    <ul class="dropdown-menu">_x000D_
                                        <li><a href="#">One</a></li>_x000D_
                                        <li><a href="#">Two</a></li>_x000D_
                                        <li><a href="#">Three</a></li>_x000D_
                                        <li role="seperator" class="divider"></li>_x000D_
                                        <li><a href="#">Four</a></li>_x000D_
                                    </ul>_x000D_
                                </div>_x000D_
                            </td>_x000D_
_x000D_
                            <td>_x000D_
                                DATA_x000D_
                                <div class="btn-group btn-group-rounded">_x000D_
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">_x000D_
                                        <span class="caret"></span>_x000D_
                                    </button>_x000D_
                                    <ul class="dropdown-menu">_x000D_
                                        <li><a href="#">One</a></li>_x000D_
                                        <li><a href="#">Two</a></li>_x000D_
                                        <li><a href="#">Three</a></li>_x000D_
                                        <li role="seperator" class="divider"></li>_x000D_
                                        <li><a href="#">Four</a></li>_x000D_
                                    </ul>_x000D_
                                </div>_x000D_
                            </td>_x000D_
                            <td>_x000D_
                                DATA_x000D_
                                <div class="btn-group btn-group-rounded">_x000D_
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">_x000D_
                                        <span class="caret"></span>_x000D_
                                    </button>_x000D_
                                    <ul class="dropdown-menu">_x000D_
                                        <li><a href="#">One</a></li>_x000D_
                                        <li><a href="#">Two</a></li>_x000D_
                                        <li><a href="#">Three</a></li>_x000D_
                                        <li role="seperator" class="divider"></li>_x000D_
                                        <li><a href="#">Four</a></li>_x000D_
                                    </ul>_x000D_
                                </div>_x000D_
                            </td>_x000D_
                            <td>DATA</td>_x000D_
                        </tr>_x000D_
                        <tr>_x000D_
                            <td>_x000D_
                                DATA_x000D_
                                <div class="btn-group btn-group-rounded">_x000D_
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">_x000D_
                                        <span class="caret"></span>_x000D_
                                    </button>_x000D_
                                    <ul class="dropdown-menu">_x000D_
                                        <li><a href="#">One</a></li>_x000D_
                                        <li><a href="#">Two</a></li>_x000D_
                                        <li><a href="#">Three</a></li>_x000D_
                                        <li role="seperator" class="divider"></li>_x000D_
                                        <li><a href="#">Four</a></li>                                    </ul>_x000D_
                                </div>_x000D_
                            </td>_x000D_
_x000D_
                            <td>_x000D_
                                DATA_x000D_
                                <div class="btn-group btn-group-rounded">_x000D_
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">_x000D_
                                        <span class="caret"></span>_x000D_
                                    </button>_x000D_
                                    <ul class="dropdown-menu">_x000D_
                                        <li><a href="#">One</a></li>_x000D_
                                        <li><a href="#">Two</a></li>_x000D_
                                        <li><a href="#">Three</a></li>_x000D_
                                        <li role="seperator" class="divider"></li>_x000D_
                                        <li><a href="#">Four</a></li>_x000D_
                                    </ul>_x000D_
                                </div>_x000D_
                            </td>_x000D_
                            <td>_x000D_
                                DATA_x000D_
                                <div class="btn-group btn-group-rounded">_x000D_
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">_x000D_
                                        <span class="caret"></span>_x000D_
                                    </button>_x000D_
                                    <ul class="dropdown-menu">_x000D_
                                        <li><a href="#">One</a></li>_x000D_
                                        <li><a href="#">Two</a></li>_x000D_
                                        <li><a href="#">Three</a></li>_x000D_
                                        <li role="seperator" class="divider"></li>_x000D_
                                        <li><a href="#">Four</a></li>_x000D_
                                    </ul>_x000D_
                                </div>_x000D_
                            </td>_x000D_
                            <td>DATA</td>_x000D_
                        </tr>_x000D_
                    </tbody>_x000D_
                </table>_x000D_
            </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


A CSS only solution is to allow the y-axis to overflow.

http://www.bootply.com/YvePJTDzI0

.table-responsive {
  overflow-y: visible !important;
}

EDIT

Another CSS only solution is to responsively apply the overflow based on viewport width:

@media (max-width: 767px) {
    .table-responsive .dropdown-menu {
        position: static !important;
    }
}
@media (min-width: 768px) {
    .table-responsive {
        overflow: inherit;
    }
}

https://www.codeply.com/go/D3XBvspns4


Burebistaruler response works ok for me on ios8 (iphone4s) but doen't woks on android that before was working. What i've donne that Works for me on ios8 (iphone4s) and andoir is:

$('.table-responsive').on('show.bs.dropdown', function () {
 $('.table-responsive').css( "min-height", "400px" );
});

$('.table-responsive').on('hide.bs.dropdown', function () {
     $('.table-responsive').css( "min-height", "none" );
})

In my case, this works fine:

.table-responsive {
  overflow-y: visible !important;
}

As long as people still stuck in this issue and we are in 2020 already. I get a pure CSS solution by giving the drop down menu a flex display

this snippet works great with datatable-scroll-wrap class

.datatable-scroll-wrap .dropdown.dropup.open .dropdown-menu {
    display: flex;
}
.datatable-scroll-wrap .dropdown.dropup.open .dropdown-menu li a {
    display: flex;
}

Cleaned up @Wazime solution a little. Works great as a general solution.

$(document).on('shown.bs.dropdown', '.table-responsive', function (e) {
    // The .dropdown container
    var $container = $(e.target);

    // Find the actual .dropdown-menu
    var $dropdown = $container.find('.dropdown-menu');
    if ($dropdown.length) {
        // Save a reference to it, so we can find it after we've attached it to the body
        $container.data('dropdown-menu', $dropdown);
    } else {
        $dropdown = $container.data('dropdown-menu');
    }

    $dropdown.css('top', ($container.offset().top + $container.outerHeight()) + 'px');
    $dropdown.css('left', $container.offset().left + 'px');
    $dropdown.css('position', 'absolute');
    $dropdown.css('display', 'block');
    $dropdown.appendTo('body');
});

$(document).on('hide.bs.dropdown', '.table-responsive', function (e) {
    // Hide the dropdown menu bound to this button
    $(e.target).data('dropdown-menu').css('display', 'none');
});

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to twitter-bootstrap

Bootstrap 4: responsive sidebar menu to top navbar CSS class for pointer cursor How to install popper.js with Bootstrap 4? Change arrow colors in Bootstraps carousel Search input with an icon Bootstrap 4 bootstrap 4 responsive utilities visible / hidden xs sm lg not working bootstrap.min.js:6 Uncaught Error: Bootstrap dropdown require Popper.js Bootstrap 4 - Inline List? Bootstrap 4, how to make a col have a height of 100%? Bootstrap 4: Multilevel Dropdown Inside Navigation

Examples related to overflow

Bootstrap button drop-down inside responsive table not visible because of scroll Remove scrollbars from textarea Carry Flag, Auxiliary Flag and Overflow Flag in Assembly Horizontal scroll css? Body set to overflow-y:hidden but page is still scrollable in Chrome How can I add a vertical scrollbar to my div automatically? CSS text-overflow: ellipsis; not working? Have a fixed position div that needs to scroll if content overflows Mobile overflow:scroll and overflow-scrolling: touch // prevent viewport "bounce" Overflow-x:hidden doesn't prevent content from overflowing in mobile browsers