Vị trí của tôi: phần tử dính không dính khi sử dụng flexbox


106

Tôi đã bị mắc kẹt về điều này một chút và nghĩ rằng tôi sẽ chia sẻ cái này position: sticky+ flexbox gotcha:

Chiếc div dính của tôi hoạt động tốt cho đến khi tôi chuyển chế độ xem của mình sang một hộp đựng flex box, và đột nhiên div không dính khi nó được bọc trong một hộp flexbox cha.

.flexbox-wrapper {
  display: flex;
  height: 600px;
}
.regular {
  background-color: blue;
}
.sticky {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  background-color: red;
}
<div class="flexbox-wrapper">
  <div class="regular">
    This is the regular box
  </div>
  <div class="sticky">
    This is the sticky box
  </div>
</div>

JSFiddle hiển thị sự cố


Hành vi này vẫn tồn tại trên tất cả các trình duyệt hỗ trợ position: stickyhay chỉ một / một số trình duyệt ?
TylerH

1
@TylerH Tôi tin rằng đó là tất cả các trình duyệt. Nó hoạt động như vậy trong cả Chrome và Safari.
BHOLT

Cảm ơn. Tôi có thể xác nhận sự cố và giải pháp cũng xảy ra trong Firefox.
TylerH

Câu trả lời:


205

Vì các phần tử hộp flex được mặc định thành stretch, nên tất cả các phần tử đều có cùng chiều cao, không thể cuộn ngược lại.

Thêm align-self: flex-startvào phần tử cố định đặt chiều cao thành tự động, cho phép cuộn và sửa nó.

Hiện tại, tính năng này được hỗ trợ trong tất cả các trình duyệt chính, nhưng Safari vẫn còn ở phía sau -webkit-tiền tố và các trình duyệt khác ngoại trừ Firefox có một số vấn đề với position: stickybảng.

.flexbox-wrapper {
  display: flex;
  overflow: auto;
  height: 200px;          /* Not necessary -- for example only */
}
.regular {
  background-color: blue; /* Not necessary -- for example only */
  height: 600px;          /* Not necessary -- for example only */
}
.sticky {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
  align-self: flex-start; /* <-- this is the fix */
  background-color: red;  /* Not necessary -- for example only */
}
<div class="flexbox-wrapper">
  <div class="regular">
    This is the regular box
  </div>
  <div class="sticky">
    This is the sticky box
  </div>
</div>

JSFiddle hiển thị giải pháp


26
điều này chỉ hoạt động khi cuộn bên trong phần tử flex chứa - khi cuộn toàn bộ cửa sổ, nó KHÔNG dính (ít nhất là trong Firefox) - vì vậy đối với những người đang có hành vi mâu thuẫn, có nhiều khả năng bạn đang gặp phải những kỳ vọng trái ngược nhau (như tôi đã)
aequalsb

@aequalsb Bạn có biết cách làm cho nó dính khi cuộn toàn bộ trang không?
Douglas Gaskell

@Douglas câu hỏi gây hiểu lầm vì nó gợi ý rằng vấn đề là với flexboxnhưng vấn đề liên quan nhiều hơn đến việc chứa stickyphần tử. nhìn vào fiddle này: jsfiddle.net/9y87zL5c trong đó hộp màu đỏ THỨ HAI hoạt động như mong đợi nhưng hộp màu đỏ ĐẦU TIÊN không dính - vì vậy ... điều này không liên quan đến flexbox (do đó mâu thuẫn với kỳ vọng) ... CŨNG ... tôi đã thêm một loạt jabberwocky để xem kết quả một cách chính xác hơn.
aequalsb

27

Trong trường hợp của tôi, một trong các vùng chứa mẹ đã overflow-x: hidden;áp dụng cho nó, điều này sẽ phá vỡ position: stickychức năng. Bạn sẽ cần xóa quy tắc đó.

Không có phần tử mẹ nào phải áp dụng quy tắc CSS ở trên. Điều kiện này áp dụng cho tất cả các bậc cha mẹ cho đến (nhưng không bao gồm) phần tử 'body'.


Bạn cũng không thể có overflow-x:hiddentrên phần tử html.
Samuel Liew

Cảm ơn rất nhiều. TÔI LUÔN đấu tranh với vị trí dính và tôi không biết về tình trạng này cho đến khi đọc câu trả lời của bạn. :)
Raphael Aleixo

@SamuelLiew, có, bạn có thể có overflow-x: hidden;trên phần tử HTML.
TheoPlatica

@RaphaelAleixo Tôi rất vui vì tôi có thể giúp được :)
TheoPlatica

Đây là những gì đã ngăn tôi không có nếp hoạt động chính xác. Cảm ơn rất nhiều!
MoOx

7

Bạn cũng có thể thử thêm một div con vào mục flex có nội dung bên trong và gán position: sticky; top: 0;cho nó.

Điều đó phù hợp với tôi đối với bố cục hai cột trong đó nội dung của cột đầu tiên cần phải cố định và cột thứ hai có thể cuộn được.


Hoàn toàn đồng ý, đây là lựa chọn đơn giản và đáng tin cậy nhất mà tôi có thể tìm thấy. Bằng cách này, bạn cũng sẽ có thể kiểm soát thời điểm dừng dính bằng cách kiểm soát chiều cao của thùng chứa.
Ibrahim ben Salah

0

Tôi đã tạo một bảng flexbox tạm thời và gặp sự cố này. Để giải quyết nó, tôi chỉ cần đặt hàng tiêu đề dính bên ngoài flexbox, ngay trước nó.


0

Đối với tình huống của tôi, giải pháp align-self: flex-start(hoặc justify-self: flex-start) không hoạt động. Tôi cũng cần giữ lại overflow-x: hiddenvì một số vùng chứa vuốt theo chiều ngang.

Giải pháp của tôi yêu cầu được lồng display: flexvới overflow-y: autođể có được các hành vi mong muốn:

  • tiêu đề có thể tự động điều chỉnh độ cao, điều này ngăn chặn việc chơi với position: absolutehoặcposition: fixed
  • nội dung cuộn theo chiều dọc, giới hạn theo chiều ngang đối với chiều rộng của chế độ xem
  • phần tử dính có thể ở bất kỳ đâu theo chiều dọc, dính vào cuối tiêu đề
  • các phần tử khác có thể trượt ngang
    • có vẻ như công cụ đoạn mã SO không thể hiển thị widthtrên các phần tử con để thể hiện trang chiếu ngang một cách chính xác hoặc có thể có một số cài đặt khác trên bố cục thực tế của tôi khiến nó hoạt động ...
    • lưu ý rằng một phần tử trình bao bọc không làm gì khác được yêu cầu để cho phép overflow-x: autohoạt động chính xác trong các phần tử dưới phần tử cha vớioverflow-x: hidden

body {
  height: 100vh;
  width: 100vw;
  display: flex;
  flex-direction: column;
}

body>header {
  background-color: red;
  color: white;
  padding: 1em;
}

.content {
  overflow-x: hidden;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

article {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.horizontal_slide {
  display: flex;
  overflow-x: auto;
  background-color: lightblue;
  padding: .5em;
}

.horizontal_slide>* {
  width: 1000px;
}

.toolbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background-color: lightgray;
  padding: .5em;
  display: flex;
}
<header>Fancy header with height adjusting to variable content</header>
<div class="content">
  <article class="card">
    <h1>One of several cards that flips visibility</h1>
    <div class="overflow_x_wrapper">
      <div class="horizontal_slide">
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
      </div>
      <div class="toolbar">Sticky toolbar part-way down the content</div>
      <p>Rest of vertically scrollable container with variable number of child containers and other elements</p>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </article>
  </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.