Моє положення: липкий елемент не є липким при використанні flexbox


106

Я трохи затримався на цьому і думав поділитися цим position: sticky+ flexbox gotcha:

Мій липкий div працював нормально, поки я не переключив свій погляд на контейнер flex box, і раптом div не став липким, коли його загорнули у батьківський файл flexbox.

.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, що показує проблему


Чи зберігається така поведінка у всіх браузерах, які підтримують, position: stickyабо лише в одному / деяких?
TylerH

1
@TylerH Я вважаю, що це все браузери. Це функціонувало як у Chrome, так і в Safari.
BHOLT

Дякую. Я також можу підтвердити, що проблема та рішення вирішуються у Firefox.
TylerH

Відповіді:


205

Оскільки елементи flex box за замовчуванням мають значення stretch, усі елементи мають однакову висоту, до яких неможливо прокрутити.

Додавши align-self: flex-startдо липкого елемента, встановіть висоту на авто, що дозволило прокрутку, та зафіксуйте її.

На даний момент це підтримується у всіх основних браузерах, але Safari все ще не має -webkit-префікса, а інші браузери, крім Firefox, мають деякі проблеми з position: stickyтаблицями.

.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, що показує рішення


26
це працює лише під час прокрутки всередині вміщуючого елемента flex - при прокрутці всього вікна воно НЕ прилипає (принаймні у Firefox) - тому для тих, хто зазнає суперечливої ​​поведінки, швидше за все, ви відчуваєте суперечливі очікування (як i was)
aequalsb

@aequalsb Чи знаєте ви спосіб закріпити його при прокручуванні цілої сторінки?
Дуглас Гаскелл,

@Douglas питання вводить в оману, оскільки вказує на те, що проблема полягає, flexboxале проблема має більше спільного із вмістом stickyелемента. подивіться на цю скрипку: jsfiddle.net/9y87zL5c, де ДРУГИЙ червоний ящик працює, як очікувалося, але ПЕРШИЙ червоний ящик не тримається - отже ... це не пов’язано з flexbox (таким чином, суперечливі очікування) ... ТАКОЖ ... i додав купу jabberwocky, щоб побачити результати більш точно.
aequalsb

27

У моєму випадку до нього overflow-x: hidden;звернувся один із батьківських контейнерів , що порушить position: stickyфункціональність. Вам потрібно буде видалити це правило.

Жоден батьківський елемент не повинен застосовувати вищезазначене правило CSS до нього. Ця умова стосується всіх батьків до (але не включаючи) елемента "тіло".


Ви також не можете мати overflow-x:hiddenелемент html.
Семюель Лів

Дуже дякую. Я ЗАВЖДИ борюся з непомітною позицією, і я не знав про цей стан, поки не прочитав вашу відповідь. :)
Рафаель Алейшо

@SamuelLiew, так, ви можете мати overflow-x: hidden;елемент HTML.
TheoPlatica

@RaphaelAleixo Я радий, що міг допомогти :)
TheoPlatica

Це те, що заважало мені правильно працювати липкою. Дуже дякую!
MoOx

7

Ви також можете спробувати додати дочірній div до елемента flex із вмістом всередині та призначити position: sticky; top: 0;цьому.

Це працювало для мене для макета з двома стовпцями, де вміст першого стовпця повинен бути липким, а другий стовпець здавався прокручуваним.


Повністю згоден, це найпростіший і надійний варіант, який я міг знайти. Таким чином, ви також зможете контролювати, коли припиняти прилипання, контролюючи висоту контейнера.
Ібрагім бен Салах

0

Я створив імпровізований флексбокс-стіл і мав цю проблему. Щоб його вирішити, я просто розмістив липкий рядок заголовка поза флексбокса, безпосередньо перед ним.


0

У моїй ситуації align-self: flex-start(або justify-self: flex-start) рішення не працює. Мені також потрібно триматися overflow-x: hidden, оскільки деякі контейнери гортають горизонтально.

Моє рішення вимагало вкладеного display: flexз , overflow-y: autoщоб отримати бажане поведінку:

  • Заголовок може динамічно регулювати висоту, що перешкоджає грі з position: absoluteабоposition: fixed
  • вміст прокручується вертикально, обмежений горизонтально до ширини подання
  • липкий елемент може бути де завгодно вертикально, прилипаючи до нижньої частини заголовка
  • інші елементи можуть ковзати горизонтально
    • схоже на те, що інструмент фрагмента SO не може відображати widthна дочірніх елементах належним чином, щоб продемонструвати горизонтальний слайд, або, можливо, у моєму фактичному макеті є якесь інше налаштування, яке змушує його працювати ...
    • зауважте, що елемент обгортки, який нічого іншого не робить, необхідний для overflow-x: autoкоректної роботи в елементах батьківського зoverflow-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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.