Задача
В блоке на странице требуется разместить два вложенных блока таким образом, чтобы один блок имел максимальную высоту, а второй — занимал все оставшееся в родительском блоке свободное место по высоте. Причем, в случае, если контент не помещается в блок, добавлять ему скролл.
Реализация
При реализации данной задачи было принято решение использовать CSS Flexbox.
Для начала следует решить задачу без учета контента, т.е. с двумя пустыми дочерними блоками:
Как это работает
Родительскому блоку (на рисунке обозначен зеленым цветом) задан display: flex; и flex-direction: column; для задания направления контента. Дочерним блокам заданы стили flex: 0 0 auto; для блока, для которого известна высота, и flex: 1 0 auto; для блока, который бодет растягиваться на все свободное место. «1» для второго блока в данном случае означает «жадность», т.е. более жадный блок занимает больше места, чем менее жадный, а т.к. в данном случае у менее жадного задана высота (может быть задана максимальная высота), то более жадный блок занимает все свободное место.
Добавим контент в нижний блок
Для добавления скролла тут достаточно указать overflow: auto;
Добавим контент в верхний блок
Тут так просто, как с нижним блоком, не выйдет. Все потому, что flex учитывает ее и высоту контента.
Чтобы решить эту проблему, контент необходимо спозиционировать абсолютно (position: absolute;) и задать ему свойства top, right, bottom, left равными нулю (чтобы растянуть его по размерам блока)
Теперь блок занимает нужный нам размер, однако контент вылазит из него. Для решения этой проблемы необходимо родительскому для контента блоку задать position: relative; overflow: auto;
Вуаля, мы получили два блока со скроллом, один из которых имеет максимальную высоту, а второй растягивается по всему свободному месту.
<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>
.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. Работающий пример можно посмотреть тут
Комментарии (14)
ScorpAL
14.10.2016 10:43+2Не хватает заголовка "Где это работает".
Почему все так стесняются протестировать в нескольких браузерах и честно написать что работает в таком и таком браузере, но не работает в таком и таком?DarthVictor
14.10.2016 12:18Давайте поможем автору в этом.
Работает в:
- Chrome 53.0.2785.143
- IE 11.321.14393.0
- Microsoft EdgeHTML 14.14393, Microsoft Edge 38.14393.0.0
- Firefox 43.0.1
- Эмулятор Хрома для мобилок
EvgenyMakhnovets
14.10.2016 12:40Спасибо, забыл об этом в статье.
P.S. если использовать префиксы, то работает и в IE 10. Ну то есть все современные браузеры поддерживаются
shlangus
14.10.2016 12:38Я не уверен что правильно понял описание задачи, но вот это похоже на то, что вы сделали, только без 2 лишних блоков.
EvgenyMakhnovets
14.10.2016 12:39В данном случае, если уменьшить контент в нижнем блоке он автоматически не уменьшится по величине
shlangus
14.10.2016 14:11+1Этот случай вы изобразили на правой картинке? Из-за элипсиса я не сообразил к чему она. Позвольте ещё одну попытку.
Serator
14.10.2016 13:13+1@EvgenyMakhnovets Уже много раз писал (не конкретно вам, а вообще), но толку все равно нет. Забудьте о свойстве
flex
. Пишите все раздельно. Тогда и про "растягивается", "жадность" и прочие недоразумения писать не нужно будет, так как об этом скажет ваш код, а не набор непонятных0 0 auto
и т.п.
И вот, кстати, решение задачи из статьи, только без горы мусора и с читаемым CSS'ом: https://jsbin.com/gajozaj/5/edit?html,css,output.
DenimTornado
14.10.2016 15:46А можете рассказать чуть больше про изначальную задачу? Честно говоря какое-то странное поведение. И если честно, не до конца понятно, что подразумевается под «максимальной» высотой? То есть первый блок должен динамически расширяться до определённого момента, так? В общем, хотелось бы чуть подробнее о задаче узнать. Заране спасибо!
EvgenyMakhnovets
14.10.2016 20:24Нижних блок имеет максимальную высоту, и его высота равна контенту, если меньше максимальной (в противном случае = максимальной + скрол). Верхний — растягивается на все оставшееся место в контернере (по высоте), если не влазит, то добавляется скрол
pepelsbey
16.10.2016 23:20Вы же понимаете, что у вас в CSS будет чудовищный селектор
.container .first-child .first-content
? Не нужна это вложенность здесь, да нигде она не нужна. Думайте иногда о том, что выдаёт вам Sass.
MooNDeaR
CSS — это просто, а главное — интуитивно понятно!