Галерея со скользящим hover-эффектом
Мы создадим галерею с красивым скользящим эффектом при наведении. Начнём с разметки. Добавим в неё пару обёрток для галереи и картинки замков из Героев 3.
Сделаем базовую стилизацию галереи. Добавляем свойство position: relative
к классу .gallery
, чтобы можно было позиционировать внутренние элементы галереи относительно этого блока. Оно пригодится позже.
Превратим .gallery__box
в грид-контейнер с тремя колонками.
Добавим gap
размером 20px
между колонками в .gallery__box
.
Добавим padding
размером 5px
к .gallery__box
для создания внутреннего отступа, отделяющего содержимое от края блока галереи.
Задаём изображениям ширину в 100%
, чтобы изображения занимали всю ширину колонок, и height: auto
для сохранения пропорций.
Задаём изображениям фиксированное соотношение сторон с помощью aspect-ratio
и object-fit: cover
. Немного скругляем углы.
Добавляем к изображению тени с помощью свойства box-shadow
.
Базовая стилизация галереи готова. Можно приступать к созданию эффекта при наведении.
Для создания нужного нам эффекта понадобится создать копию разметки галереи. В копии разметки изменим класс gallery__box--regular
на gallery__box--copy
.
Затемним верхний экземпляр галереи с помощью css-фильтров grayscale
и brightness
.
Временно изменим пропорции изображений, чтобы всё помещалось на один экран.
Главный секрет этого эффекта — использование свойства clip-path
, которое позволяет полностью обрезать содержание блока.
С помощью clip-path
мы можем обрезать галерею так, чтобы были видны только отдельные картинки. Например, значение inset(0px 420px 0px 0)
обрежет всё, кроме первой картинки.
Функция inset
описывает «внутренний прямоугольник». Каждое значение — это отступ соответствующей стороны этого прямоугольника от границ родителя.
Например, inset(50px 50px 50px 50px)
создаст прямоугольник с отступами 50px
от каждой стороны.
Первое значение в inset
задаёт отступ от верхней стороны. Давайте изменим его на ноль.
Второе значение в inset
задаёт отступ от правой стороны. Давайте обнулим и его. Видите, как пропала обрезка справа?
Третье значение в inset
задаёт отступ от снизу. Обнуляем
Четвёртое значение в inset
задаёт отступ от слева. Тоже обнуляем.
То есть запись inset(0px 420px 0px 0)
задаёт прямоугольник, который занимает всю высоту контейнера и правая сторона которого смещена от правой стороны контейнера на 420px
.
Чтобы обрезать первое и третье изображения, нужно задать правой и левой сторонам прямоугольника смещения 210px
.
Чтобы обрезать первое и второе изображение задаём смещение 420px
левой стороне прямоугольника.
Можете сами поэкспериментировать со значением inset()
, чтобы закрепить материал.
Наша задача — создать эффект при наведении, то есть использовать псевдокласс :hover
. Посмотрите на этот сложный селектор:
:root:has(.gallery__image:nth-child(1):hover) .gallery__box--copy {}
И наведите курсор на первое изображение в верхней галерее. Видите, этот селектор позволяет нам управлять состоянием нижней галереи при наведении на элементы верхней.
Добавляем плавный переход для clip-path
в классе .gallery__box--copy
. Наведите ещё раз курсор на первое изображение в верхнем блоке. Ховер-эффект начинает прорисовываться.
Благодаря плавному переходу «область обрезки» плавно двигается по нижней галерее.
Используем ещё один сложный селектор:
:root:has(.gallery__image:nth-child(2):hover) .gallery__box--copy {}
Он заставляет отображаться второе изображение в нижней галерее при наведении на второе изображение в верхней.
Аналогичное CSS-правило добавим для третьего изображения. Эффект его работы станет виден, если наведёте курсор на первое или второе изображение, а потом обратно на третье.
Изменяем обрезку по умолчанию таким образом, чтобы было видно первое изображение.
Теперь с помощью абсолютного позиционирования размещаем нижнюю галерею над верхней, так чтобы они полностью совпадали. Добиться этого не сложно, ведь элементы одинаковые.
Задаём нижней галерее размеры контейнера и, на всякий случай, z-index
.
Возвращаем изображениям исходное соотношение сторон. Красивый скользящий эффект при наведении готов.