Использование CSS Flexbox для позиционирования блоков на странице

Задача


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

image


Реализация


При реализации данной задачи было принято решение использовать CSS Flexbox.
Для начала следует решить задачу без учета контента, т.е. с двумя пустыми дочерними блоками:

image

Как это работает


Родительскому блоку (на рисунке обозначен зеленым цветом) задан display: flex; и flex-direction: column; для задания направления контента. Дочерним блокам заданы стили flex: 0 0 auto; для блока, для которого известна высота, и flex: 1 0 auto; для блока, который бодет растягиваться на все свободное место. «1» для второго блока в данном случае означает «жадность», т.е. более жадный блок занимает больше места, чем менее жадный, а т.к. в данном случае у менее жадного задана высота (может быть задана максимальная высота), то более жадный блок занимает все свободное место.

Добавим контент в нижний блок


Для добавления скролла тут достаточно указать overflow: auto;

image

Добавим контент в верхний блок


Тут так просто, как с нижним блоком, не выйдет. Все потому, что flex учитывает ее и высоту контента.

image

Чтобы решить эту проблему, контент необходимо спозиционировать абсолютно (position: absolute;) и задать ему свойства top, right, bottom, left равными нулю (чтобы растянуть его по размерам блока)

image

Теперь блок занимает нужный нам размер, однако контент вылазит из него. Для решения этой проблемы необходимо родительскому для контента блоку задать position: relative; overflow: auto;

image

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

image

Результат (HTML):
<div class="container">
  <div class="first-child">
    <div class="first-content">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
    </div>    
  </div>
  <div class="second-child">
    <div class="second-content">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
    </div>
  </div>
</div>


Результат (SCSS)
.container {
  display: flex;
  flex-direction: column;
  width: 150px;
  height: 200px;
  background-color: #A5D6A7;
  
  .first-child {    
    flex: 1 0 auto;
    position: relative;
    overflow: auto;
    width: 125px;
    box-sizing: border-box;
    background-color: #90CAF9;
    
    .first-content {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      padding: 5px;
    }
  }
  
  .second-child {
    flex: 0 0 auto;
    width: 125px;
    max-height: 75px;
    padding: 5px;
    box-sizing: border-box;
    overflow: auto;
    background-color: #CE93D8;
  }
}


P.S. Работающий пример можно посмотреть тут

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 14

    0
    CSS — это просто, а главное — интуитивно понятно!
      +2
      Не хватает заголовка "Где это работает".

      Почему все так стесняются протестировать в нескольких браузерах и честно написать что работает в таком и таком браузере, но не работает в таком и таком?
        0
        Давайте поможем автору в этом.
        Работает в:
        • Chrome 53.0.2785.143
        • IE 11.321.14393.0
        • Microsoft EdgeHTML 14.14393, Microsoft Edge 38.14393.0.0
        • Firefox 43.0.1
        • Эмулятор Хрома для мобилок
          0
          Спасибо, забыл об этом в статье.
          P.S. если использовать префиксы, то работает и в IE 10. Ну то есть все современные браузеры поддерживаются
        0
        Я не уверен что правильно понял описание задачи, но вот это похоже на то, что вы сделали, только без 2 лишних блоков.
          0
          В данном случае, если уменьшить контент в нижнем блоке он автоматически не уменьшится по величине
            +1
            Этот случай вы изобразили на правой картинке? Из-за элипсиса я не сообразил к чему она. Позвольте ещё одну попытку.
          0
          чуть проще можно сделать
            0
            Та же проблема, что и в предыдущем комментарии
            +1

            @EvgenyMakhnovets Уже много раз писал (не конкретно вам, а вообще), но толку все равно нет. Забудьте о свойстве flex. Пишите все раздельно. Тогда и про "растягивается", "жадность" и прочие недоразумения писать не нужно будет, так как об этом скажет ваш код, а не набор непонятных 0 0 auto и т.п.


            И вот, кстати, решение задачи из статьи, только без горы мусора и с читаемым CSS'ом: https://jsbin.com/gajozaj/5/edit?html,css,output.

              0
              А можете рассказать чуть больше про изначальную задачу? Честно говоря какое-то странное поведение. И если честно, не до конца понятно, что подразумевается под «максимальной» высотой? То есть первый блок должен динамически расширяться до определённого момента, так? В общем, хотелось бы чуть подробнее о задаче узнать. Заране спасибо!
                0
                Нижних блок имеет максимальную высоту, и его высота равна контенту, если меньше максимальной (в противном случае = максимальной + скрол). Верхний — растягивается на все оставшееся место в контернере (по высоте), если не влазит, то добавляется скрол
                0

                Вы же понимаете, что у вас в CSS будет чудовищный селектор .container .first-child .first-content? Не нужна это вложенность здесь, да нигде она не нужна. Думайте иногда о том, что выдаёт вам Sass.

                  0
                  Да, косяк мой, но статья не совсем об этом)

                Only users with full accounts can post comments. Log in, please.