Хранение контейнера flexbox и переполнение детей в пределах 100% высоты - PullRequest
3 голосов
/ 30 марта 2019

У меня есть контейнер flexbox с 3 секциями. Идея состоит в том, что каждый раздел будет похож на аккордеон и расширяется, но при любом расширении мне нужно, чтобы содержимое разделов переполнялось по вертикали только в том случае, если оно переместит весь контейнер выше 100% высоты родителя, сохраняя при этом 100 % от высоты контейнера контейнера flexbox.

Вот фрагмент того, что я пробовал с процентной высотой.

html, body {
  height: 100%;
  margin: 0;
}

#container {
  width: 100%;
  height: 100%;
  background-color: gray;
  display: flex;
  flex-direction: column;
}

#a {
  flex: 0 1 auto;
}

#b {
  flex: 2 1 auto;
}

#c {
  flex: 0 1 auto;
}

#s2 {
  max-height: 100%;
  overflow: auto;
  background-color: lightblue;
}
<div id="container">
    <div id="a"><div>Section 1</div></div>
    <div id="b">
      <div>Section 2</div>
      <div id="s2">
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
      </div>
    </div>
    <div id="c"><div>Section 3</div></div>
</div>

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

html, body {
  height: 100%;
  margin: 0;
}

#container {
  width: 100%;
  height: 100%;
  background-color: gray;
  display: flex;
  flex-direction: column;
}

#a {
  flex: 0 1 auto;
}

#b {
  flex: 2 1 auto;
}

#c {
  flex: 0 1 auto;
}

#s2 {
  max-height: 300px;
  overflow: auto;
  background-color: lightblue;
}
<div id="container">
    <div id="a"><div>Section 1</div></div>
    <div id="b">
      <div>Section 2</div>
      <div id="s2">
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
      </div>
    </div>
    <div id="c"><div>Section 3</div></div>
</div>

Обратите внимание, что Раздел 3 устраняет слабину, оставшуюся от предполагаемой гибкой основы Раздела 2. Я хочу, чтобы Раздел 2 вырос до 100%, а затем переполнился. Это возможно даже с flexbox?

Я был ошеломлен похожими вопросами, самые близкие из которых я считаю:

Сделать div заполнить высоту оставшегося пространства экрана - Это очень похоже, но мой вопрос добавляет "необходимо прокрутить, если он переполняется на 100%".

Ребенок с максимальной высотой: родитель переполняется на 100% - Я думаю, что это корень проблемы. Не имея установленной родительской высоты, он не может рассчитать высоту для переполнения.

Как сделать контейнер flexbox для прокрутки? - Опять-таки, необходима гибкая база пикселей. :. (

Я могу использовать display: tables или другие решения. После этого я думаю, что потребуется решение javascript.

Ответы [ 3 ]

1 голос
/ 30 марта 2019

Ты почти хорош.Просто сделайте элемент #b также контейнером flexbox и с overflow:hidden или min-height:0

html, body {
  height: 100%;
  margin: 0;
}

#container {
  width: 100%;
  height: 100%;
  background-color: gray;
  display: flex;
  flex-direction: column;
}

#a {
  flex: 0 1 auto;
}

#b {
  flex: 2 1 auto;
  overflow:hidden;
  /*added this*/
  display:flex;
  flex-direction:column;
  /**/
}

#c {
  flex: 0 1 auto;
}

#s2 {
  overflow: auto;
  background-color: lightblue;
}
<div id="container">
    <div id="a"><div>Section 1</div></div>
    <div id="b">
      <div>Section 2</div>
      <div id="s2">
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
      </div>
    </div>
    <div id="c"><div>Section 3</div></div>
</div>

Вместо того, чтобы сделать контейнер 10101 * flexbox, вы также можете рассмотреть height:100% для s2

html, body {
  height: 100%;
  margin: 0;
}

#container {
  width: 100%;
  height: 100%;
  background-color: gray;
  display: flex;
  flex-direction: column;
}

#a {
  flex: 0 1 auto;
}

#b {
  flex: 2 1 auto;
  overflow:hidden;
}

#c {
  flex: 0 1 auto;
}

#s2 {
  height:100%;
  overflow: auto;
  background-color: lightblue;
}
<div id="container">
    <div id="a"><div>Section 1</div></div>
    <div id="b">
      <div>Section 2</div>
      <div id="s2">
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
      </div>
    </div>
    <div id="c"><div>Section 3</div></div>
</div>
1 голос
/ 30 марта 2019

Секция #b вашего аккордеона заполняет оставшееся пространство в #container - поэтому вы можете разделить это вертикальное пространство между его содержимым - заголовок и#s2:

  • make #b a flexbox с flex-direction: column
  • также не забудьте установить min-height: 0 для #b (min-height is auto по умолчанию для flex item )
  • flex: 1 будет достаточно в #b вместо flex: 2 1 auto
  • такжедобавьте flex: 1 к #s2, чтобы оно заполнило оставшееся пространство внутри #b (вы можете опустить max-height: 100%).

См. Демонстрацию ниже:

html, body {
  height: 100%;
  margin: 0;
}

#container {
  width: 100%;
  height: 100%; 
  background-color: gray;
  display: flex;
  flex-direction: column;
}

#a {
  flex: 0 1 auto;
}

#b {
  flex: 1; /* this would do */
  display: flex; /* added*/
  flex-direction: column; /* added */
  min-height: 0; /* added */
}

#c {
  flex: 0 1 auto;
}

#s2 {
  flex: 1; /* added */
  /* max-height: 100%;*/
  overflow: auto;
  background-color: lightblue;
}
<div id="container">
    <div id="a"><div>Section 1</div></div>
    <div id="b">
      <div>Section 2</div>
      <div id="s2">
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
      </div>
    </div>
    <div id="c"><div>Section 3</div></div>
</div>

Теперь у вас есть аккордеон с полным обзором - вы также можете позволить #container занимать столько места, сколькоон нужен, когда элемент аккордеона расширяется и позволяет ему расширяться до высоты области просмотра и переполняться только потом - просто измените height: 100% в container на max-height: 100% - см. демонстрацию ниже:

html, body {
  height: 100%;
  margin: 0;
}

#container {
  width: 100%;
  max-height: 100%; /* changed to max-height */
  background-color: gray;
  display: flex;
  flex-direction: column;
}

#a {
  flex: 0 1 auto;
}

#b {
  flex: 1; /* this would do */
  display: flex; /* added*/
  flex-direction: column; /* added */
  min-height: 0; /* added */
}

#c {
  flex: 0 1 auto;
}

#s2 {
  flex: 1; /* added */
  /* max-height: 100%;*/
  overflow: auto;
  background-color: lightblue;
}
<div id="container">
    <div id="a"><div>Section 1</div></div>
    <div id="b">
      <div>Section 2</div>
      <div id="s2">
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
       <div>Item</div>
      </div>
    </div>
    <div id="c"><div>Section 3</div></div>
</div>
1 голос
/ 30 марта 2019

Отметьте это https://codepen.io/anon/pen/EJYwmq

Проблема в том, что элементы внутри флексбоксов имеют неявную "минимальную высоту", равную ее реальной высоте.Вы можете установить это min-height: 0px.

html, body {
  height: 100%;
  margin: 0;
}

#container {
  height: 100%;
  background-color: gray;
  display: flex;
  flex-direction: column;
}

#b {
  flex: 100% 1 1;
  min-height: 0px; // this is important!
  overflow: hidden;
  display: flex; // make it a flex too so you have better control of the scrollbar
  flex-direction: column;
}

#s2 {
  min-height: 0px;
  max-height: 100%;
  overflow: auto;
  background-color: lightblue;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...