Tidak dapat menggulir ke atas item fleksibel yang meluap wadah

259

Jadi, dalam mencoba membuat modal yang berguna menggunakan flexbox, saya menemukan apa yang tampaknya menjadi masalah browser dan saya bertanya-tanya apakah ada perbaikan yang diketahui atau solusi - atau ide tentang cara mengatasinya.

Hal yang saya coba selesaikan, memiliki dua aspek. Pertama, membuat jendela modal terpusat secara vertikal, yang berfungsi seperti yang diharapkan. Yang kedua adalah untuk mendapatkan jendela modal untuk menggulir - secara eksternal, sehingga seluruh jendela modal akan menggulir, bukan isi di dalamnya (ini adalah agar Anda dapat memiliki dropdown dan elemen UI lainnya yang dapat melampaui batas modal - seperti pemilih tanggal kustom, dll.)

Namun, ketika menggabungkan pemusatan vertikal dengan bilah gulir, bagian atas modal bisa menjadi tidak dapat diakses karena mulai meluap. Dalam contoh di atas, Anda dapat mengubah ukuran untuk memaksa overflow, dan dengan melakukannya Anda dapat menggulir ke bagian bawah modal, tetapi tidak ke atas (paragraf pertama terputus).

Berikut tautan ke kode contoh (sangat disederhanakan)

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
}

Ini efek (saat ini) Firefox, Safari, Chrome, dan Opera .. Itu memang menarik berperilaku benar di IE10 jika Anda berkomentar di IE10 vender prefixed css - Saya tidak repot-repot menguji di IE11, tetapi menganggap perilaku cocok dengan IE10 .

Ada ide yang bagus. Tautan ke masalah yang diketahui, atau alasan di balik perilaku ini juga akan berguna.

jejacks0n
sumber

Jawaban:

478

Masalah

Flexbox membuat pemusatan sangat mudah.

Dengan hanya menerapkan align-items: centerdan justify-content: centerke wadah fleksibel, item fleksibel Anda akan terpusat secara vertikal dan horizontal.

Namun, ada masalah dengan metode ini ketika item fleksibel lebih besar dari wadah fleksibel.

Seperti disebutkan dalam pertanyaan, ketika item fleksibel meluap wadah bagian atas menjadi tidak dapat diakses.

masukkan deskripsi gambar di sini

Untuk overflow horisontal, bagian kiri menjadi tidak dapat diakses (atau bagian kanan, dalam bahasa RTL).

Berikut adalah contoh dengan wadah LTR memiliki justify-content: centerdan tiga item fleksibel:

masukkan deskripsi gambar di sini

Lihat bagian bawah jawaban ini untuk penjelasan tentang perilaku ini.


Solusi # 1

Untuk memperbaiki masalah ini, gunakan margin otomatis flexbox , bukan justify-content.

Dengan automargin, item flex yang meluap dapat dipusatkan secara vertikal dan horizontal tanpa kehilangan akses ke bagian mana pun darinya.

Jadi alih-alih kode ini pada wadah fleksibel:

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

Gunakan kode ini pada item fleksibel:

.flex-item {
    margin: auto;
}

masukkan deskripsi gambar di sini

Demo yang Direvisi


Solusi # 2 (belum diterapkan di sebagian besar browser)

Tambahkan safenilai ke aturan pelurusan kata kunci Anda, seperti ini:

justify-content: safe center

atau

align-self: safe center

Dari spesifikasi Modul Kotak Alignment CSS :

4.4. Overflow Alignment: safedan unsafekata kunci serta batas keamanan gulir

Ketika [item fleksibel] lebih besar dari [kontainer fleksibel], itu akan meluap. Beberapa mode penyelarasan, jika merasa terhormat dalam situasi ini, dapat menyebabkan kehilangan data: misalnya, jika konten bilah sisi berada di tengah, ketika mereka meluap mereka dapat mengirim bagian dari kotak mereka melewati tepi awal viewport, yang tidak dapat digulir ke .

Untuk mengontrol situasi ini, mode pelurusan overflow dapat ditentukan secara eksplisit. Unsafeperataan menghormati mode perataan yang ditentukan dalam situasi luapan, bahkan jika itu menyebabkan kehilangan data, sementara safeperataan mengubah mode perataan dalam situasi luapan dalam upaya untuk menghindari kehilangan data.

Perilaku default adalah memuat subjek pelurusan dalam area yang dapat digulir, meskipun pada saat penulisan fitur keselamatan ini belum diterapkan.

safe

Jika ukuran [item fleksibel] melebihi [kontainer fleksibel], [item fleksibel] disejajarkan seolah-olah mode alignment adalah [ flex-start].

unsafe

Terlepas dari ukuran relatif dari [item fleksibel] dan [kontainer fleksibel], nilai penyelarasan yang diberikan dihormati.

Catatan: Box Alignment Module digunakan untuk berbagai model tata letak kotak, bukan hanya fleksibel. Jadi dalam kutipan spesifikasi di atas, istilah dalam tanda kurung sebenarnya mengatakan "subjek pelurusan", "wadah pelurusan" dan " start". Saya menggunakan istilah khusus-fleksibel untuk menjaga fokus pada masalah khusus ini.


Penjelasan untuk batasan gulir dari MDN:

Pertimbangan item fleksibel

Properti perataan Flexbox melakukan pemusatan "benar", tidak seperti metode pemusatan lainnya di CSS. Ini berarti bahwa item flex akan tetap berada di tengah, bahkan jika item tersebut meluap wadah flex.

Namun, terkadang hal ini dapat menimbulkan masalah, jika meluap melewati tepi atas halaman, atau tepi kiri [...], karena Anda tidak dapat menggulir ke area itu, bahkan jika ada konten di sana!

Dalam rilis yang akan datang, properti pelurusan akan diperluas untuk memiliki opsi "aman" juga.

Untuk saat ini, jika ini merupakan masalah, Anda dapat menggunakan margin untuk mencapai pemusatan, karena mereka akan merespons dengan cara yang "aman" dan berhenti pemusatan jika meluap.

Alih-alih menggunakan align-properti, cukup beri automargin pada item fleksibel yang ingin Anda pusatkan.

Alih-alih justify-properti, letakkan margin otomatis di tepi luar item flex pertama dan terakhir dalam wadah flex.

The automargin akan "fleksibel" dan menganggap ruang sisa, berpusat item fleksibel ketika ada sisa ruang, dan beralih ke keselarasan normal ketika tidak.

Namun, jika Anda mencoba untuk mengganti justify-contentdengan pemusatan berbasis margin dalam kotak multi-line, Anda mungkin kurang beruntung, karena Anda perlu menempatkan margin pada item flex pertama dan terakhir pada setiap baris. Kecuali jika Anda dapat memprediksi sebelumnya item mana yang akan berakhir pada baris mana, Anda tidak dapat menggunakan pemusatan berbasis margin pada sumbu utama untuk mengganti justify-contentproperti.

Michael Benjamin
sumber
4
Ya, itu solusi yang lebih baik, dan terima kasih telah memberikan wawasan berharga tambahan.
jejacks0n
1
Perlu dicatat bahwa ini tidak bekerja di IE11. Latar belakang akan terpotong.
Daniel
2
@Aniel, saya baru saja menguji kode di IE11. Tidak ada yang tidak dapat diakses. Bahkan, masalah yang dijelaskan dalam pertanyaan bahkan tidak ada di IE11. Anda mungkin merujuk pada teks yang terjadi hanya terjadi di IE11. Itu masalah lain untuk pertanyaan lain.
Michael Benjamin
11
Untuk memperbaiki masalah di IE11: tambahkan align-items: flex-startke wadah flex dan simpan margin: autountuk item flex.
Eugene Fidelin
2
Ini tidak berfungsi untuk saya saat menggunakan arah-fleksibel: kolom;
Stefan
22

Yah, sebagaimana Hukum Murphy akan memilikinya, bacaan yang saya lakukan setelah memposting pertanyaan ini menghasilkan beberapa hasil - tidak sepenuhnya terselesaikan, tetapi tetap berguna.

Saya bermain-main dengan min-height sedikit sebelum memposting, tetapi tidak menyadari kendala ukuran intrinsik yang cukup baru untuk spesifikasi.

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

Menambahkan min-height: min-contentke area flexbox tidak menyelesaikan masalah di Chrome, dan dengan awalan vendor juga memperbaiki Opera dan Safari, meskipun Firefox tetap belum terselesaikan.

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

Masih mencari ide di Firefox, dan solusi potensial lainnya.

jejacks0n
sumber
Saya hanya ingin mengatakan bahwa itu sudah berfungsi untuk saya di Firefox. Jadi solusi dengan min-content sangat sempurna.
pudgereyem
@ pudgereyem Saya kira mereka menerapkannya. Solusi lain dengan margin: autoberhenti flex-basisbekerja untuk saya sedangkan jawaban ini menyelesaikan kedua masalah.
Martin Dawson
Benar-benar solusi yang brilian. Saya tidak peduli dengan Edge atau IE, jadi ini berfungsi dengan baik untuk saya!
Ohgod
18

Saya berhasil melakukan ini hanya dengan 3 kontainer. Caranya adalah dengan memisahkan wadah flexbox dari wadah yang mengontrol pengguliran. Terakhir, masukkan semuanya ke dalam wadah root untuk memusatkan semuanya. Berikut adalah gaya-gaya penting untuk menciptakan efek:

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>

Saya telah membuat demo di sini: https://jsfiddle.net/r5jxtgba/14/

colinbr96
sumber
thx untuk tips scroll-container, saya mencari sejak dua hari untuk memperbaiki konten gulir ***** saya !!!
artSx
ingat, jangan berikan flex: 1 1 autoke scroll-container. Saya melakukan ini dengan kebiasaan dan mendapat masalah.
AmirHossein
1
Jsfiddle menunjukkan bahwa itu tidak berfungsi ketika Anda menambahkan lebih banyak konten di dalam wadah.
bplittle
4

Saya pikir saya menemukan solusi. Ini berfungsi dengan banyak teks dan sedikit teks . Anda tidak perlu menentukan lebar apa pun, dan itu harus bekerja di 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>

Mpen
sumber
Ini adalah solusi terbaik untuk browser lawas. Terima kasih banyak!
Daniel
5
Wow, itu banyak sekali.
Nathan Arthur
1
Wow, saya sudah menghabiskan berjam - jam mencoba untuk mencapai ini. (Semua metode lain gagal di chrome seluler ketika Anda menambahkan animasi. Ini tidak) Terima kasih banyak!
falsePockets
1

Menurut MDN, safenilai sekarang dapat diberikan ke properti seperti align-itemsdan justify-content. Dijelaskan sebagai berikut:

Jika ukuran item meluap wadah pelurusan, item itu malah sejajar seolah-olah mode penyelarasan itu start.

Jadi, bisa digunakan sebagai berikut.

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

Namun, tidak jelas berapa banyak dukungan browser yang dimilikinya, saya tidak dapat menemukan contoh penggunaannya, dan saya sendiri mengalami beberapa masalah. Menyebutkannya di sini untuk menarik lebih banyak perhatian padanya.

Chris Talman
sumber
7 Juni 2018 dan masih belum diimplementasikan di chrome.
AmirHossein
Menurut halaman MDN (saat ini), "aman" dan "tidak aman" masih hanya Firefox pada saat ini (well, Safari dan sebagian besar peramban seluler memiliki dukungan yang tidak diketahui - saya akan memainkannya dengan aman dan menganggap tidak ada dukungan).
JaMiT
MDN melaporkan dukungan Firefox, tetapi ketika saya mengujinya di Firefox, sepertinya tidak berhasil. jsbin.com/pimoqof/1/edit?html,cssoutoutput
Oliver Joseph Ash
Juni 2020 dan tidak di sebagian besar browser, menurut caniuse
den232
0

Saya juga berhasil melakukannya menggunakan wadah tambahan

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

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

ubah nilai .content width / height dan lihat

Nadeesh Peiris
sumber
0

2 Metode Flex Container dengan Table fallback menguji IE8-9, flex bekerja di IE10,11. Sunting: Diedit untuk memastikan pemusatan vertikal saat konten minimal, menambahkan dukungan lawas.

Masalahnya bermula dari ketinggian yang diwarisi dari ukuran viewport yang menyebabkan anak-anak meluap, seperti yang dijawab Michael. https://stackoverflow.com/a/33455342/3500688

sesuatu yang lebih sederhana dan gunakan flex untuk mempertahankan tata letak dalam wadah sembulan (konten):

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