Não é possível rolar para a parte superior do item flexível que está transbordando contêiner


259

Portanto, ao tentar criar um modal útil usando o flexbox, descobri o que parece ser um problema no navegador e fico imaginando se há uma correção ou solução conhecida - ou idéias sobre como resolvê-lo.

A coisa que estou tentando resolver tem dois aspectos. Primeiro, mantendo a janela modal centralizada verticalmente, o que funciona como esperado. A segunda é fazer com que a janela modal role - externamente, para que toda a janela modal role, não o conteúdo dentro dela (é para que você possa ter menus suspensos e outros elementos da interface do usuário que possam se estender para fora dos limites do modal - como um selecionador de data personalizado etc.)

No entanto, ao combinar a centralização vertical com as barras de rolagem, a parte superior do modal pode se tornar inacessível quando começar a transbordar. No exemplo acima, você pode redimensionar para forçar o estouro e, ao fazer isso, permite rolar para a parte inferior do modal, mas não para a parte superior (o primeiro parágrafo é cortado).

Aqui está o link para o código de exemplo (altamente simplificado)

https://jsfiddle.net/dh9k18k0/2/

.modal-container {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  overflow-x: auto;
}
.modal-container .modal-window {
  display: -ms-flexbox;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  // Optional support to confirm scroll behavior makes sense in IE10
  //-ms-flex-direction: column;
  //-ms-flex-align: center;
  //-ms-flex-pack: center;
  height: 100%;
}
.modal-container .modal-window .modal-content {
  border: 1px solid #ccc;
  border-radius: 4px;
  background: #fff;
  width: 100%;
  max-width: 500px;
  padding: 10px
}

Isso afeta o Firefox, o Safari, o Chrome e o Opera (atual). Ele se comporta de maneira interessante no IE10 se você comentar no CSS prefixado do IE10 vender - eu ainda não testei o IE11, mas presumo que o comportamento corresponda ao do IE10 .

Alguma idéia seria boa. Links para problemas conhecidos ou raciocínio por trás desse comportamento também seriam úteis.

Respostas:


478

O problema

O Flexbox facilita muito a centralização.

Simplesmente aplicando align-items: centere justify-content: centerao contêiner flex, seus itens flexíveis serão centralizados vertical e horizontalmente.

No entanto, há um problema com esse método quando o item flexível é maior que o contêiner flexível.

Conforme observado na pergunta, quando o item flexível excede o contêiner, a parte superior se torna inacessível.

insira a descrição da imagem aqui

Para estouro horizontal, a seção esquerda fica inacessível (ou a seção direita, nos idiomas RTL).

Aqui está um exemplo com um contêiner LTR com justify-content: centere três itens flexíveis:

insira a descrição da imagem aqui

Veja o final desta resposta para uma explicação desse comportamento.


Solução # 1

Para corrigir esse problema, use as margens automáticas do flexbox , em vez de justify-content.

Com automargens, um item flexível transbordante pode ser centralizado vertical e horizontalmente sem perder o acesso a qualquer parte dele.

Então, em vez deste código no contêiner flex:

#flex-container {
    align-items: center;
    justify-content: center;
}

Use este código no item flexível:

.flex-item {
    margin: auto;
}

insira a descrição da imagem aqui

Demonstração revisada


Solução 2 (ainda não implementada na maioria dos navegadores)

Adicione o safevalor à sua regra de alinhamento de palavras-chave, assim:

justify-content: safe center

ou

align-self: safe center

Na especificação do Módulo de alinhamento de caixas CSS :

4.4 Overflow Alinhamento: o safee unsafepalavras-chave e os limites de segurança de rolagem

Quando o [item flexível] for maior que o [recipiente flexível], ele excederá. Alguns modos de alinhamento, se respeitados nesta situação, podem causar perda de dados: por exemplo, se o conteúdo de uma barra lateral estiver centralizado, quando eles excederem, poderão enviar parte de suas caixas além da borda inicial da janela de visualização, que não pode ser rolada para .

Para controlar essa situação, um modo de alinhamento de estouro pode ser especificado explicitamente. Unsafeo alinhamento respeita o modo de alinhamento especificado em situações de estouro, mesmo que cause perda de dados, enquanto o safealinhamento altera o modo de alinhamento em situações de estouro, na tentativa de evitar a perda de dados.

O comportamento padrão é conter o assunto do alinhamento dentro da área de rolagem, embora, no momento da escrita, esse recurso de segurança ainda não esteja implementado.

safe

Se o tamanho do [item flexível] ultrapassar o [contêiner flexível], o [item flexível] será alinhado como se o modo de alinhamento fosse [ flex-start].

unsafe

Independentemente dos tamanhos relativos de [item flexível] e [container flexível], o valor de alinhamento fornecido é respeitado.

Nota: O Módulo de alinhamento de caixas é para uso em vários modelos de layout de caixas, não apenas flex. Portanto, no trecho de especificação acima, os termos entre colchetes realmente dizem "assunto de alinhamento", "contêiner de alinhamento" e " start". Usei termos específicos de flex para manter o foco nesse problema específico.


Explicação para limitação de rolagem do MDN:

Considerações sobre itens flexíveis

As propriedades de alinhamento do Flexbox fazem centralização "verdadeira", ao contrário de outros métodos de centralização em CSS. Isso significa que os itens flexíveis permanecerão centralizados, mesmo se transbordarem o contêiner flexível.

Às vezes, isso pode ser problemático, no entanto, se eles ultrapassarem a borda superior da página ou a borda esquerda, [...] pois você não pode rolar para essa área, mesmo se houver conteúdo!

Em uma versão futura, as propriedades de alinhamento serão estendidas para ter também uma opção "segura".

Por enquanto, se isso for uma preocupação, você poderá usar as margens para obter a centralização, pois elas responderão de uma maneira "segura" e pararão de centralizar se transbordarem.

Em vez de usar as align-propriedades, basta colocar automargens nos itens flex que você deseja centralizar.

Em vez das justify-propriedades, coloque margens automáticas nas bordas externas do primeiro e do último itens flexíveis no contêiner flexível.

As automargens "flexionam" e assumem o espaço restante, centralizando os itens flexíveis quando houver espaço restante e alternando para o alinhamento normal quando não houver.

No entanto, se você estiver tentando substituir justify-contentpela centralização baseada em margens em uma caixa flexível de várias linhas, provavelmente não terá sorte, pois precisará colocar as margens no primeiro e no último item flexível de cada linha. A menos que você possa prever com antecedência quais itens serão finalizados em qual linha, não será possível usar com confiabilidade a centralização baseada em margens no eixo principal para substituir a justify-contentpropriedade.


4
Sim, essa é uma solução melhor e obrigado por fornecer informações adicionais valiosas.
precisa saber é o seguinte

1
Note-se que isso não funciona no IE11. O fundo será cortado.
Daniel

2
@ Daniel, acabei de testar o código no IE11. Nada está inacessível. De fato, o problema descrito na pergunta nem existe no IE11. Você pode estar se referindo ao excesso de texto ocorrendo apenas no IE11. Essa é outra questão para outra pergunta.
Michael Benjamin

11
Para corrigir o problema no IE11: adicione align-items: flex-startao contêiner flex e mantenha-o margin: autono item flex.
Eugene Fidelin

2
Isso não funciona para mim ao usar flex-direction: column;
Stefan

22

Bem, como dizia a Lei de Murphy, a leitura que fiz depois de postar essa pergunta resultou em alguns resultados - não completamente resolvidos, mas de alguma forma úteis.

Eu brinquei um pouco com a altura mínima antes de postar, mas não estava ciente das restrições de tamanho intrínsecas que são relativamente novas para as especificações.

http://caniuse.com/#feat=intrinsic-width

Adicionar um min-height: min-contentà área flexbox resolve o problema no Chrome e, com prefixos de fornecedores, também corrige o Opera e o Safari, embora o Firefox permaneça sem solução.

min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome

Ainda estou procurando idéias sobre o Firefox e outras soluções em potencial.


Eu só queria dizer que ele já funciona para mim no Firefox. Portanto, a solução com conteúdo mínimo foi perfeita.
precisa saber é o seguinte

@pudgereyem Acho que eles implementaram isso então. A outra solução com margin: autoparadas flex-basisde trabalhar para mim, enquanto essa resposta resolveu os dois problemas.
Martin Dawson

Uma solução brilhante, de fato. Eu não me importo com o Edge ou o IE, então isso funciona perfeitamente para mim!
precisa saber é o seguinte

18

Consegui fazer isso com apenas 3 contêineres. O truque é separar o contêiner flexbox do contêiner que controla a rolagem. Por fim, coloque tudo em um contêiner raiz para centralizar tudo. Aqui estão os estilos essenciais para criar o efeito:

CSS:

.root {
  display: flex;
  justify-content: center;
  align-items: center;
}

.scroll-container {
  margin: auto;
  max-height: 100%;
  overflow: auto;
}

.flex-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

HTML:

<div class="root">
  <div class="scroll-container">
    <div class="flex-container">
      <p>Lorem ipsum dolor sit amet.</p>
    </div>
  </div>
</div>

Eu criei uma demonstração aqui: https://jsfiddle.net/r5jxtgba/14/


thx para uma dicas de rolagem-contêiner, eu procurei há dois dias para corrigir o meu conteúdo de rolagem *****!
ArtSx #

Lembre - se, não dê flex: 1 1 autopara o scroll-container. Eu estava fazendo isso com o hábito e entrei em problemas.
AmirHossein

1
O jsfiddle mostra que não funciona quando você adiciona mais conteúdo dentro do contêiner.
bplittle 12/06

4

Eu acho que encontrei uma solução. Funciona com muito texto e pouco texto . Você não precisa especificar as larguras de nada, e ele deve funcionar no IE8.

.wrap1 {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
  overflow-y: auto;
}
.wrap2 {
  display: table;
  width: 100%;
  height: 100%;
  text-align: center;
}
.wrap3 {
  vertical-align: middle;
  display: table-cell;
}
.wrap4 {
  margin: 10px;
}
.dialog {
  text-align: left;
  background-color: white;
  padding: 5px;
  border-radius: 3px;
  margin: auto;
  display: inline-block;
  box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
  <div class="wrap2">
    <div class="wrap3">
      <div class="wrap4">
        <div class="dialog">
          <p>Lorem ipsum dolor sit amet.</p>
        </div>
      </div>
    </div>
  </div>
</div>


Esta é a melhor solução para navegadores herdados. Muito obrigado!
Daniel

5
Uau, isso é um monte de envoltórios.
Nathan Arthur

1
Uau, eu passei horas tentando conseguir isso. (Todos os outros métodos falham no Chrome para dispositivos móveis quando você adiciona animações. Isso não acontece) Muito obrigado!
falsePockets

1

De acordo com o MDN, o safevalor agora pode ser fornecido para propriedades como align-itemse justify-content. É descrito da seguinte forma:

Se o tamanho do item exceder o limite do contêiner de alinhamento, o item será alinhado como se o modo de alinhamento estivesse start.

Portanto, pode ser usado da seguinte maneira.

.rule
{
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: safe center;
}

No entanto, não está claro quanto de suporte ao navegador ele possui, não encontrei nenhum exemplo de uso e estou tendo alguns problemas com ele. Mencionando aqui para chamar mais atenção.


7 de junho de 2018 e ainda não implementado no chrome.
AmirHossein

De acordo com as páginas MDN (atuais), "seguro" e "inseguro" ainda são apenas para o Firefox neste momento (bem, o Safari e a maioria dos navegadores móveis têm suporte desconhecido - eu jogaria com segurança e não assumirei suporte).
JaMiT 18/04/19

O MDN relata o suporte ao Firefox, mas quando o testei no Firefox, ele não pareceu funcionar. jsbin.com/pimoqof/1/edit?html,css,output
Oliver Joseph Ash

Junho 2020 e não na maioria dos navegadores, de acordo com caniuse
den232

0

Eu também consegui fazer isso usando contêiner extra

HTML

<div class="modal-container">
  <div class="modal">
    <div class="content-container">
       <div class="content">
         <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
        </div>
      </div>
  </div>  
</div>

CSS

.modal-container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-color: black;
}

.modal {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #aaa;
  height: 80%;
  width: 90%;
}

.content-container {
  background-color: blue;
  max-height: 100%;
  overflow: auto;
  padding:0;
}

.content {
  display: flex;
  background-color: red;
  padding: 5px;
  width: 900px;
  height: 300px;
}

em jsfiddle> https://jsfiddle.net/Nash171/cpf4weq5/

altere os valores de largura / altura do conteúdo e consulte


0

2 Método Flex de Contêiner com fallback de Tabela testado IE8-9, flex trabalha no IE10,11. Editar: Editado para garantir a centralização vertical quando houver conteúdo mínimo, adicionado suporte herdado.

O problema decorre do fato de a altura ser herdada do tamanho da janela de visualização que causa o estouro das crianças, como Michael respondeu. https://stackoverflow.com/a/33455342/3500688

algo mais simples e use flex para manter o layout no contêiner pop-up (conteúdo):

#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
    /* display: flex; */
    /* flex-wrap: wrap; */
}
		<!--[if lt IE 10]>
<style>
	  #popup {
			display: table;
			width:100%;
		}
		.iewrapper {
			display: table-cell;
			vertical-align: middle;
		}
	</style>
	<![endif]-->
<div id="popup">
	<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
    <div class="container">
        <p class="p3">Test</p>
    <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
    <p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
    </div>
	<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.