Es kann nicht zum oberen Rand des Flex-Elements gescrollt werden, dessen Container überläuft

259

Bei dem Versuch, mithilfe von Flexbox ein nützliches Modal zu erstellen, habe ich ein scheinbares Browserproblem festgestellt und mich gefragt, ob es eine bekannte Lösung oder Problemumgehung gibt - oder Ideen zur Lösung.

Das, was ich zu lösen versuche, hat zwei Aspekte. Zunächst wird das modale Fenster vertikal zentriert, was wie erwartet funktioniert. Das zweite besteht darin, das modale Fenster zum Scrollen zu bringen - extern, sodass das gesamte modale Fenster gescrollt wird, nicht der Inhalt darin (dies bedeutet, dass Sie Dropdowns und andere UI-Elemente haben können, die sich außerhalb der Grenzen des modalen Fensters erstrecken können -. wie eine benutzerdefinierte Datumsauswahl usw.)

Wenn Sie jedoch die vertikale Zentrierung mit Bildlaufleisten kombinieren, kann die Oberseite des Modals unzugänglich werden, wenn es zu überlaufen beginnt. Im obigen Beispiel können Sie die Größe ändern, um den Überlauf zu erzwingen. Auf diese Weise können Sie zum unteren Rand des Modals scrollen, jedoch nicht zum oberen Rand (der erste Absatz ist abgeschnitten).

Hier ist der Link zum Beispielcode (stark vereinfacht)

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
}

Dies wirkt sich auf (aktuelles) Firefox, Safari, Chrome und Opera aus. Interessanterweise verhält es sich in IE10 korrekt, wenn Sie im IE10-Vendor-Präfix CSS einen Kommentar abgeben. Ich habe mich noch nicht um das Testen in IE11 gekümmert, gehe jedoch davon aus, dass das Verhalten mit dem von IE10 übereinstimmt .

Irgendwelche Ideen wären gut. Links zu bekannten Problemen oder Begründungen für dieses Verhalten wären ebenfalls hilfreich.

jejacks0n
quelle

Antworten:

478

Das Problem

Flexbox macht das Zentrieren sehr einfach.

Durch einfaches Aufbringen align-items: centerund justify-content: centerauf den Flex-Container werden Ihre Flex-Elemente vertikal und horizontal zentriert.

Bei dieser Methode tritt jedoch ein Problem auf, wenn das Flex-Element größer als der Flex-Container ist.

Wie in der Frage erwähnt, ist der Deckel nicht mehr zugänglich, wenn der Flexgegenstand über den Behälter läuft.

Geben Sie hier die Bildbeschreibung ein

Bei horizontalem Überlauf ist der linke Abschnitt nicht mehr zugänglich (oder der rechte Abschnitt in RTL-Sprachen).

Hier ist ein Beispiel mit einem LTR-Container mit justify-content: centerdrei flexiblen Elementen:

Geben Sie hier die Bildbeschreibung ein

Eine Erklärung dieses Verhaltens finden Sie am Ende dieser Antwort.


Lösung Nr. 1

Um dieses Problem zu beheben, verwenden Sie anstelle von Flexbox Auto Randsjustify-content .

Mit autoRändern kann ein überlaufendes flexibles Element vertikal und horizontal zentriert werden, ohne den Zugriff auf einen Teil davon zu verlieren.

Also anstelle dieses Codes auf dem Flex-Container:

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

Verwenden Sie diesen Code für das Flex-Element:

.flex-item {
    margin: auto;
}

Geben Sie hier die Bildbeschreibung ein

Überarbeitete Demo


Lösung 2 (in den meisten Browsern noch nicht implementiert)

Fügen Sie den safeWert wie folgt zu Ihrer Keyword-Ausrichtungsregel hinzu:

justify-content: safe center

oder

align-self: safe center

Aus der Spezifikation des CSS-Box-Ausrichtungsmoduls :

4.4. Überlauf Ausrichtung: die safeund unsafeKeywords und Scroll - Sicherheitsgrenzen

Wenn das [Flex-Element] größer als der [Flex-Container] ist, läuft es über. Einige Ausrichtungsmodi können, wenn sie in dieser Situation berücksichtigt werden, zu Datenverlust führen. Wenn beispielsweise der Inhalt einer Seitenleiste zentriert ist und sie überlaufen, senden sie möglicherweise einen Teil ihrer Felder über die Startkante des Ansichtsfensters hinaus, zu der kein Bildlauf durchgeführt werden kann .

Um diese Situation zu steuern, kann ein Überlaufausrichtungsmodus explizit angegeben werden. UnsafeDie Ausrichtung berücksichtigt den angegebenen Ausrichtungsmodus in Überlaufsituationen, auch wenn dies zu Datenverlust führt, während die safeAusrichtung den Ausrichtungsmodus in Überlaufsituationen ändert, um Datenverlust zu vermeiden.

Das Standardverhalten besteht darin, das Ausrichtungsobjekt im scrollbaren Bereich zu enthalten, obwohl diese Sicherheitsfunktion zum Zeitpunkt des Schreibens noch nicht implementiert ist.

safe

Wenn die Größe des [Flex-Elements] den [Flex-Container] überschreitet, wird das [Flex-Element] stattdessen so ausgerichtet, als wäre der Ausrichtungsmodus [ flex-start].

unsafe

Unabhängig von den relativen Größen des [Flex-Elements] und des [Flex-Containers] wird der angegebene Ausrichtungswert berücksichtigt.

Hinweis: Das Box-Ausrichtungsmodul kann für mehrere Box-Layout-Modelle verwendet werden, nicht nur für Flex. Im obigen Spezifikationsauszug sagen die Begriffe in Klammern tatsächlich "Ausrichtungsgegenstand", "Ausrichtungscontainer" und " start". Ich habe flex-spezifische Begriffe verwendet, um mich auf dieses spezielle Problem zu konzentrieren.


Erläuterung zur Bildlaufbeschränkung von MDN:

Überlegungen zu Flex-Elementen

Die Ausrichtungseigenschaften von Flexbox führen im Gegensatz zu anderen Zentrierungsmethoden in CSS eine "echte" Zentrierung durch. Dies bedeutet, dass die Flex-Elemente zentriert bleiben, auch wenn sie den Flex-Container überlaufen.

Dies kann jedoch manchmal problematisch sein, wenn sie über den oberen Rand der Seite oder den linken Rand [...] hinauslaufen, da Sie nicht in diesen Bereich scrollen können, selbst wenn dort Inhalt vorhanden ist!

In einer zukünftigen Version werden die Ausrichtungseigenschaften erweitert, um auch eine "sichere" Option zu haben.

Wenn dies ein Problem darstellt, können Sie stattdessen Ränder verwenden, um die Zentrierung zu erreichen, da diese "sicher" reagieren und die Zentrierung beenden, wenn sie überlaufen.

Anstatt die align-Eigenschaften zu verwenden, setzen autoSie einfach Ränder auf die Flex-Elemente, die Sie zentrieren möchten.

Platzieren Sie anstelle der justify-Eigenschaften automatische Ränder an den Außenkanten des ersten und letzten Flex-Elements im Flex-Container.

Die autoRänder "biegen" sich und nehmen den verbleibenden Platz ein, zentrieren die Flex-Elemente, wenn noch Platz übrig ist, und wechseln zur normalen Ausrichtung, wenn dies nicht der Fall ist.

Wenn Sie jedoch versuchen, justify-contentin einer mehrzeiligen Flexbox durch eine randbasierte Zentrierung zu ersetzen , haben Sie wahrscheinlich kein Glück, da Sie die Ränder auf das erste und letzte Flexelement in jeder Zeile setzen müssen. Wenn Sie nicht im Voraus vorhersagen können, welche Elemente in welcher Zeile landen, können Sie die justify-contentEigenschaft nicht zuverlässig durch randbasierte Zentrierung in der Hauptachse ersetzen .

Michael Benjamin
quelle
4
Ja, das ist eine bessere Lösung, und ich danke Ihnen, dass Sie zusätzliche wertvolle Erkenntnisse geliefert haben.
jejacks0n
1
Es ist zu beachten, dass dies in IE11 nicht funktioniert. Der Hintergrund wird abgeschnitten.
Daniel
2
@ Daniel, ich habe gerade den Code in IE11 getestet. Nichts ist unzugänglich. Tatsächlich existiert das in der Frage beschriebene Problem nicht einmal in IE11. Möglicherweise beziehen Sie sich auf den Textüberlauf, der nur in IE11 auftritt. Das ist ein anderes Problem für eine andere Frage.
Michael Benjamin
11
So beheben Sie das Problem in IE11: Fügen Sie align-items: flex-startes dem Flex-Container hinzu und bewahren Sie es margin: autofür das Flex-Element auf.
Eugene Fidelin
2
Dies funktioniert bei mir nicht, wenn die Flex-Richtung verwendet wird: column;
Stefan
22

Nun, wie Murphys Gesetz es wollte, führte die Lektüre, die ich nach dem Posten dieser Frage gemacht habe, zu einigen Ergebnissen - nicht vollständig gelöst, aber dennoch etwas nützlich.

Ich habe vor dem Posten ein wenig mit der Mindesthöhe herumgespielt, war mir jedoch der Größenbeschränkungen nicht bewusst, die für die Spezifikation ziemlich neu sind.

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

Durch Hinzufügen eines min-height: min-contentzum Flexbox-Bereich wird das Problem in Chrome behoben, und mit Herstellerpräfixen werden auch Opera und Safari behoben, obwohl Firefox weiterhin ungelöst ist.

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

Ich suche immer noch nach Ideen für Firefox und andere mögliche Lösungen.

jejacks0n
quelle
Ich wollte nur sagen, dass es in Firefox bereits für mich funktioniert. Die Lösung mit Min-Content war also perfekt.
pudgereyem
@pudgereyem Ich denke, sie haben es dann implementiert. Die andere Lösung mit margin: autoAnschlägen flex-basisaus für mich arbeiten , während diese Antwort beider Probleme gelöst.
Martin Dawson
Eine brillante Lösung. Edge oder IE interessieren mich nicht, daher funktioniert dies perfekt für mich!
Ohgodwhy
18

Ich habe es mit nur 3 Containern geschafft. Der Trick besteht darin, den Flexbox-Container von dem Container zu trennen, der das Scrollen steuert. Zuletzt legen Sie alles in einen Root-Container, um alles zu zentrieren. Hier sind die wesentlichen Stile, um den Effekt zu erzielen:

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>

Ich habe hier eine Demo erstellt: https://jsfiddle.net/r5jxtgba/14/

colinbr96
quelle
Danke für einen Scroll-Container-Tipp, ich habe seit zwei Tagen nach Fix für meinen ***** Scroll-Inhalt gesucht !!!
ArtSx
Denken Sie daran, geben Sie nicht flex: 1 1 autoan die scroll-container. Ich tat dies aus Gewohnheit und geriet in ein Problem.
AmirHossein
1
Die jsfiddle zeigt, dass es nicht funktioniert, wenn Sie mehr Inhalt in den Container einfügen.
Kleiner
4

Ich glaube, ich habe eine Lösung gefunden. Es funktioniert mit viel Text und ein wenig Text . Sie müssen die Breite von nichts angeben, und es sollte in IE8 funktionieren.

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

mpen
quelle
Dies ist die beste Lösung für ältere Browser. Vielen Dank!
Daniel
5
Wow, das sind viele Wraps.
Nathan Arthur
1
Wow, ich habe Stunden damit verbracht , dies zu erreichen. (Alle anderen Methoden schlagen in Mobile Chrome fehl, wenn Sie Animationen hinzufügen. Dies ist nicht der Fall.) Vielen Dank!
falsePockets
1

Laut MDN kann der safeWert nun für Eigenschaften wie align-itemsund bereitgestellt werden justify-content. Es wird wie folgt beschrieben:

Wenn die Größe des Elements den Ausrichtungscontainer überschreitet, wird das Element stattdessen so ausgerichtet, als ob der Ausrichtungsmodus wäre start.

Es könnte also wie folgt verwendet werden.

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

Es ist jedoch unklar, wie viel Browserunterstützung es hat, ich konnte keine Beispiele für seine Verwendung finden und ich hatte selbst einige Probleme damit. Erwähnen Sie es hier, um mehr Aufmerksamkeit darauf zu lenken.

Chris Talman
quelle
7. Juni 2018 und noch nicht in Chrom implementiert.
AmirHossein
Laut den (aktuellen) MDN-Seiten sind "sicher" und "unsicher" zu diesem Zeitpunkt immer noch nur für Firefox verfügbar (nun, Safari und die meisten mobilen Browser haben unbekannte Unterstützung - ich würde auf Nummer sicher gehen und keine Unterstützung annehmen).
JaMiT
MDN meldet Firefox-Unterstützung, aber als ich es in Firefox getestet habe, schien es nicht zu funktionieren. jsbin.com/pimoqof/1/edit?html,css,output
Oliver Joseph Ash
Juni 2020 und nicht in den meisten Browsern, laut caniuse
den232
0

Ich habe es auch mit einem zusätzlichen Container geschafft

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/

Ändern Sie die Werte für die Breite / Höhe des Inhalts und sehen Sie

Nadeesh Peiris
quelle
0

2 Container Flex-Methode mit Table Fallback getestet IE8-9, Flex funktioniert in IE10,11. Bearbeiten: Bearbeitet, um eine vertikale Zentrierung bei minimalem Inhalt sicherzustellen. Unterstützung für ältere Benutzer hinzugefügt.

Das Problem ist darauf zurückzuführen, dass die Höhe von der Größe des Ansichtsfensters geerbt wird, wodurch Kinder überlaufen, wie Michael antwortete. https://stackoverflow.com/a/33455342/3500688

etwas einfacheres und verwenden Sie flex, um das Layout innerhalb des Popup-Containers (Inhalt) zu pflegen:

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

Silverandrew
quelle