Không thể cuộn lên trên cùng của mục flex đang tràn container


259

Vì vậy, khi cố gắng tạo ra một phương thức hữu ích bằng flexbox, tôi đã tìm thấy vấn đề có vẻ là vấn đề của trình duyệt và tự hỏi liệu có một bản sửa lỗi hoặc cách khắc phục nào - hoặc ý tưởng về cách giải quyết nó.

Điều tôi đang cố gắng giải quyết, có hai khía cạnh. Đầu tiên, lấy cửa sổ phương thức tập trung theo chiều dọc, hoạt động như mong đợi. Thứ hai là để cửa sổ phương thức cuộn - bên ngoài, do đó, toàn bộ cửa sổ phương thức cuộn, không phải nội dung bên trong nó (điều này để bạn có thể thả xuống và các thành phần UI khác có thể mở rộng ra ngoài giới hạn của phương thức - như một công cụ chọn ngày tùy chỉnh, v.v.)

Tuy nhiên, khi kết hợp định tâm dọc với các thanh cuộn, phần trên của phương thức có thể không truy cập được khi nó bắt đầu tràn. Trong ví dụ trên, bạn có thể thay đổi kích thước để buộc tràn, và khi làm như vậy, nó cho phép bạn cuộn xuống dưới cùng của phương thức, nhưng không phải ở trên cùng (đoạn đầu tiên bị cắt).

Đây là liên kết đến mã ví dụ (rất đơn giản)

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
}

Hiệu ứng này (hiện tại) Firefox, Safari, Chrome và Opera .. Nó thực sự hoạt động chính xác trong IE10 nếu bạn nhận xét trong css của trình duyệt IE10 có tiền tố css - Tôi chưa bận tâm kiểm tra trong IE11, nhưng giả sử hành vi phù hợp với IE10 .

Bất kỳ ý tưởng sẽ được tốt. Liên kết đến các vấn đề đã biết hoặc lý do đằng sau hành vi này cũng sẽ hữu ích.

Câu trả lời:


478

Vấn đề

Flexbox làm cho việc định tâm rất dễ dàng.

Chỉ cần áp dụng align-items: centerjustify-content: centervào hộp chứa flex, (các) mục flex của bạn sẽ được căn giữa theo chiều dọc và chiều ngang.

Tuy nhiên, có một vấn đề với phương pháp này khi vật phẩm flex lớn hơn vật chứa flex.

Như đã lưu ý trong câu hỏi, khi vật phẩm flex tràn vào thùng chứa, phần trên sẽ không thể truy cập được.

nhập mô tả hình ảnh ở đây

Đối với tràn ngang, phần bên trái trở nên không thể truy cập (hoặc phần bên phải, bằng ngôn ngữ RTL).

Đây là một ví dụ với một container LTR có justify-content: centervà ba mục flex:

nhập mô tả hình ảnh ở đây

Xem phần dưới của câu trả lời này để được giải thích về hành vi này.


Giải pháp số 1

Để khắc phục vấn đề này, hãy sử dụng lề tự động flexbox , thay vì justify-content.

Với autolề, một mục flex tràn có thể được căn giữa theo chiều dọc và chiều ngang mà không mất quyền truy cập vào bất kỳ phần nào của nó.

Vì vậy, thay vì mã này trên container flex:

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

Sử dụng mã này trên mục flex:

.flex-item {
    margin: auto;
}

nhập mô tả hình ảnh ở đây

Bản sửa đổi


Giải pháp số 2 (chưa được triển khai trong hầu hết các trình duyệt)

Thêm safegiá trị cho quy tắc căn chỉnh từ khóa của bạn, như thế này:

justify-content: safe center

hoặc là

align-self: safe center

Từ đặc tả mô-đun sắp xếp hộp CSS :

4.4. Overflow Alignment: các safeunsafecác từ khóa và giới hạn an toàn cuộn

Khi [mục flex] lớn hơn [thùng chứa flex], nó sẽ tràn. Một số chế độ căn chỉnh, nếu được tôn trọng trong tình huống này, có thể gây mất dữ liệu: ví dụ: nếu nội dung của thanh bên được căn giữa, khi tràn, chúng có thể gửi một phần hộp của chúng qua cạnh bắt đầu của khung nhìn, không thể cuộn đến .

Để kiểm soát tình huống này, chế độ căn chỉnh tràn có thể được chỉ định rõ ràng. Unsafecăn chỉnh tôn vinh chế độ căn chỉnh được chỉ định trong các tình huống tràn, ngay cả khi nó gây mất dữ liệu, trong khi safecăn chỉnh sẽ thay đổi chế độ căn chỉnh trong các tình huống tràn để cố gắng tránh mất dữ liệu.

Hành vi mặc định là chứa chủ thể căn chỉnh trong vùng có thể cuộn, mặc dù tại thời điểm viết tính năng an toàn này chưa được triển khai.

safe

Nếu kích thước của [mục flex] tràn vào [thùng chứa flex], thì [mục flex] được căn chỉnh thay vì chế độ căn chỉnh là [ flex-start].

unsafe

Bất kể kích thước tương đối của [mục flex] và [thùng chứa flex], giá trị căn chỉnh đã cho đều được tôn trọng.

Lưu ý: Mô-đun căn chỉnh hộp được sử dụng trên nhiều mô hình bố trí hộp, không chỉ flex. Vì vậy, trong đoạn trích đặc tả ở trên, các thuật ngữ trong ngoặc thực sự nói "chủ đề căn chỉnh", "bộ chứa căn chỉnh" và " start". Tôi đã sử dụng các thuật ngữ cụ thể flex để tập trung vào vấn đề cụ thể này.


Giải thích cho giới hạn cuộn từ MDN:

Xem xét mục Flex

Các thuộc tính căn chỉnh của Flexbox thực hiện định tâm "đúng", không giống như các phương pháp định tâm khác trong CSS. Điều này có nghĩa là các mục flex sẽ giữ ở giữa, ngay cả khi chúng tràn vào hộp chứa flex.

Điều này đôi khi có thể có vấn đề, tuy nhiên, nếu chúng tràn qua cạnh trên của trang hoặc cạnh trái [...], vì bạn không thể cuộn đến khu vực đó, ngay cả khi có nội dung ở đó!

Trong phiên bản tương lai, các thuộc tính căn chỉnh cũng sẽ được mở rộng để có tùy chọn "an toàn".

Hiện tại, nếu đây là một vấn đề đáng lo ngại, thay vào đó, bạn có thể sử dụng lề để đạt được định tâm, vì họ sẽ phản hồi theo cách "an toàn" và ngừng tập trung nếu chúng tràn.

Thay vì sử dụng các align-thuộc tính, chỉ cần đặt autolề trên các mục flex bạn muốn đặt ở giữa.

Thay vì các justify-thuộc tính, đặt lề tự động ở các cạnh bên ngoài của các mục flex đầu tiên và cuối cùng trong thùng chứa flex.

Các autolề sẽ "uốn cong" và giả định không gian còn lại, căn giữa các mục flex khi có không gian còn lại và chuyển sang căn chỉnh bình thường khi không.

Tuy nhiên, nếu bạn đang cố gắng thay thế justify-contentbằng định tâm dựa trên lề trong hộp linh hoạt nhiều dòng, có lẽ bạn không gặp may, vì bạn cần đặt lề trên mục flex đầu tiên và cuối cùng trên mỗi dòng. Trừ khi bạn có thể dự đoán trước các mặt hàng sẽ kết thúc trên dòng nào, bạn không thể sử dụng định tâm dựa trên lề trong trục chính để thay thế thuộc justify-contenttính.


4
Vâng, đó là một giải pháp tốt hơn, và cảm ơn bạn đã cung cấp cái nhìn sâu sắc bổ sung có giá trị.
jejacks0n

1
Cần lưu ý rằng nó không hoạt động trong IE11. Nền sẽ bị cắt.
Daniel

2
@Daniel, tôi vừa kiểm tra mã trong IE11. Không có gì là không thể truy cập. Trong thực tế, vấn đề được mô tả trong câu hỏi thậm chí không tồn tại trong IE11. Bạn có thể đề cập đến lỗi tràn văn bản chỉ xảy ra trong IE11. Đó là một vấn đề khác cho một câu hỏi khác.
Michael Benjamin

11
Để khắc phục sự cố trong IE11: thêm align-items: flex-startvào thùng chứa flex và giữ margin: autocho mục flex.
Eugene Fidelin

2
Điều này không hoạt động đối với tôi khi sử dụng flex-direction: cột;
Stefan

22

Vâng, như Luật của Murphy sẽ có nó, việc đọc tôi đã làm sau khi đăng câu hỏi này dẫn đến một vài kết quả - dù sao cũng không được giải quyết hoàn toàn, nhưng dù sao cũng có ích.

Tôi đã chơi xung quanh với chiều cao tối thiểu một chút trước khi đăng, nhưng không nhận thức được các ràng buộc kích thước nội tại còn khá mới đối với thông số kỹ thuật.

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

Thêm một min-height: min-contentkhu vực flexbox sẽ giải quyết vấn đề trong Chrome và với tiền tố của nhà cung cấp cũng sửa lỗi Opera và Safari, mặc dù Firefox vẫn chưa được giải quyết.

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

Vẫn đang tìm kiếm ý tưởng trên Firefox và các giải pháp tiềm năng khác.


Tôi chỉ muốn nói rằng nó đã hoạt động với tôi trong Firefox. Vì vậy, giải pháp với nội dung tối thiểu là hoàn hảo.
pudgereyem

@pudgereyem Tôi đoán họ đã thực hiện nó rồi. Giải pháp khác với các margin: autođiểm dừng flex-basislàm việc cho tôi trong khi câu trả lời này đã giải quyết cả hai vấn đề.
Martin Dawson

Một giải pháp tuyệt vời thực sự. Tôi không quan tâm đến Edge hay IE, vì vậy điều này hoạt động hoàn hảo với tôi!
Ohgodwhy

18

Tôi quản lý để kéo cái này ra chỉ với 3 container. Mẹo nhỏ là tách hộp chứa flexbox khỏi thùng chứa điều khiển cuộn. Cuối cùng, đặt mọi thứ vào một thùng chứa gốc để tập trung tất cả. Dưới đây là các phong cách thiết yếu để tạo hiệu ứng:

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>

Tôi đã tạo một bản demo ở đây: https://jsfiddle.net/r5jxtgba/14/


thx cho một mẹo cuộn container, tôi đã tìm kiếm từ hai ngày để sửa nội dung cuộn ***** của mình !!!
artSx

nhớ, không cung cấp cho flex: 1 1 autođến scroll-container. Tôi đã làm điều này với thói quen và gặp vấn đề.
AmirHossein

1
Các jsfiddle cho thấy rằng nó không hoạt động khi bạn thêm nhiều nội dung bên trong container.
bplittle

4

Tôi nghĩ rằng tôi đã tìm thấy một giải pháp. Nó hoạt động với rất nhiều văn bảnmột ít văn bản . Bạn không cần chỉ định độ rộng của bất cứ thứ gì và nó sẽ hoạt động trong 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>


Đây là giải pháp tốt nhất cho các trình duyệt cũ. Cảm ơn rât nhiều!
Daniel

5
Wow, đó là rất nhiều kết thúc tốt đẹp.
Nathan Arthur

1
Wow, tôi đã dành hàng giờ cố gắng để đạt được điều này. (Tất cả các phương pháp khác đều thất bại trong chrome di động khi bạn thêm hình động. Điều này không) Cảm ơn rất nhiều!
falsePockets

1

Theo MDN, safegiá trị hiện có thể được cung cấp cho các thuộc tính như align-itemsjustify-content. Nó được mô tả như sau:

Nếu kích thước của mục vượt quá vùng chứa căn chỉnh, thì mục đó được căn chỉnh như thể chế độ căn chỉnh start.

Vì vậy, nó có thể được sử dụng như sau.

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

Tuy nhiên, không rõ nó có bao nhiêu trình duyệt hỗ trợ, tôi không thể tìm thấy bất kỳ ví dụ nào về việc sử dụng nó và tôi đã gặp một số vấn đề với chính nó. Đề cập đến nó ở đây để thu hút sự chú ý nhiều hơn về nó.


Ngày 7 tháng 6 năm 2018 và vẫn chưa được thực hiện trong chrome.
AmirHossein

Theo các trang MDN (hiện tại), "an toàn" và "không an toàn" vẫn chỉ có Firefox tại thời điểm này (tốt, Safari và hầu hết các trình duyệt di động đều không biết hỗ trợ - Tôi sẽ chơi an toàn và không hỗ trợ).
JaMiT

MDN báo cáo hỗ trợ Firefox, nhưng khi tôi thử nghiệm nó trong Firefox, nó dường như không hoạt động. jsbin.com/pimoqof/1/edit?html,css,output
Oliver Joseph Ash

Tháng 6 năm 2020 và không có trong hầu hết các trình duyệt, theo caniuse
den232

0

Tôi cũng quản lý để làm điều đó bằng cách sử dụng thêm container

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

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

thay đổi .content giá trị chiều rộng / chiều cao và xem


0

2 Phương pháp Flex Container với dự phòng Bảng đã thử nghiệm IE8-9, flex hoạt động trong IE10,11. Chỉnh sửa: Đã chỉnh sửa để đảm bảo định tâm dọc khi nội dung tối thiểu, hỗ trợ thêm.

Vấn đề bắt nguồn từ chiều cao được kế thừa từ kích thước khung nhìn khiến trẻ em bị tràn, như Michael trả lời. https://stackoverflow.com/a/33455342/3500688

một cái gì đó đơn giản hơn và sử dụng flex để duy trì bố cục trong thùng chứa cửa sổ bật lên (nội dung):

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.