Анимация hover для карточек

CSS-эффекты при наведении на карточку: подъём, тень, overlay, zoom изображения — только CSS, никакого JS.

Задача

Карточки товаров или статей должны реагировать на наведение курсора — визуально «приподниматься» или раскрывать дополнительную информацию. Всё это делается через CSS transition без JavaScript.

Решение

<div class="card">
  <div class="card__img-wrap">
    <img class="card__img" src="photo.jpg" alt="Фото" />
    <div class="card__overlay">
      <a class="card__cta" href="#">Подробнее</a>
    </div>
  </div>
  <div class="card__body">
    <h3 class="card__title">Название карточки</h3>
    <p class="card__price">2 990 ₽</p>
  </div>
</div>
.card {
  border-radius: 12px;
  overflow: hidden;
  background: #fff;
  border: 1px solid #e2e8f0;
  /* Подъём и тень при hover */
  transition: transform 0.25s ease, box-shadow 0.25s ease;
  will-change: transform;
}

.card:hover {
  transform: translateY(-6px);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
}

/* Изображение: zoom при hover */
.card__img-wrap {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
}

.card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.card:hover .card__img {
  transform: scale(1.08);
}

/* Тёмный overlay с кнопкой */
.card__overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.card:hover .card__overlay {
  opacity: 1;
}

.card__cta {
  padding: 10px 24px;
  background: #fff;
  color: #1e293b;
  border-radius: 6px;
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  transform: translateY(8px);
  transition: transform 0.3s ease;
}

.card:hover .card__cta {
  transform: translateY(0);
}

.card__body { padding: 16px; }
.card__title { font-size: 1rem; font-weight: 600; margin-bottom: 4px; }
.card__price { color: #3b82f6; font-weight: 700; }

Ключевые моменты

  • will-change: transform — подсказка браузеру создать отдельный GPU-слой; используй умеренно.
  • overflow: hidden на .card и .card__img-wrap — обязателен, иначе zoom изображения выйдет за края.
  • Анимируй только transform и opacity — они не вызывают reflow, обрабатываются на GPU.
  • transition на дочернем элементе (.card__cta) — он наследует hover от родителя через CSS-каскад.

Варианты

  • 3D tilt эффект — JS-версия: отслеживай координаты мыши и применяй rotateX/rotateY через mousemove.
  • @media (hover: hover) — применяй hover-эффекты только на устройствах с мышью; на touch не активировать.
    @media (hover: hover) { .card:hover { transform: translateY(-6px); } }
    

Связанные рецепты / темы