Невозможно прокрутить к вершине гибкого элемента, который переполнен контейнер
Итак, пытаясь создать полезный мод с использованием 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,
Любые идеи были бы хорошими. Ссылки на известные проблемы или причины такого поведения также могут быть полезны.
15 ответов
Эта проблема
Flexbox делает центрирование очень простым.
Просто применяя align-items: center
а также justify-content: center
к гибкому контейнеру ваши гибкие элементы будут центрированы по вертикали и горизонтали.
Тем не менее, существует проблема с этим методом, когда гибкий элемент больше, чем гибкий контейнер.
Как отмечено в вопросе, когда гибкий элемент переполняет контейнер, верх становится недоступным.
При горизонтальном переполнении левая часть становится недоступной (или правая часть на языках 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 Alignment Module:
4.4. Выравнивание переполнения:
safe
а такжеunsafe
ключевые слова и пределы безопасности прокруткиКогда [flex item] больше, чем [flex container], он будет переполнен. Некоторые режимы выравнивания, если их соблюдать в этой ситуации, могут привести к потере данных: например, если содержимое боковой панели центрировано, при переполнении они могут отправить часть своих полей за начальный край окна просмотра, который нельзя прокрутить до,
Для управления этой ситуацией можно явно указать режим выравнивания переполнения.
Unsafe
выравнивание учитывает указанный режим выравнивания в ситуациях переполнения, даже если это приводит к потере данных, в то время какsafe
выравнивание изменяет режим выравнивания в ситуациях переполнения, чтобы избежать потери данных.Поведение по умолчанию должно содержать объект выравнивания в прокручиваемой области, хотя на момент написания этой функции безопасности еще не реализовано.
safe
Если размер [flex item] выходит за пределы [flex container], вместо этого [flex item] выравнивается, как если бы режим выравнивания был [
flex-start
].
unsafe
Независимо от относительных размеров [flex item] и [flex container], данное значение выравнивания учитывается.
Примечание. Модуль выравнивания ящиков предназначен для использования в разных моделях ящиков, а не только в гибких. Таким образом, в приведенном выше отрывке спецификации термины в скобках на самом деле говорят "объект выравнивания", "контейнер выравнивания" и " start
". Я использовал специфичные для flex термины, чтобы сосредоточиться на этой конкретной проблеме.
Объяснение ограничения прокрутки от MDN:
Свойства выравнивания Flexbox выполняют "истинное" центрирование, в отличие от других методов центрирования в CSS. Это означает, что гибкие элементы будут оставаться в центре, даже если они переполняют гибкий контейнер.
Однако иногда это может быть проблематично, если они переполняют верхний край страницы или левый край [...], поскольку вы не можете прокрутить до этой области, даже если там есть контент!
В будущем выпуске свойства выравнивания будут расширены, чтобы также иметь "безопасный" параметр.
На данный момент, если это проблема, вы можете вместо этого использовать поля для достижения центрирования, так как они будут отвечать "безопасным" способом и прекратят центрирование, если они переполнятся.
Вместо использования
align-
свойства, просто положитьauto
поля на гибкие элементы, которые вы хотите центрировать.Вместо
justify-
свойства, поместите авто поля на внешние края первого и последнего flex-элементов в flex-контейнере.
auto
поля будут "сгибаться" и принимать оставшееся пространство, центрируя элементы сгибания, когда есть оставшееся пространство, и переключаться на нормальное выравнивание, когда его нет.Однако, если вы пытаетесь заменить
justify-content
с центрированием на основе полей в многострочном флексбоксе вам, вероятно, не повезло, так как вам нужно поставить поля на первом и последнем флекс-элементе в каждой строке. Если вы не можете заранее предсказать, какие элементы окажутся на какой линии, вы не сможете надежно использовать центрирование на основе маржи по главной оси для заменыjustify-content
имущество.
Мне удалось осуществить это всего с 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/
Что ж, как гласит Закон Мерфи, чтение, которое я сделал после публикации этого вопроса, привело к нескольким результатам - не полностью разрешенным, но, тем не менее, несколько полезным.
Я немного поиграл с min-height перед публикацией, но не знал о внутренних ограничениях размеров, которые являются довольно новыми для спецификации.
Добавление 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 и другие потенциальные решения.
Я думаю, что нашел решение. Это работает с большим количеством текста и небольшим количеством текста. Вам не нужно указывать ширину чего-либо, и это должно работать в 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>
Попробуй это!
<div class="flex-container">
<div class="item">First item</div>
<div class="item">Second item</div>
<div class="item">Third item</div>
</div>
.flex-container {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
overflow-x: auto;
.item:first-child {
margin-left: auto;
}
.item:last-child {
margin-right: auto;
}
}
Вам, вероятно, следует использовать
Если codepen не работает
<div class="wrapper">
<div class="modal"></div>
</div>
<style>
.wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
overflow-y: auto;
text-align: center;
}
/* Required for centering */
.wrapper:before {
content: '';
height: 100%;
width: 0;
vertical-align: middle;
display: inline-block;
}
.modal {
/* Required for centering */
display: inline-block;
vertical-align: middle;
text-align: left;
width: 320px;
height: 320px;
background-color: #fff;
border-radius: 25px;
}
</style>
Он работает путем создания встроенного элемента, который равен полной высоте родительского элемента и отображается как встроенный блок, как и ваш целевой элемент (.modal), затем
Вы можете использовать
На момент написания (15.09.2021) при переходе в Google в режиме инкогнито отображается модальная политика файлов cookie, в которой используется этот метод для центрирования.
Согласно 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/
изменить значения .content ширина / высота и посмотреть
2 Контейнер Flex Метод с таблицей нейтрализация испытания IE8-9, гибкие работы в IE10,11. Редактировать: отредактировано для обеспечения вертикального центрирования при минимальном содержании, добавлена устаревшая поддержка.
Как объясняет Майкл, проблема заключается в том, что высота наследуется от размера области просмотра, что приводит к переполнению дочерних элементов. /questions/8157228/nevozmozhno-prokrutit-k-vershine-gibkogo-elementa-kotoryij-perepolnen-kontejner/8157229#8157229
что-то более простое и используйте 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>
Удаление
align-items: center;
,
justify-content: center;
на родителя (сохранить
display: flex;
) и добавление
margin: auto;
на дочернем элементе решает проблему вертикального выравнивания.
Заменять
.parent {
display: flex;
align-items: center;
justify-content: center;
}
с
.parent {
display: flex;
}
.child {
margin: auto;
}
Возможно, вам придется определить
height
а также
width
css для дочернего элемента в зависимости от его содержимого.
https://codepen.io/sanathsharma-the-vuer/pen/dyJeXVG — ссылка на codepen, демонстрирующая то же самое.
Я решил это с помощью
{
display: flex;
justify-content: center;
align-items: center;
min-height: 100%; // expand height if not overflow
min-width: 100%; // expand width if not overflow
}
У меня была похожая проблема с этой. В итоге я решил это, установив
justify-content
к . Не очень хороший вариант, но он работает, когда контейнер переполняется гибким дисплеем.
Вы можете использовать медиа-запрос или JavaScript, чтобы добавить к нему условия, чтобы, если он ожидает переполнения, он переключался на
space-between
.
Надеюсь, это кому-то поможет.
Вместоjustify-content: center
, добавить дваdiv
сflex: 1
как первый и последний дочерний элемент вашего гибкого контейнера.