Галерея со скользящим 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.
Возвращаем изображениям исходное соотношение сторон. Красивый скользящий эффект при наведении готов.