it-roy-ru.com

Невозможно прокрутить к вершине гибкого элемента, который переполнен контейнер

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

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

155
jejacks0n

Эта проблема

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

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

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

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

enter image description here

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

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

enter image description here

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


Решение № 1

Чтобы решить эту проблему, используйте flexbox auto margins вместо justify-content.

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

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

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

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

.flex-item {
    margin: auto;
}

enter image description here

Revised Demo


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

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

justify-content: safe center

или же

align-self: safe center

Из спецификация CSS Box Alignment Module :

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

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

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

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

safe

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

unsafe

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

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


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

Flex item Соображения

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

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

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

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

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

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

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

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

291
Michael_B

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

Я немного поиграл с 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 и другие потенциальные решения.

18
jejacks0n

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

12
colinbr96

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

4
mpen

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

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

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

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

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

1
Chris Talman

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

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/

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

0
Nadeesh Peiris

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

Как объясняет Майкл, проблема заключается в том, что высота наследуется от размера области просмотра, что приводит к переполнению дочерних элементов. https://stackoverflow.com/a/33455342/3500688

что-то более простое и используйте 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'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>
    <p class="p3">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>
        <!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>
0
Silverandrew