Impossibile scorrere verso l'alto dell'articolo flessibile che è un contenitore traboccante


259

Quindi, nel tentativo di creare un utile modale usando flexbox, ho trovato quello che sembra essere un problema del browser e mi chiedo se esiste una correzione nota o una soluzione alternativa o idee su come risolverlo.

La cosa che sto cercando di risolvere ha due aspetti. Innanzitutto, centrando verticalmente la finestra modale, che funziona come previsto. Il secondo è far scorrere la finestra modale - esternamente, quindi l'intera finestra modale scorre, non il contenuto al suo interno (in questo modo è possibile avere menu a discesa e altri elementi dell'interfaccia utente che possono estendersi al di fuori dei limiti del modale - come un selettore di date personalizzato, ecc.)

Tuttavia, quando si combina la centratura verticale con le barre di scorrimento, la parte superiore del modale può diventare inaccessibile quando inizia a traboccare. Nell'esempio sopra, puoi ridimensionare per forzare l'overflow e, così facendo, ti permette di scorrere fino alla fine del modale, ma non verso l'alto (il primo paragrafo viene troncato).

Ecco il link al codice di esempio (altamente semplificato)

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
}

Questi effetti (attuali) Firefox, Safari, Chrome e Opera .. Funziona in modo interessante in IE10 se si commenta nel CSS con prefisso del venditore IE10 - Non ho ancora disturbato i test in IE11, ma suppongo che il comportamento corrisponda a quello di IE10 .

Qualsiasi idea sarebbe buona. Sarebbero utili anche collegamenti a problemi noti o ragionamenti alla base di questo comportamento.

Risposte:


478

Il problema

Flexbox rende il centraggio molto semplice.

Semplicemente applicando align-items: centere justify-content: centeral contenitore flessibile, i tuoi articoli flessibili saranno centrati verticalmente e orizzontalmente.

Tuttavia, esiste un problema con questo metodo quando l'elemento flessibile è più grande del contenitore flessibile.

Come notato nella domanda, quando l'elemento flessibile trabocca il contenitore, la parte superiore diventa inaccessibile.

inserisci qui la descrizione dell'immagine

Per l'overflow orizzontale, la sezione sinistra diventa inaccessibile (o la sezione destra, nelle lingue RTL).

Ecco un esempio con un contenitore LTR con justify-content: centertre elementi flessibili:

inserisci qui la descrizione dell'immagine

Vedi il fondo di questa risposta per una spiegazione di questo comportamento.


Soluzione n. 1

Per risolvere questo problema, utilizzare i margini automatici di flexbox , anziché justify-content.

Con i automargini, un elemento flessibile traboccante può essere centrato verticalmente e orizzontalmente senza perdere l'accesso a qualsiasi parte di esso.

Quindi, invece di questo codice sul contenitore flessibile:

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

Usa questo codice sull'elemento flessibile:

.flex-item {
    margin: auto;
}

inserisci qui la descrizione dell'immagine

Demo rivista


Soluzione n. 2 (non ancora implementata nella maggior parte dei browser)

Aggiungi il safevalore alla regola di allineamento delle parole chiave, in questo modo:

justify-content: safe center

o

align-self: safe center

Dalle specifiche del modulo di allineamento box CSS :

4.4. Overflow Allineamento: l' safee unsafeparole chiave e limiti di sicurezza di scorrimento

Quando [l'elemento flessibile] è più grande del [contenitore flessibile], trabocca. Alcune modalità di allineamento, se rispettate in questa situazione, possono causare la perdita di dati: ad esempio, se i contenuti di una barra laterale sono centrati, quando traboccano possono inviare parte delle loro caselle oltre il bordo iniziale della finestra, che non può essere fatto scorrere fino a .

Per controllare questa situazione, è possibile specificare esplicitamente una modalità di allineamento di overflow . UnsafeL'allineamento rispetta la modalità di allineamento specificata in situazioni di overflow, anche se causa la perdita di dati, mentre l' safeallineamento modifica la modalità di allineamento in situazioni di overflow nel tentativo di evitare la perdita di dati.

Il comportamento predefinito consiste nel contenere l'oggetto di allineamento all'interno dell'area scorrevole, sebbene al momento della stesura di questa funzione di sicurezza non sia ancora implementata.

safe

Se la dimensione dell '[oggetto flessibile] trabocca nel [contenitore flessibile], l' [elemento flessibile] viene invece allineato come se la modalità di allineamento fosse [ flex-start].

unsafe

Indipendentemente dalle dimensioni relative di [oggetto flessibile] e [contenitore flessibile], il valore di allineamento indicato viene rispettato.

Nota: il Box Alignment Module può essere utilizzato su più modelli di layout box, non solo flessibile. Quindi, nell'estratto della specifica sopra, i termini tra parentesi indicano in realtà "oggetto di allineamento", "contenitore di allineamento" e " start". Ho usato termini specifici di flex per focalizzarmi su questo particolare problema.


Spiegazione per la limitazione di scorrimento da MDN:

Considerazioni sugli articoli Flex

Le proprietà di allineamento di Flexbox eseguono un centraggio "vero", a differenza di altri metodi di centraggio nei CSS. Ciò significa che gli oggetti flessibili rimarranno centrati, anche se traboccano il contenitore flessibile.

Questo a volte può essere problematico, tuttavia, se traboccano oltre il bordo superiore della pagina o il bordo sinistro [...], poiché non è possibile scorrere fino a quell'area, anche se è presente del contenuto!

In una versione futura, le proprietà di allineamento verranno estese per avere anche un'opzione "sicura".

Per ora, se questo è un problema, puoi invece utilizzare i margini per raggiungere il centraggio, in quanto risponderanno in modo "sicuro" e smetteranno di centrare se traboccano.

Invece di usare le align-proprietà, basta mettere i automargini sugli oggetti flessibili che si desidera centrare.

Invece delle justify-proprietà, metti i margini automatici sui bordi esterni del primo e dell'ultimo oggetto flessibile nel contenitore flessibile.

I automargini "flettono" e assumono lo spazio rimanente, centrando gli elementi flessibili quando c'è spazio rimanente e passando all'allineamento normale quando no.

Tuttavia, se stai cercando di sostituire justify-contentcon la centratura basata sui margini in un flexbox multilinea, probabilmente sei sfortunato, poiché è necessario posizionare i margini sul primo e sull'ultimo elemento flessibile su ogni riga. A meno che non sia possibile prevedere in anticipo quali elementi finiranno su quale riga, non è possibile utilizzare in modo affidabile la centratura basata sui margini nell'asse principale per sostituire la justify-contentproprietà.


4
Sì, questa è una soluzione migliore e grazie per aver fornito ulteriori informazioni preziose.
jejacks0n

1
Va notato che non funziona in IE11. Lo sfondo verrà tagliato.
Daniel,

2
@Daniel, ho appena testato il codice in IE11. Niente è inaccessibile. In effetti, il problema descritto nella domanda non esiste nemmeno in IE11. È possibile che ci si riferisca al troppo pieno di testo che si verifica solo in IE11. Questo è un altro problema per un'altra domanda.
Michael Benjamin,

11
Per risolvere il problema in IE11: aggiungere align-items: flex-startal contenitore flessibile e conservare l' margin: autoarticolo flessibile.
Eugene Fidelin,

2
Questo non funziona per me quando uso flex-direction: column;
Stefan,

22

Bene, come vuole la Legge di Murphy, la lettura che ho fatto dopo aver pubblicato questa domanda ha prodotto alcuni risultati - non completamente risolti, ma comunque utili.

Ho giocato un po 'con l'altezza minima un po' prima di pubblicare, ma non ero consapevole dei vincoli di dimensionamento intrinseci che sono abbastanza nuovi per le specifiche.

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

L'aggiunta di un'area min-height: min-contenta flexbox risolve il problema in Chrome e con i prefissi del fornitore risolve anche Opera e Safari, sebbene Firefox rimanga irrisolto.

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

Ancora alla ricerca di idee su Firefox e altre potenziali soluzioni.


Volevo solo dire che funziona già per me in Firefox. Quindi la soluzione con contenuto minimo era perfetta.
pudgereyem,

@pudgereyem Immagino che lo abbiano implementato allora. L'altra soluzione con margin: autosmette flex-basisdi funzionare per me mentre questa risposta ha risolto entrambi i problemi.
Martin Dawson,

Una soluzione geniale davvero. Non mi interessa Edge o IE, quindi questo funziona perfettamente per me!
Ohgodwhy,

18

Sono riuscito a farcela con solo 3 contenitori. Il trucco è quello di separare il contenitore flexbox dal contenitore che controlla lo scorrimento. Infine, metti tutto in un contenitore radice per centrare tutto. Ecco gli stili essenziali per creare l'effetto:

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>

Ho creato una demo qui: https://jsfiddle.net/r5jxtgba/14/


grazie per i suggerimenti di un contenitore di scorrimento, ho cercato da due giorni per correggere il mio contenuto ***** scroll !!!
artSx

ricorda, non dare flex: 1 1 autoal scroll-container. Lo stavo facendo per abitudine e ho avuto problemi.
AmirHossein,

1
Il jsfiddle mostra che non funziona quando aggiungi più contenuto all'interno del contenitore.
bplittle

4

Penso di aver trovato una soluzione. Funziona con un sacco di testo e un po 'di testo . Non è necessario specificare le larghezze di nulla e dovrebbe funzionare in 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>


Questa è la soluzione migliore per i browser legacy. Grazie mille!
Daniel,

5
Wow, sono un sacco di avvolgimenti.
Nathan Arthur,

1
Wow, ho passato ore a cercare di raggiungere questo obiettivo. (Tutti gli altri metodi falliscono in Chrome per dispositivi mobili quando aggiungi animazioni. Questo non lo fa) Grazie mille!
falsePockets

1

Secondo MDN, il safevalore può ora essere fornito a proprietà come align-itemse justify-content. È descritto come segue:

Se la dimensione dell'elemento supera il contenitore di allineamento, l'elemento viene invece allineato come se fosse la modalità di allineamento start.

Quindi, potrebbe essere usato come segue.

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

Tuttavia, non è chiaro quanto supporto del browser abbia, non sono riuscito a trovare alcun esempio del suo utilizzo e ho riscontrato alcuni problemi da solo. Menzionandolo qui per attirare più attenzione ad esso.


7 giugno 2018 e non ancora implementato in Chrome.
AmirHossein,

Secondo le (attuali) pagine MDN, "sicuro" e "non sicuro" sono ancora solo Firefox a questo punto (beh, Safari e la maggior parte dei browser mobili hanno un supporto sconosciuto - giocherei sicuro e non assumerei alcun supporto).
JaMiT

MDN riporta il supporto di Firefox, ma quando l'ho provato su Firefox, non sembrava funzionare. jsbin.com/pimoqof/1/edit?html,css,output
Oliver Joseph Ash

Giugno 2020 e non nella maggior parte dei browser, secondo caniuse
den232

0

Sono anche riuscito a farlo utilizzando un contenitore aggiuntivo

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;
}

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

modificare i valori di larghezza / altezza del contenuto e vedere


0

2 Metodo Flex container con Fallback della tabella testato IE8-9, flex funziona in IE10,11. Modifica: modificato per garantire il centraggio verticale quando contenuto minimo, aggiunto supporto legacy.

Il problema deriva dall'altezza ereditata dalle dimensioni del riquadro di visualizzazione che provoca il trabocco dei bambini, come ha risposto Michael. https://stackoverflow.com/a/33455342/3500688

qualcosa di più semplice e usa la flessibilità per mantenere il layout all'interno del contenitore popup (contenuto):

#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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.