Псевдо 3D эффект при наведении на карточку
В данной статье кратко опишу как добиться такого эффекта карточки при наведении
Структура примера
Сверстаем 4 карточки, при этом будем использовать CSS переменную --color
прямо в инлайн стилях для элементов выбора цвета
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Pseudo 3D Effect on Hover</title>
<link rel="stylesheet" href="css/bootstrap-reboot.min.css"/>
<link rel="preconnect" href="https://fonts.gstatic.com"/>
<link href="https://fonts.googleapis.com/css2?family=Lora:wght@700&family=Roboto:wght@300;400&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="css/main.css"/>
</head>
<body>
<section class="section">
<div class="container">
<div class="section__wrapper">
<div class="card"><a href="">
<div class="card__image"><img src="https://images.unsplash.com/photo-1545838593-b4aeec49204b?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80" alt=""/></div>
<div class="card__body">
<div class="card__title"><span>Relaxed Fit Short-sleeve Shirt</span></div>
<div class="card__price"><span>$14</span></div>
<div class="card__colors">
<div class="card__color" style="--color:#92D1C3"></div>
<div class="card__color" style="--color:#6A7FDB"></div>
<div class="card__color" style="--color:#EE7674"></div>
</div>
</div></a></div>
<div class="card"><a href="">
<div class="card__image"><img src="https://images.unsplash.com/photo-1568151556783-f2b5999eada6?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80" alt=""/></div>
<div class="card__body">
<div class="card__title"><span>Fit Short-sleeve Shirt</span></div>
<div class="card__price"><span>$24</span></div>
<div class="card__colors">
<div class="card__color" style="--color:#216869"></div>
<div class="card__color" style="--color:#F6AE2D"></div>
<div class="card__color" style="--color:#EE7674"></div>
</div>
</div></a></div>
<div class="card"><a href="">
<div class="card__image"><img src="https://images.unsplash.com/photo-1566204580788-1437e545bb36?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1000&q=80" alt=""/></div>
<div class="card__body">
<div class="card__title"><span>Sleeve Shirt</span></div>
<div class="card__price"><span>$19</span></div>
<div class="card__colors">
<div class="card__color" style="--color:#FDF5BF"></div>
<div class="card__color" style="--color:#F26419"></div>
<div class="card__color" style="--color:#EE7674"></div>
</div>
</div></a></div>
<div class="card"><a href="">
<div class="card__image"><img src="https://images.unsplash.com/photo-1549043671-1e4550948355?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80" alt=""/></div>
<div class="card__body">
<div class="card__title"><span>Short-sleeve Shirt</span></div>
<div class="card__price"><span>$9</span></div>
<div class="card__colors">
<div class="card__color" style="--color:#216869"></div>
<div class="card__color" style="--color:#6A7FDB"></div>
<div class="card__color" style="--color:#47624F"></div>
</div>
</div></a></div>
</div>
</div>
</section>
</body>
</html>
CSS стили
Основную сетку карточек и элементы выбора цвета сделаем через display: grid;
, чтобы более удобно и гибко и настраивать расположение элементов и расстояние между ними
Для элемента выбора цвета задаем начальное значение CSS переменной --color: transparent;
и сразу применяем ее значение для background-color: var(--color);
Значение переменной мы заменяем необходимым цветом в инлайн стилях в HTML структуре
Карточке задаём начальные значения свойств, которые будет меняться при наведении курсора - filter: drop-shadow(0px 0px 0px #ccc9dc); transform: perspective(1000px) rotateY(0deg) rotateX(0deg);
filter: drop-shadow()
создаёт тень на основе контента, в данном примере размытие тени установлено в 0px
, поэтому тень полностью повторяет контуры элементов карточки
transform
со значением perspective(1000px)
создает имитацию 3D-пространства
Для плавного изменения значений используем transition: 0.4s ease-out;
При наведении на карточку меняем её значения на filter: drop-shadow(24px 12px 0px #ccc9dc); transform: perspective(1000px) rotateY(-16deg) rotateX(8deg);
Документация по transform: perspective();
- https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective()
Документация по filter: drop-shadow();
- https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/drop-shadow()
Для zoom эффекта изображения используем object-fit: cover;
и transform: scale();
, подробнее в статье Zoom-эффект - масштаб и позиционирование изображения
Для изменения формы изображения используем свойство clip-path
В данном примере задаем начальные значения clip-path: polygon(0% 0%, 100% 0, 100% 50%, 100% 100%, 0% 100%);
И при наведении курсора на карточку меняем значения на clip-path: polygon(0% 0%, 88% 0%, 100% 50%, 88% 100%, 0% 100%);
Для плавного изменения значений также используем transition: 0.4s ease-out;
Чтобы посмотреть, каких фигур можно добиться данным свойством, можно воспользоваться генератором CSS clip-path maker
Документация по clip-path
- https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path
body {
font-family: 'Roboto', sans-serif;
background: #fff;
position: relative;
}
.container {
max-width: 1140px;
padding: 0 16px;
margin: 0 auto;
}
.section {
padding: 64px 0;
}
.section__wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 32px;
gap: 32px;
}
.card {
width: 100%;
transition: 0.4s ease-out;
-webkit-filter: drop-shadow(0px 0px 0px #ccc9dc);
filter: drop-shadow(0px 0px 0px #ccc9dc);
transform: perspective(1000px) rotateY(0deg) rotateX(0deg);
}
.card a {
text-decoration: none;
}
.card__image {
overflow: hidden;
height: 400px;
-webkit-clip-path: polygon(0% 0%, 100% 0, 100% 50%, 100% 100%, 0% 100%);
clip-path: polygon(0% 0%, 100% 0, 100% 50%, 100% 100%, 0% 100%);
transition: 0.4s ease-out;
}
.card__image img {
display: block;
-o-object-fit: cover;
object-fit: cover;
width: 100%;
height: 100%;
transition: 0.4s ease-out;
}
.card__body {
padding: 16px;
}
.card__title span {
display: inline-block;
color: #121212;
font-size: 16px;
margin-bottom: 4px;
transition: 0.4s ease-out;
font-family: 'Lora', serif;
}
.card__price {
text-align: right;
}
.card__price span {
display: inline-block;
font-family: 'Lora', serif;
margin-bottom: 12px;
font-size: 16px;
color: #121212;
transition: 0.4s ease-out;
}
.card__colors {
display: grid;
grid-template-columns: repeat(auto-fill, 16px);
grid-gap: 4px;
gap: 4px;
transition: 0.4s ease-out;
}
.card__color {
--color: transparent;
width: 16px;
height: 16px;
display: block;
border-radius: 8px;
background-color: var(--color);
}
.card:hover {
-webkit-filter: drop-shadow(24px 12px 0px #ccc9dc);
filter: drop-shadow(24px 12px 0px #ccc9dc);
transform: perspective(1000px) rotateY(-16deg) rotateX(8deg);
}
.card:hover .card__image {
-webkit-clip-path: polygon(0% 0%, 88% 0%, 100% 50%, 88% 100%, 0% 100%);
clip-path: polygon(0% 0%, 88% 0%, 100% 50%, 88% 100%, 0% 100%);
}
.card:hover .card__image img {
transform: scale(1.2);
}
@media (max-width: 767.98px) {
.section__wrapper {
grid-template-columns: 1fr;
}
}
Получаем следующий результат
Архив с примером можно скачать по ссылке
Буду рад, если статья оказалась полезной
Спасибо за ваше внимание и уделённое время!