Моя позиция: липкий элемент не липкий при использовании flexbox


107

Я немного position: stickyзациклился на этом и подумал, что поделюсь вот этим + flexbox gotcha:

Мой липкий div работал нормально, пока я не переключил свое представление на контейнер flexbox, и внезапно 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

Поскольку элементы гибкого блока по умолчанию 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
это работает только при прокрутке внутри содержащего гибкого элемента - при прокрутке всего окна оно НЕ прилипает (по крайней мере, в Firefox) - поэтому для тех, кто испытывает противоречивое поведение, более вероятно, что вы испытываете противоречивые ожидания (например, я was)
aequalsb

@aequalsb Знаете ли вы, как заставить его придерживаться при прокрутке всей страницы?
Дуглас Гаскелл

@Douglas, вопрос вводит в заблуждение, потому что он предполагает, что проблема заключается в flexboxтом, что проблема больше связана с содержанием stickyэлемента. посмотрите на эту скрипку: jsfiddle.net/9y87zL5c, где ВТОРОЕ красное поле работает, как ожидалось, но ПЕРВОЕ красное поле не прилипает - так что ... это не связано с flexbox (таким образом, противоречивые ожидания) ... ТАКЖЕ ... i добавил кучу треп, чтобы более точно видеть результаты.
aequalsb

28

В моем случае overflow-x: hidden;к нему применился один из родительских контейнеров , что нарушит position: stickyфункциональность. Вам нужно удалить это правило.

Ни к одному родительскому элементу не должно применяться указанное выше правило CSS. Это условие применяется ко всем родителям до (но не включая) элемента body.


Вы также не можете overflow-x:hiddenиспользовать элемент html.
Сэмюэл Лью

Большое спасибо. Я ВСЕГДА борюсь с закреплением позиции, и я не знал об этом условии, пока не прочитал ваш ответ. :)
Рафаэль Алейшо

@SamuelLiew, да, вы можете overflow-x: hidden;использовать элемент HTML.
TheoPlatica

@RaphaelAleixo Я рад, что смог помочь :)
TheoPlatica

Это то, что мешало мне правильно работать с липкой лентой. Большое спасибо!
MoOx,

7

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

Это сработало для меня для макета с двумя столбцами, где содержимое первого столбца должно быть липким, а второй столбец прокручивается.


Полностью согласен, это самый простой и надежный вариант, который я мог найти. Таким образом, вы также сможете контролировать, когда прекратить прилипание, контролируя высоту контейнера.
Ибрагим бен Салах,

0

Я сделал самодельную таблицу flexbox и столкнулся с этой проблемой. Чтобы решить эту проблему, я просто помещаю липкую строку заголовка за пределы флексбокса непосредственно перед ней.


0

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

Мое решение требовало вложенного display: flexс , overflow-y: autoчтобы получить желаемое поведение:

  • заголовок может динамически регулировать высоту, что предотвращает игру с position: absoluteилиposition: fixed
  • контент прокручивается по вертикали, ограничиваясь по горизонтали шириной просмотра
  • липкий элемент может быть где угодно по вертикали, прилипая к нижней части заголовка
  • другие элементы могут скользить горизонтально
    • похоже, что инструмент SO snippet не может отображать 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.