Выравнивание по низу карточки
При верстке карточек товаров для каталога или аналогичных блоков, описание в карточке может значительно отличаться по объему текста. В результате, контент после этого текста располагается на разной высоте, что в большинстве случаев неприемлемо. Как это исправить?
Варианты решения
Возможные, но некорректные решения
Первый вариант - блоку с текстом можно задать фиксированную высоту, но это будет некорректно, так как неизвестно, какой объем текста будет использоваться для описания.
Второй вариант - блоку, который нужно прижать к низу карточки, присвоить position: absolute; bottom: 0;
и внизу карточки сделать увеличенный внутренний отступ padding
, но опять же вариант некорректен, так как придется надеяться, что этого отступа всегда будет хватать.
Корректное решение
Для корректного решения данной задачи воспользуемся display: flex
Рассмотрим простой пример
<div class="simple">
<div class="container">
<div class="simple__flex">
<div class="simple__card">
<div class="simple__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur accusantium corrupti reiciendis nisi voluptatum nobis vitae et, quo quaerat excepturi tempora, libero perspiciatis quae voluptates qui dolores autem doloribus ab.</div>
<div class="simple__button button"><a href="">Button</a></div>
</div>
<div class="simple__card">
<div class="simple__text">Lorem ipsum dolor sit amet</div>
<div class="simple__button button"><a href="">Button</a></div>
</div>
<div class="simple__card">
<div class="simple__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorum voluptate vero ipsa praesentium autem nihil.</div>
<div class="simple__button button"><a href="">Button</a></div>
</div>
<div class="simple__card">
<div class="simple__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorum voluptate vero ipsa praesentium autem nihil. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorum voluptate vero ipsa praesentium autem nihil.</div>
<div class="simple__button button"><a href="">Button</a></div>
</div>
</div>
</div>
</div>
Есть замечательное свойство flex-grow: 1;
, которое позволяет элементу растягиваться и занимать все доступное свободное пространство в родительском блоке, а также есть сокращенная запись этого свойства - flex: 1;
Подробнее про flex
Чтобы свойство flex: 1;
для блока <div class="simple__text"></div>
заработало, необходимо родительскому блоку <div class="simple__card"></div>
присвоить display: flex;
и flex-direction: column;
чтобы элементы располагались вертикально
Далее, если в ряду карточек у текста одинаковое количество строк, блоки с текстом будут одинаковой высоты, и нижний контент итак будет выровнен по низу карточки
Но если в ряду карточек имеются карточки с разным количеством текста, то карточки растягиваются по высоте самой высокой в ряду и внизу карточки образуется свободное пространство, так как у родительского блока <div class="simple__flex"></div>
установлено display: flex;
, a у него по умолчанию align-items: stretch;
Это свободное пространство занимаем блоком <div class="simple__text"></div>
с помощью свойства flex: 1;
, а нижний блок с контентом прижимается к низу карточки, чего мы и добивались
.simple__flex {
display: flex;
justify-content: space-between;
}
.simple__card {
padding: 30px;
width: calc(25% - 10px);
display: flex;
flex-direction: column; /* располагаем <div class="simple__text"></div> и <div class="simple__button"></div> вертикально */
}
.simple__text {
flex: 1; /* растягиваем <div class="simple__text"></div> на все доступное свободное пространство в карточке <div class="simple__card"></div> */
}
.simple__button {
margin-top: 15px;
}
Более сложный пример с адаптивной сеткой
Посмотрите пример на Codepen
Полный код примера
<section class="catalog">
<div class="container">
<div class="catalog__flex">
<div class="catalog__row">
<div class="catalog__col">
<div class="catalog__card card">
<div class="card__image"><img src="https://picsum.photos/1920/1080" alt=""/></div>
<div class="card__body">
<div class="card__title">Catalog One</div>
<div class="card__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aspernatur, maiores.</div>
<div class="card__bottom">
<div class="card__cost">$49</div>
<div class="card__button button"><a href="">Buy</a></div>
</div>
</div>
</div>
</div>
<div class="catalog__col">
<div class="catalog__card card">
<div class="card__image"><img src="https://picsum.photos/1920/1081" alt=""/></div>
<div class="card__body">
<div class="card__title">Catalog Two</div>
<div class="card__text">Consectetur adipisicing elit</div>
<div class="card__bottom">
<div class="card__cost">$19</div>
<div class="card__button button"><a href="">Buy</a></div>
</div>
</div>
</div>
</div>
<div class="catalog__col">
<div class="catalog__card card">
<div class="card__image"><img src="https://picsum.photos/1920/1082" alt=""/></div>
<div class="card__body">
<div class="card__title">Catalog Three</div>
<div class="card__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus, ipsum. Lorem ipsum dolor sit amet.</div>
<div class="card__bottom">
<div class="card__cost">$89</div>
<div class="card__button button"><a href="">Buy</a></div>
</div>
</div>
</div>
</div>
<div class="catalog__col">
<div class="catalog__card card">
<div class="card__image"><img src="https://picsum.photos/1920/1083" alt=""/></div>
<div class="card__body">
<div class="card__title">Catalog Four</div>
<div class="card__text">Consectetur adipisicing elit</div>
<div class="card__bottom">
<div class="card__cost">$39</div>
<div class="card__button button"><a href="">Buy</a></div>
</div>
</div>
</div>
</div>
<div class="catalog__col">
<div class="catalog__card card">
<div class="card__image"><img src="https://picsum.photos/1920/1084" alt=""/></div>
<div class="card__body">
<div class="card__title">Catalog Five</div>
<div class="card__text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Modi et vel pariatur laborum sed nihil quisquam, neque rerum atque minus!</div>
<div class="card__bottom">
<div class="card__cost">$69</div>
<div class="card__button button"><a href="">Buy</a></div>
</div>
</div>
</div>
</div>
<div class="catalog__col">
<div class="catalog__card card">
<div class="card__image"><img src="https://picsum.photos/1920/1085" alt=""/></div>
<div class="card__body">
<div class="card__title">Catalog Six</div>
<div class="card__text">Consectetur adipisicing elit onsectetur adipisicing elit</div>
<div class="card__bottom">
<div class="card__cost">$99</div>
<div class="card__button button"><a href="">Buy</a></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
@import url("https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;700&display=swap");
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family: 'Rubik', sans-serif;
}
.container {
padding: 0 30px;
max-width: 1200px;
margin: 0 auto;
}
.card {
border-radius: 15px;
overflow: hidden;
height: 100%;
display: flex;
flex-direction: column;
background: #fff;
}
.card__image {
height: 200px;
overflow: hidden;
width: 100%;
border-radius: 15px;
}
.card__image img {
display: block;
width: 100%;
height: 100%;
-o-object-fit: cover;
object-fit: cover;
}
.card__body {
padding: 15px;
flex: 1;
display: flex;
flex-direction: column;
}
.card__title {
font-size: 24px;
text-align: center;
margin-bottom: 15px;
}
.card__text {
text-align: center;
font-size: 16px;
flex: 1;
margin-bottom: 15px;
font-weight: 300;
}
.card__bottom {
display: flex;
align-items: center;
justify-content: space-evenly;
}
.card__cost {
font-size: 24px;
color: #4a60d7;
font-weight: 300;
}
.button {
text-align: center;
}
.button a {
display: inline-flex;
padding: 0 15px;
background: #4a60d7;
align-items: center;
justify-content: center;
text-align: center;
height: 40px;
width: 100px;
color: #fff;
border-radius: 5px;
text-decoration: none;
transition: all 0.6s ease;
}
.button a:hover {
background: #40ffdc;
}
.catalog {
background: #f1f1f1;
padding: 60px 0;
}
.catalog__title {
margin-bottom: 60px;
}
.catalog__row {
display: flex;
flex-wrap: wrap;
margin: 0 -15px -30px;
}
.catalog__col {
width: 33.33333333%;
padding: 0 15px 30px;
}
@media (max-width: 991.98px) {
.container {
padding: 0 15px;
}
.popular__col {
width: 50%;
}
}
@media (max-width: 767.98px) {
.catalog__col {
width: 100%;
}
}
Полезные ссылки