Nie można przewijać na górę elementu flex, który jest przepełniony kontenerem

Więc, próbując zrobić użyteczny modal za pomocą flexbox, znalazłem coś, co wydaje się być problemem przeglądarki i zastanawiam się, czy jest znana poprawka lub obejście -- lub pomysły na to, jak go rozwiązać.

To, co próbuję rozwiązać, ma dwa aspekty. Po pierwsze, uzyskanie okna modalnego w pionie, które działa zgodnie z oczekiwaniami. Drugim jest uzyskanie okna modalnego do przewijania -- zewnętrznie, więc całe okno modalne przewija, a nie zawartość w nim (to jest tak, że można mieć rozwijane i inne elementy interfejsu użytkownika, które mogą wykraczać poza granice modalnego -- jak niestandardowy selektor daty, itp.)

Jednak, podczas łączenia pionowego centrowania z paskami przewijania, górna część modalu może stać się niedostępna, gdy zaczyna się przelewać. W powyższym przykładzie można zmienić rozmiar, aby wymusić przepełnienie, a w ten sposób pozwala na przewinięcie do dołu modalnego, ale nie do góry (pierwszy akapit jest odcięty).

Oto link do przykładowego kodu (wysoce uproszczone)

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
}

To efekty (aktualne) Firefox, Safari, Chrome i Opera.. Co ciekawe zachowuje się poprawnie w IE10, jeśli skomentujesz w IE10 prefiks css-nie zawracałem sobie głowy testowaniem w IE11 jeszcze, ale zakładam, że zachowanie pasuje do IE10.

Każdy pomysł byłby dobry. Przydatne byłyby również linki do znanych problemów lub rozumowanie za tym zachowaniem.
Author: Michael Benjamin, 2015-10-31

7 answers

Problem

Flexbox ułatwia centrowanie.

Po prostu zastosuj align-items: center i justify-content: center do pojemnika flex, twoje elementy flex będą wyśrodkowane pionowo i poziomo.

Jednakże, istnieje problem z tą metodą, gdy element flex jest większy niż kontener flex.

Jak wspomniano w pytaniu, gdy element flex przepełnia Pojemnik, top staje się niedostępny.

Tutaj wpisz opis obrazka

Do przelewu poziomego, lewa sekcja staje się niedostępna (lub prawa sekcja, w językach RTL).

Oto przykład z kontenerem LTR posiadającym justify-content: center i trzy elementy flex:

Tutaj wpisz opis obrazka

wyjaśnienie tego zachowania znajduje się na dole tej odpowiedzi.


Rozwiązanie # 1

Aby rozwiązać ten problem użyj flexbox Auto, zamiast justify-content.

Z auto marginesem, przepełniony element flex może być pionowo i poziomo wyśrodkowany bez utraty dostępu do jakiejkolwiek jego części.

Więc zamiast tego kodu na kontenerze flex:

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

Użyj tego kodu na elemencie flex:

.flex-item {
    margin: auto;
}

Tutaj wpisz opis obrazka

Revised Demo


Rozwiązanie # 2 (jeszcze nie zaimplementowane w większości przeglądarek)

Dodaj wartość safe do reguły wyrównania słów kluczowych, tak:

justify-content: safe center

Lub

align-self: safe center

From The CSS Box Alignment Module Specyfikacja :

4.4. Wyrównanie przepełnienia: słowa kluczowe safe i unsafe oraz bezpieczeństwo przewijania limity

Gdy [element flex] jest większy niż [kontener flex], będzie przepełnienie. Niektóre tryby wyrównywania, jeśli w tej sytuacji są honorowane, mogą spowodować utratę danych. na przykład, jeśli zawartość paska bocznego jest wyśrodkowane, gdy przepełnią się mogą wysłać część swoich skrzynek za krawędź startowa okna widokowego, do której nie można przewijać.

Aby kontrolować tę sytuację, an wyrównanie przepełnienia tryb może być wyraźnie określone. Unsafe wyrównanie tryb wyrównania w sytuacjach przepełnienia, nawet jeśli powoduje utratę danych, podczas gdy safe wyrównanie zmienia tryb wyrównania w przepełnieniu sytuacje w celu uniknięcia utraty danych.

Domyślnym zachowaniem jest umieszczenie obiektu wyrównania w przewijalny obszar, choć w momencie pisania tej funkcji bezpieczeństwa jest nie jeszcze wdrożone.

safe

Jeśli rozmiar [elementu flex] przepełnia [kontener flex], [element flex] jest wyrównany tak, jakby tryb wyrównania był [flex-start].

unsafe

Niezależnie od względnych rozmiarów [flex item] i [flex kontener], podana wartość wyrównania jest honorowana.

Uwaga: moduł wyrównywania skrzynek jest przeznaczony do użytku w wielu skrzynkach modele układu, nie tylko flex. Tak więc w powyższym fragmencie specyfikacji terminy w nawiasach mówią "alignment subject"," alignment container " i " start". Użyłem terminów specyficznych dla flex, aby skupić się na tym konkretnym problemie.


Wyjaśnienie ograniczenia przewijania z MDN:

Element Flex rozważania

Właściwości wyrównania Flexbox 'a robią" prawdziwe " centrowanie, w przeciwieństwie do innych metody centrowania w CSS. Oznacza to, że elementy flex will stay wyśrodkowane, nawet jeśli przepełnią Pojemnik flex.

Czasami może to być problematyczne, jednak, jeśli przepełnia się obok górna krawędź strony lub lewa krawędź [...], jako nie możesz przewijać tego obszaru, nawet jeśli jest tam zawartość!

W przyszłym wydaniu właściwości wyrównania zostaną rozszerzone o opcja "Bezpieczna" również.

Na razie, jeśli jest to problemem, możesz zamiast tego użyć marginesów, aby osiągnąć centrowanie, jak będą reagować w sposób "bezpieczny" i przestać centrować, jeśli przepełniają się.

Zamiast używać właściwości align-, po prostu umieść auto marginesy na elementy flex, które chcesz wyśrodkować.

Zamiast właściwości justify- umieść marginesy auto Na Zewnątrz krawędzie pierwszego i ostatniego elementu flex w kontenerze flex.

Marginesy auto "zginą" i przyjmą pozostałą przestrzeń, centrowanie elementów flex, gdy jest resztka miejsca, i przełączanie do normy / align = "left" /

Jeśli jednak próbujesz zastąpić justify-content centrowanie oparte na marży W multi-line flexbox, prawdopodobnie nie masz szczęście, ponieważ musisz umieścić marginesy na pierwszym i ostatnim elemencie flex na każdej linii. Chyba, że można przewidzieć z wyprzedzeniem, które przedmioty będą kończy się na jakiej linii, nie można niezawodnie korzystać z centrowania opartego na marży w główna oś zastępująca właściwość justify-content.

 576
Author: Michael Benjamin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-05 00:39:31

Cóż, zgodnie z Prawem Murphy ' ego, czytanie, które zrobiłem po opublikowaniu tego pytania, przyniosło kilka rezultatów - nie do końca rozwiązanych, ale mimo wszystko przydatnych.

Grałem trochę z min-height przed publikacją, ale nie byłem świadomy wewnętrznych ograniczeń rozmiaru, które są dość nowe w specyfikacji.

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

Dodanie min-height: min-content do obszaru flexbox rozwiązuje problem w Chrome, a z prefiksami dostawcy naprawia również operę i Safari, choć Firefox pozostaje nierozwiązany.

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

Wciąż szukam pomysłów na Firefoksa i inne potencjalne rozwiązania.

 23
Author: jejacks0n,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-31 17:51:08

Udało mi się to zrobić tylko trzema pojemnikami. Sztuką jest oddzielenie pojemnika flexbox od pojemnika kontrolującego przewijanie. Na koniec umieść wszystko w kontenerze głównym, aby wyśrodkować wszystko. Oto podstawowe style do tworzenia efektu:

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>

Stworzyłem demo tutaj: https://jsfiddle.net/r5jxtgba/14/

 19
Author: colinbr96,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 11:07:17

Chyba znalazłem rozwiązanie. Działa z dużą ilością tekstu i małym tekstem . Nie musisz określać szerokości czegokolwiek, a to powinno działać w 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>
 3
Author: mpen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-15 23:04:07

Zgodnie z MDN, wartość safe może być teraz dostarczana do właściwości takich jak align-items oraz justify-content. Opisywany jest następująco:

Jeśli rozmiar elementu przepełnia kontener wyrównania, element jest wyrównany tak, jakby tryb wyrównania był start.

Więc, może być stosowany w następujący sposób.

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

Nie jest jednak jasne, ile ma wsparcia dla przeglądarki, nie mogłem znaleźć żadnych przykładów jej użycia, a miałem pewne problemy z ja też. Wspominając o tym tutaj, aby zwrócić na to większą uwagę.

 1
Author: Chris Talman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-04 13:52:09

Udało mi się również zrobić to za pomocą dodatkowego pojemnika

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

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

Zmień .content width/height wartości i patrz

 0
Author: Nadeesh Peiris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 08:38:44

2 Container Flex Method with table fallback tested IE8-9, flex działa w IE10,11. Edycja: edytowano, aby zapewnić pionowe centrowanie przy minimalnej zawartości, dodano obsługę starszych wersji.

Problem wynika z tego, że wysokość jest dziedziczona z rozmiaru ekranu, co powoduje przepełnienie dzieci, jak odpowiedział Michael. https://stackoverflow.com/a/33455342/3500688

Coś prostszego i użyj flex, aby utrzymać układ w kontenerze popup (zawartość):

#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>
 0
Author: Silverandrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-17 00:52:17