A lista suspensa do botão Bootstrap dentro da tabela responsiva não está visível devido à rolagem

86

Eu tenho um problema com botões suspensos dentro de tabelas quando são responsivos e rolam ativos porque o menu suspenso não está visível por causa da overflow: auto;propriedade. Como posso corrigir isso para mostrar a opção suspensa do botão quando ele está recolhido? Posso usar um pouco de jQuery, mas depois que tive problemas com rolar da esquerda para a direita, decidi encontrar outra solução. Anexei uma foto para entender melhor.insira a descrição da imagem aqui

Aqui está um pequeno violino js:

BurebistaRuler
fonte

Respostas:

60

Resolvi isso sozinho e coloquei a resposta no escopo para ajudar outro usuário com o mesmo problema: Temos um evento em bootstrap e podemos usar esse evento para definir, overflow: inheritmas isso funcionará se você não tiver a propriedade css em seu pai recipiente.

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

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

e este é o violino

info: Neste exemplo de violino funciona de forma estranha e não tenho certeza do porquê, mas no meu projeto funciona bem.

BurebistaRuler
fonte
3
Isso só funciona para tabelas com uma lista suspensa na primeira célula da linha.
Almino Melo
6
no caso de tabela carregada dinamicamente: $('body') .on('show.bs.dropdown', '.table-responsive', function () { $(this).css("overflow", "visible"); }) .on('hide.bs.dropdown', '.table-responsive', function () { $(this).css("overflow", "auto"); });
Exlord
4
Mas, após o clique, os dados saem do tamanho mínimo da tela. Então isso não funciona. !!!!
Shreya Shah
1
Isso funcionaria se você pudesse impedir a tabela de rolar de volta para a esquerda quando o menu suspenso for aberto. Mas como está, se você tiver um menu suspenso à direita da tela, a mesa se moverá para a esquerda ao abrir. Os menus suspensos mais à direita (mascarados pela .table-responsiveclasse) ficam completamente ocultos ao tentar editá-los.
Ponyboy
43

Uma única solução CSS é permitir que o eixo y transborde.

http://www.bootply.com/YvePJTDzI0

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

EDITAR

Outra solução CSS única é aplicar responsivamente o estouro com base na largura da janela de visualização:

@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

Zim
fonte
@ZimSystem Ainda faz a mesma coisa, fundamentalmente não é a solução.
Jemar Jones de
Esta solução funciona mesmo se você remover o css personalizado. Talvez seja uma coisa html. Ainda estou procurando uma solução somente css.
fernandodof de
1
Não. Não funciona. Acho que é porque estou usando tabelas de dados
peterchaula
funciona para mim, exceto que o botão está na parte inferior da página ... então a lista suspensa aparece fora da janela ...
Brucie Alpha
31

Para referência, estamos em 2018 e estou usando o BS4.1

Tente adicionar data-boundary="viewport"o botão que alterna o menu suspenso (aquele com a classe dropdown-toggle). Consulte https://getbootstrap.com/docs/4.1/components/dropdowns/#options

Ben
fonte
4
Eu confirmo que essa é uma solução funcional que eu também encontrei.
sdvnksv
4
Não posso falar pelas versões anteriores, mas para o Bootstrap 4 esta realmente é a melhor solução. É simples, não sacrifica a capacidade de resposta, ele usa funcionalidades que já são fornecidas no framework, em vez de tentar hackea-lo com estilos ou scripts extras.
T. Linnell
16

Eu peguei uma abordagem diferente, tirei o elemento do pai e o configurei com a posição absoluta por jQuery

Fidle JS de trabalho: http://jsfiddle.net/s270Lyrd/

insira a descrição da imagem aqui

A solução JS que estou usando.

//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');
    }
});
Wazime
fonte
1
Esta resposta é a correção perfeita para mim ao usar a tabela de dados jquery (render ajax). Eu ajustei de acordo e funcionou muito bem.
13

Esta solução funcionou muito bem para mim:

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

Mais detalhes: https://github.com/twbs/bootstrap/issues/15374

pham cuong
fonte
11

minha solução global rápida de 2 centavos:

// 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);
  })
})();

Explicações: Quando um menu suspenso dentro de um '.table-responsive' é mostrado, ele calcula a altura da tabela e a expande (com preenchimento) para corresponder à altura necessária para exibir o menu. O menu pode ser de qualquer tamanho.

No meu caso, esta não é a tabela que tem a classe '.table-responsive', é uma div envolvente:

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

Portanto, a $ table var no script é na verdade uma div! (só para ficar claro ... ou não) :)

Nota: Eu envolvo em uma função para que meu IDE possa reduzir a função;) mas não é obrigatório!

BaltazarQc
fonte
2
Esta é a única solução que funcionou para mim, mas eu sugeriria usar $ table.css ("padding-bottom", menuOffsetHeight - tableOffsetHeight + 16); insetad de $ table.css ("padding-bottom", menuOffsetHeight - tableOffsetHeight); para adicionar preenchimento extra que está no bootstrap por padrão, além de uma pequena lacuna na parte inferior.
Phil Young,
Isso funciona, mas o preenchimento faz com que pareça ruim. Gostaria que houvesse uma solução que o fizesse funcionar sem o inchaço do preenchimento.
Qasim
solução agradável e simples
NMC
11

Eu tenho uma solução usando apenas CSS, basta usar a posição relativa para os menus suspensos dentro da tabela responsiva:

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

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

Leo Caseiro
fonte
1
esta é a melhor solução, estou usando para ui-select na minha tabela responsiva.
Sergio Ivanuzzo
Melhor solução também para mim
Mauro
2
Este violino não funciona . Ele continua ocultando a lista suspensa abaixo da tabela.
HelloIT de
@HelloIT tente o codepen (atualizado) codepen.io/leocaseiro/pen/rKxmpz
Leo Caseiro
1
Concordo com @hellioIT que este método não parece funcionar na caneta
MrPaulDriver
9

Defina essas propriedades. Boa sorte!

data-toggle="dropdown" data-boundary="window"
Halit Yeşil
fonte
3
Solução Bootstrap 4 apenas
nevada_scout
5

Isso foi corrigido no Bootstrap v4.1 e superior adicionando data-boundary="viewport"( Bootstrap Dropdowns Docs )

Mas para versões anteriores (v4.0 e abaixo), encontrei este trecho de javascript que funciona perfeitamente. Ele funciona para pequenas tabelas e tabelas de rolagem:

$('.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': ''});
});
Cyrus V.
fonte
4

Limpei um pouco a solução @Wazime. Funciona muito bem como uma solução geral.

$(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');
});
tremores
fonte
2

A solução recomendada e escolhida, nem sempre é a melhor solução. Infelizmente, é a solução que o LinkedIn usou recentemente e cria várias barras de rolagem na página com base na situação.

Meu método era ligeiramente diferente.

Eu continha o div responsivo à tabela em outro div. Em seguida, apliquei altura 100%, largura: 100%, bloco de exibição e posição absoluta para que a altura e a largura sejam baseadas no tamanho da página e defini o estouro como oculto.

Em seguida, na tabela de div responsivo, adicionei uma altura mínima de 100%

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

Como você pode ver no exemplo de trabalho abaixo, nenhuma barra de rolagem adicionada, nenhum comportamento engraçado e praticamente como está usando porcentagens - deve funcionar independentemente do tamanho da tela. Eu não testei isso para isso, no entanto. Se isso falhar por algum motivo, pode-se substituir 100% por 100vh e 100vw respectivamente.

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">

<!-- Optional theme -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">

            <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>


<div class="table_container" style="height: 100%; width: 100%; display: block;position: absolute;overflow: hidden;">
<div class="table-responsive" style="min-height:100%;">
                <table class="table">
                    <thead>
                        <tr>
                            <th>Value1</th>
                            <th>Value2</th>
                            <th>Value3</th>
                            <th>Value4</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>

                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>
                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>
                            <td>DATA</td>
                        </tr>
                        <tr>
                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>                                    </ul>
                                </div>
                            </td>

                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>
                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>
                            <td>DATA</td>
                        </tr>
                    </tbody>
                </table>
            </div>
</div>

Bruce
fonte
Não é uma solução para altura de visão menor. Os links suspensos inferiores não estão mais acessíveis devido à falta de visualização.
Seika85
1

Com base na resposta aceita e na resposta de @LeoCaseiro aqui está o que acabei usando no meu caso:

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

nas telas grandes, o menu suspenso não ficará oculto atrás da mesa de resposta e na tela pequena ficará oculto, mas está tudo bem porque há uma barra de rolagem no celular de qualquer maneira.

Espero que isso ajude alguém.

medBouzid
fonte
0

A resposta do Burebistaruler funciona bem para mim no ios8 (iphone4s), mas não funciona no Android que antes estava funcionando. O que eu fiz que funciona para mim no iOS8 (iphone4s) e no andoir é:

$('.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" );
})
Oscar Jofre
fonte
0

Isso pode ser útil para outra pessoa. Estou usando o DatatablesJS. Eu adiciono 500px à altura atual da mesa. Faço isso porque os Datatables permitem que você use 10, 20, etc. páginas em sua tabela. Portanto, preciso calcular dinamicamente a altura da mesa.
Quando o menu suspenso é mostrado, adiciono altura extra.
Quando o menu suspenso está oculto, eu redefino a altura da mesa original.

$(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");
    })
})

E o HTML

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

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

Antes: insira a descrição da imagem aqui

Depois que o menu suspenso é mostrado: insira a descrição da imagem aqui

miguel.angel
fonte
0

Resolvemos esse problema aqui no trabalho, aplicando uma classe .dropup ao menu suspenso quando o menu suspenso está próximo à parte inferior de uma tabela. insira a descrição da imagem aqui

Roshin Jose
fonte
Estou muito feliz com essa solução no final. $('table tr:nth-last-child(-n+3) td').addClass('dropup').
Furgas de
0

Isso funcionou para mim no Bootstrap 4, pois tem pontos de interrupção diferentes da v3:

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

Enquanto as pessoas ainda estão presas a esse problema e já estamos em 2020. Eu obtenho uma solução CSS pura fornecendo ao menu suspenso uma tela flexível

este snippet funciona muito bem com a datatable-scroll-wrapclasse

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

Bem, lendo a primeira resposta, vi que realmente não funciona quando você está vendo a barra de rolagem e o botão de alternância estava na última coluna (no meu caso) ou outra coluna que não está visível

erro de imagem

Mas, se você alterar 'herdar' para 'oculto', isso funcionará.

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

insira a descrição da imagem aqui

Tente fazer dessa forma.

Luís Gustavo Batista
fonte
-1

Em bootstrap.css, pesquise o próximo código:

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

... e atualize com isto:

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

Basta usar isto

.table-responsive {
    overflow: inherit;
}

Funciona no Chrome, mas não no IE10 ou Edge porque a propriedade de herança não é compatível

Deepak Swain
fonte
-1

No meu caso, isso funciona bem:

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