У меня есть макет на основе flexbox с двумя панелями (верхняя и нижняя), занимающие 1/3 и 2/3 области просмотра соответственно. (На самом деле панелей больше, но я сократил это до минимального примера).

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

Проблема: содержимое top сжимается до своего размера даже с flex-shrink: 0, и полоса прокрутки никогда не появляется.

Обратите внимание на то, как content уменьшается в следующей демонстрации, даже если у него явно указана высота:

html, body {
    height: 100%;
    width: 100%;
    margin: 0;
    padding: 0;
    overflow: hidden;
}

.main {
    display: flex;
    height: 100%;
    flex-direction: column;
}

.top {
    display: flex;
    flex-direction: column;
    flex-basis: 33%;
    border-bottom: 1px solid #ccc;
    overflow: auto;
    justify-content: center;
    padding: 20px;
}

.bottom {
    overflow: auto;
    flex-basis: 67%;
}

.content {
    height: 500px;
    background-color: #eee;
}
<div class="main">
  <div class="top">
    <div class="content">Content</div>
  </div>
  <div class="bottom"></div>
</div>

Вопросы:

  1. Как исправить это, сохранив требования к макету? Отключение display: flex для верхней панели дает желаемый эффект в демонстрации. Я мог позиционировать содержимое top без гибкого бокса, но теряю преимущества гибкого макета и автоматического вертикального центрирования.

  2. Почему это происходит? Приветствуются ссылки на спецификации CSS.

1
Daniel Janus 3 Янв 2018 в 14:00

2 ответа

Лучший ответ

Вы написали:

Проблема: содержимое top сжимается до своего размера даже с flex-shrink: 0, и полоса прокрутки никогда не появляется.

На самом деле решение - flex-shrink: 0. Возникает вопрос, где вы это применили?

Это не сработает, если вы примените его к top - гибкому элементу в основном контейнере с flex-basis: 33% (то есть height: 33% в данном случае) - потому что длина {{X3 }} - это процент. Таким образом, он будет сжиматься / расширяться естественным образом, если длина в процентах относительно родительского контейнера.

Вам нужно применить flex-shrink: 0 к .content - гибкому элементу во вложенном контейнере с фиксированной высотой (height: 500px / flex-basis: 500px).

Итак, это будет работать:

.content {
    height: 500px;
    flex-shrink: 0;
}

Или это:

.content {
    flex-basis: 500px;
    flex-shrink: 0;
}

Или, еще лучше, это:

.content {
    flex: 0 0 500px;  /* don't grow, don't shrink, stay fixed at 500px */
}

Из спецификации:

< Сильный >7,2 . Компоненты Гибкость

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

body {
  margin: 0;
}

.main {
  display: flex;
  flex-direction: column;
  height: 100vh;  
}

.top {
  display: flex;
  flex-direction: column;
  flex-basis: 33%;
  border-bottom: 1px solid #ccc;
  overflow: auto;
  justify-content: center;
  padding: 20px;
}

.bottom {
  overflow: auto;
  flex-basis: 67%;
}

.content {
  flex: 0 0 500px;
  background-color: #eee;
}
<div class="main">
  <div class="top">
    <div class="content">Content</div>
  </div>
  <div class="bottom"></div>
</div>

Затем возникает вторая проблема , заключающаяся в том, что верхняя часть элемента top обрезается и становится недоступной для прокрутки. Это вызвано justify-content: center на контейнере.

Это известная проблема. Это решается за счет использования гибких полей auto.

Итак, вместо этого:

.top {
    display: flex;
    flex-direction: column;
    flex-basis: 33%;
    border-bottom: 1px solid #ccc;
    overflow: auto;
    /* justify-content: center;  <--- REMOVE */
    padding: 20px;
}

Сделай это:

.content {
  flex: 0 0 500px;
  margin: auto 0; /*  top & bottom auto margins */
  background-color: #eee;
}
body {
  margin: 0;
}

.main {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.top {
  display: flex;
  flex-direction: column;
  flex-basis: 33%;
  border-bottom: 1px solid #ccc;
  overflow: auto; 
  /* justify-content: center;  USE AUTO MARGINS ON FLEX ITEM INSTEAD */
  padding: 20px;
}

.bottom {
  overflow: auto;
  flex-basis: 67%;
}

.content {
  flex: 0 0 500px;
  margin: auto 0;
  background-color: #eee;
}
<div class="main">
  <div class="top">
    <div class="content">Content</div>
  </div>
  <div class="bottom"></div>
</div>

Вот полное объяснение:

1
Michael Benjamin 3 Янв 2018 в 16:42

Полоса прокрутки появляется, когда достаточно элементов .content, сжатых до минимальной высоты (в данном случае - одна высота строки).

На самом деле с flex все работает не так. height строго не соблюдается. Если вы все еще хотите работать с height, вы можете исправить это, установив для min-height значение .content в соответствии с минимальной высотой, которую вы хотите для них.

Или вы можете вместо этого установить flex на .content (и избавиться от height): css flex: 100 пикселей 1 0; Что установит минимальную высоту (flex-base) на 100 пикселей, flex-grow на 1, чтобы он занимал все доступное пространство, и flex-shrink на 0, чтобы элемент всегда был не менее 100 пикселей в высоту.

0
kLabz 3 Янв 2018 в 11:24