Не удается прокрутить элемент flex, переполненный контейнером

Итак, пытаясь сделать полезный модальный с помощью flexbox, я нашел то, что кажется проблемой браузера, и мне интересно, есть ли известное исправление или обходной путь-или идеи о том, как его решить.

то, что я пытаюсь решить, имеет два аспекта. Во-первых, получение модального окна по вертикали, которое работает так, как ожидалось. Во-вторых, чтобы получить модальное окно для прокрутки-внешне, так что все модальное окно прокручивается, а не содержимое внутри него (это так, вы можете иметь выпадающие списки и другие элементы пользовательского интерфейса, которые могут выходить за пределы модального-например, пользовательский выбор даты и т. д.)

однако при объединении вертикального центрирования с полосами прокрутки верхняя часть модального может стать недоступной, поскольку она начинает переполняться. В приведенном выше примере, вы можете изменить силу переполнения, и это позволяет в нижней части модального, но не до самого верха (первый абзац отрезать).

вот ссылка на пример код (сильно упрощенный)

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
}

это эффекты (текущие) Firefox, Safari, Chrome и Opera.. Интересно, что он ведет себя правильно в IE10, если вы комментируете в css с префиксом IE10-я еще не беспокоился о тестировании в IE11, но предполагаю, что поведение соответствует поведению IE10.

любые идеи были бы хороши. Ссылки на известные проблемы или рассуждения об этом поведении также были бы полезны.

6 ответов


Проблема

Flexbox делает центризовать очень легким.

прос align-items: center и justify-content: center к контейнеру гибкого трубопровода, ваши деталь(ы) гибкого трубопровода будут вертикально и горизонтально центризованы.

однако существует проблема с этим методом, когда элемент flex больше, чем контейнер flex.

как отмечено в вопросе, когда элемент flex переполняет контейнер, верхняя часть становится недоступный.

enter image description here

для горизонтального переполнения левая секция становится недоступной (или правая секция на языках RTL).

вот пример с контейнером LTR, имеющим justify-content: center и три элемента flex:

enter image description here

см. нижнюю часть этого ответа для объяснения этого поведения.


Решение № 1

исправить эта проблема использовать автоматические поля flexbox, вместо justify-content.

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

поэтому вместо этого кода на контейнере flex:

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

используйте этот код на элементе flex:

.flex-item {
    margin: auto;
}

enter image description here

пересмотрен Демо


решение #2 (еще не реализовано в большинстве браузеров)

добавить safe значение для вашего правила выравнивания ключевых слов, например:

justify-content: safe center

или

align-self: safe center

С спецификация модуля выравнивания CSS Box:

4.4. Выравнивание переполнения:safe и unsafe ключевые слова и безопасность прокрутки пределы

когда [гибкий элемент] больше, чем [гибкий контейнер], он будет переполнение. Некоторые режимы выравнивания, если соблюдаются в этой ситуации, могут причина потери данных: например, если содержимое боковой панели по центру, когда они переполняются, они могут отправить часть своих ящиков мимо начальный край окна просмотра, к которому невозможно прокрутить.

чтобы контролировать эту ситуацию, an переполнение выравнивания режим может быть явно указать. Unsafe выравнивание чтит указанное режим выравнивания в ситуациях переполнения, даже если это приводит к потере данных, в то время как safe выравнивание изменяет режим выравнивания в переполнении ситуации в попытке избежать потери данных.

по умолчанию содержит согласование предмета в области прокрутки, хотя на момент написания этой функции безопасности еще не реализовано.

safe

если размер [элемент flex] переполняет [контейнер flex], [flex item] вместо этого выравнивается, как если бы режим выравнивания был [flex-start].

unsafe

независимо от относительных размеров элемента [flex] и [flex container], данное значение выравнивания выполняется.

Примечание: модуль выравнивания коробки предназначен для использования в нескольких моделях компоновки коробки, а не только flex. Так в спецификации выдержка выше, термины в скобках фактически говорят "объект выравнивания"," контейнер выравнивания "и"start". Я использовал гибкие термины, чтобы сосредоточиться на этой конкретной проблеме.


объяснение ограничения прокрутки из MDN:

элемент гибкий соображения

свойства выравнивания Flexbox делают" истинный " центрировать, не похож на другое методы центрирования в CSS. Это означает, что элементы flex будут оставаться центрированные, даже если они переполняют контейнер flex.

иногда это может быть проблематично, однако, если они переполняются мимо верхний край страницы или левый край [...], как вы не можете прокручивать эту область, даже если там есть контент!

в будущем выпуске свойства выравнивания будут расширены, чтобы иметь "безопасный" вариант.

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

вместо align- свойства, просто поставить auto наценки на гибкие элементы, которые вы хотите центр.

вместо justify- свойства, ставим автополя снаружи края первого и последнего элементов контейнера в контейнер.

на auto поля будут "сгибаться" и предполагать оставшееся пространство, центрирование элементов flex, когда есть остатки пространство и переключение к нормальному выравниванию, когда нет.

однако, если вы пытаетесь заменить justify-content С маржинальное центрирование в многострочном flexbox, вы, вероятно, из удачи, так как вам нужно поместить поля на первый и последний элемент flex в каждой строке. Если вы не можете заранее предсказать, какие элементы будут в конце концов, на какой линии вы не можете надежно использовать маржинальное центрирование основная ось для замены justify-content собственность.


Я немного поиграл с min-height перед публикацией, но не знал о внутренних ограничениях размера, которые довольно новы для спецификации.

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

добавлять min-height: min-content к области flexbox разрешает проблему в Chrome и с префиксами поставщиков также исправляет Opera и Safari, хотя Firefox остается нерешенным.

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

все еще ищет идеи по Firefox и другие потенциальные решения.


мне удалось вытащить это всего за 3 контейнера. Трюк состоит в том, чтобы отделить контейнер flexbox от контейнера, который управляет прокруткой. Наконец, поместите все в корневой контейнер, чтобы центрировать все это. Вот основные стили для создания эффекта:

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>

Я создал демо здесь:https://jsfiddle.net/r5jxtgba/14/


Я думаю, что нашел решение. Он работает с много текста и маленький текст. Вам не нужно указывать ширину и должны работа в 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>

согласно MDN,safe значение теперь может быть предоставлено таким свойствам, как align-items и justify-content. Это описывается следующим образом:

если размер элемента переполняет контейнер выравнивания, элемент выравнивается, как если бы режим выравнивания был start.

таким образом, он может использоваться следующим образом.

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

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


мне также удалось сделать это, используя дополнительный контейнер

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

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

изменить .содержание значения ширины / высоты и см.