Нельзя прокручивать верхнюю часть гибкого элемента, который переполняет контейнер

Итак, пытаясь сделать полезный модальный с помощью 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, если вы прокомментируете в IE10 vender префикс css - я еще не тестировал тестирование в IE11, но предполагаю, что поведение соответствует IE10.

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

Ответ 1

Проблема

Flexbox делает центрирование очень простым.

Просто применяя align-items: center и justify-content: center к контейнеру flex, ваш элемент flex будет располагаться по вертикали и по горизонтали.

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

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

введите описание изображения здесь

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

Здесь пример с контейнером LTR с justify-content: center и тремя элементами гибкости:

введите описание изображения здесь

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


Решение № 1

Чтобы устранить эту проблему, используйте Flexbox автоматические поля вместо justify-content.

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

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

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

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

.flex-item {
    margin: auto;
}

введите описание изображения здесь

Пересмотренная демонстрация


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

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

justify-content: safe center

или

align-self: safe center

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

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

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

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

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

safe

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

unsafe

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

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


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

Элемент Flex соображения

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

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

В следующей версии свойства выравнивания будут расширены, чтобы "безопасный" вариант.

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

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

Вместо свойств justify- поместите автоматические поля на внешней стороне края первого и последнего элементов гибкости в контейнере гибких дисков.

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

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

Ответ 2

Хорошо, как это сделал бы закон Мерфи, чтение, которое я прочитал после публикации этого вопроса, привело к нескольким результатам - не полностью разрешенному, но, тем не менее, полезному.

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

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

Мне удалось осуществить это всего за 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/

Ответ 4

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

Ответ 5

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

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

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

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

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

Ответ 6

Мне также удалось сделать это с помощью дополнительного контейнера

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

измените значения .content ширина/высота и посмотрите

Ответ 7

2 Контейнер Flex Метод с таблицей нейтрализация испытания IE8-9, гибкие работы в IE10,11. Редактировать: отредактировано для обеспечения вертикального центрирования при минимальном содержании, добавлена устаревшая поддержка.

Как объясняет Майкл, проблема заключается в том, что высота наследуется от размера области просмотра, что приводит к переполнению дочерних элементов. fooobar.com/info/5641/...

что-то более простое и используйте flex для поддержки макета во всплывающем контейнере (контент):

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