Чи знаєте ви такий ефект, коли чиясь голова просовується крізь коло чи отвір? Відомий анімаційний фільм Поркі Піг, де він махає рукою на прощання, вискакуючи з серії червоних кілець, є чудовим прикладом, і Кіліан Валкхоф нещодавно відтворив це тут, на CSS-Tricks.
У мене є схожа ідея, але я взявся за інший спосіб і з додаванням анімації. Я вважаю, що це досить практично та створює гарний ефект наведення, який можна використовувати на чомусь на зразок власного аватара.
Бачиш це? Ми збираємося створити масштабну анімацію, де аватар ніби вискочить із кола, у якому він знаходиться. Круто, правда? Не дивіться на код, а давайте створимо цю анімацію разом крок за кроком.
HTML: лише один елемент
Якщо ви не перевірили код демо-версії і вам цікаво, скільки div
Це займе, а потім зупиніться на цьому, тому що наша розмітка — це не що інше, як один елемент зображення:
<img src="" alt="">
Так, єдиний елемент! Складною частиною цієї вправи є використання найменшої можливої кількості коду. Якщо ви були за мною деякий час ви повинні звикнути до цього. Я наполегливо намагаюся знайти рішення CSS, які можна досягти за допомогою найменшого коду, який максимально зручно підтримувати.
Я написав серія статей тут, на CSS-Tricks, де я досліджую різні ефекти наведення, використовуючи ту саму розмітку HTML, що містить один елемент. Я детально описую градієнти, маскування, відсікання, контури та навіть техніку компонування. Я настійно рекомендую перевірити їх, тому що я повторно використаю багато трюків у цій публікації.
Файл зображення квадратної форми з прозорим фоном найкраще підійде для того, що ми робимо. Ось той, який я використовую, якщо ви хочете почати з нього.
Я сподіваюся побачити якомога більше прикладів цього, використовуючи реальні зображення — тому, будь ласка, поділіться своїм кінцевим результатом у коментарях, коли закінчите, щоб ми могли створити колекцію!
Перш ніж переходити до CSS, давайте спочатку розберемо ефект. Зображення збільшується при наведенні, тому ми обов’язково скористаємося transform: scale()
там. За аватаром є коло, і радіальний градієнт повинен зробити свою справу. Нарешті, нам потрібен спосіб створити рамку в нижній частині кола, яка створить видимість аватара за колом.
Приступаємо до роботи!
Ефект масштабу
Почнемо з додавання трансформації:
img { width: 280px; aspect-ratio: 1; cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}
Ще нічого складного, правда? Йдемо далі.
Коло
Ми сказали, що фон буде радіальним градієнтом. Це ідеально, тому що ми можемо створювати жорсткі межі між кольорами радіального градієнта, що створює враження, ніби ми малюємо коло суцільними лініями.
img { --b: 5px; /* border width */ width: 280px; aspect-ratio: 1; background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, #0000 ); cursor: pointer; transition: .5s;
}
img:hover { transform: scale(1.35);
}
Зверніть увагу на змінну CSS, --b
, я використовую там. Він представляє товщину «межі», яка насправді просто використовується для визначення жорстких кольорових зупинок для червоної частини радіального градієнта.
Наступний крок — пограти з розміром градієнта при наведенні. Коло має зберігати свій розмір у міру збільшення зображення. Оскільки ми застосовуємо a scale()
трансформації, ми дійсно потребуємо зменшити розмір кола, тому що інакше воно збільшується до аватара. Таким чином, коли зображення збільшується, нам потрібен градієнт для зменшення масштабу.
Давайте почнемо з визначення змінної CSS, --f
, який визначає «масштабний коефіцієнт», і використовуйте його для встановлення розміру кола. Я використовую 1
як значення за замовчуванням, оскільки це початковий масштаб для зображення та кола, з якого ми перетворюємо.
Ось демо для ілюстрації трюку. Наведіть курсор, щоб побачити, що відбувається за лаштунками:
Я додав третій колір до radial-gradient
щоб краще визначити область градієнта при наведенні:
radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), #C02942 calc(100% - var(--b)) 99%, lightblue
);
Тепер нам потрібно розташувати наш фон у центрі кола та переконатися, що він займає всю висоту. Я люблю заявляти про все прямо на background
скорочена властивість, щоб ми могли додати наше фонове позиціонування та переконатися, що воно не повторюється, додавши ці значення відразу після radial-gradient()
:
background: radial-gradient() 50% / calc(100% / var(--f)) 100% no-repeat;
Фон розташовується по центру (50%
), має ширину, рівну calc(100%/var(--f))
, і має висоту, що дорівнює 100%
.
Ніщо не масштабується, коли --f
дорівнює 1
— знову наш початковий масштаб. Тим часом градієнт займає всю ширину контейнера. Коли ми збільшуємо --f
, розмір елемента зростає — завдяки scale()
transform — і розмір градієнта зменшується.
Ось що ми отримуємо, коли застосовуємо все це до нашої демонстрації:
Ми наближаємось! У нас є ефект переливу вгорі, але нам все одно потрібно приховати нижню частину зображення, щоб воно виглядало так, ніби воно вискакує з кола, а не стоїть перед ним. Це складна частина всієї цієї справи, і це те, що ми збираємося робити далі.
Нижня межа
Я вперше спробував вирішити це за допомогою border-bottom
властивість, але я не зміг знайти спосіб зіставити розмір межі з розміром кола. Ось найкраще, що я міг отримати, і ви відразу бачите, що це неправильно:
Фактичним рішенням є використання outline
власність. так, outline
, Чи не border
, в попередня стаття, я показую як outline
є потужним і дозволяє нам створювати круті ефекти наведення. У поєднанні з outline-offset
, ми маємо саме те, що нам потрібно для нашого ефекту.
Ідея полягає в тому, щоб встановити outline
на зображенні та налаштуйте його зсув, щоб створити нижню межу. Зміщення залежатиме від коефіцієнта масштабування так само, як розмір градієнта.
Тепер у нас є наша нижня «межа» (насправді an outline
) у поєднанні з «рамкою», створеною градієнтом, щоб створити повне коло. Нам ще потрібно приховати частини outline
(зверху та з боків), до якого ми дійдемо за мить.
Ось наш код на даний момент, включаючи ще кілька змінних CSS, за допомогою яких можна налаштувати розмір зображення (--s
) і колір «рамки» (--c
):
img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50% / calc(100% / var(--f)) 100% no-repeat; transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}
Оскільки нам потрібна кругла нижня межа, ми додали a border-radius
на нижній стороні, дозволяючи outline
щоб відповідати кривизні градієнта.
Розрахунок, використаний на outline-offset
набагато простіше, ніж здається. За замовчуванням, outline
малюється поза коробки елемента. А в нашому випадку це потрібно перекриття елемент. Точніше, нам потрібно, щоб він слідував колу, створеному градієнтом.
Коли ми масштабуємо елемент, ми бачимо простір між колом і краєм. Не забуваймо, що ідея полягає в тому, щоб зберегти коло незмінного розміру після запуску масштабної трансформації, що залишає нам простір, який ми будемо використовувати для визначення зсуву контуру, як показано на малюнку вище.
Не забуваймо, що другий елемент масштабується, тому наш результат також масштабується… це означає, що нам потрібно розділити результат на f
щоб отримати реальне значення зсуву:
Offset = ((f - 1) * S/2) / f = (1 - 1/f) * S/2
Ми додаємо мінус, оскільки нам потрібно, щоб контур йшов ззовні всередину:
Offset = (1/f - 1) * S/2
Ось коротка демонстрація, яка показує, як контур повторює градієнт:
Можливо, ви вже бачите це, але нам все одно потрібен нижній контур, щоб перекривати коло, а не дозволяти йому протікати крізь нього. Ми можемо зробити це, видаливши розмір рамки зі зсуву:
outline-offset: calc((1 / var(--f) - 1) * var(--s) / 2) - var(--b));
Тепер нам потрібно знайти, як видалити верхню частину з контуру. Іншими словами, нам потрібна лише нижня частина зображення outline
.
По-перше, давайте додамо простір угорі за допомогою відступу, щоб уникнути перекриття вгорі:
img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ width: var(--s); aspect-ratio: 1; padding-block-start: calc(var(--s)/5); /* etc. */
}
img:hover { --f: 1.35; /* hover scale */
}
Немає особливої логіки в цьому верхньому прокладці. Ідея полягає в тому, щоб контур не торкався голови аватара. Я використовував розмір елемента, щоб визначити, що простір завжди має однакову пропорцію.
Зверніть увагу, що я додав content-box
значення для background
:
background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000 ) 50%/calc(100%/var(--f)) 100% no-repeat content-box;
Нам це потрібно, тому що ми додали відступи, і ми хочемо встановити фон лише для вікна вмісту, тому ми повинні явно вказати фону зупинитися на цьому.
Додавання маски CSS до суміші
Ми дійшли до останньої частини! Все, що нам потрібно зробити, це сховати деякі частини, і ми готові. Для цього ми будемо спиратися на mask
і, звичайно, градієнти.
Ось малюнок, щоб проілюструвати те, що нам потрібно приховати або що нам потрібно показати, щоб бути точнішим
Ліве зображення – це те, що ми маємо зараз, а праве – те, що ми хочемо. Зелена частина ілюструє маску, яку ми повинні застосувати до вихідного зображення, щоб отримати остаточний результат.
Ми можемо визначити дві частини нашої маски:
- Кругла частина внизу, яка має той самий розмір і кривизну, що й радіальний градієнт, який ми використали для створення кола позаду аватара
- Прямокутник у верхній частині, який покриває область всередині контуру. Зверніть увагу на те, що контур знаходиться за межами зеленої зони вгорі — це найважливіша частина, оскільки це дозволяє обрізати контур так, щоб було видно лише нижню частину.
Ось наш остаточний CSS:
img { --s: 280px; /* image size */ --b: 5px; /* border thickness */ --c: #C02942; /* border color */ --f: 1; /* initial scale */ --_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; --_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b)); width: var(--s); aspect-ratio: 1; padding-top: calc(var(--s)/5); cursor: pointer; border-radius: 0 0 999px 999px; outline: var(--b) solid var(--c); outline-offset: var(--_o); background: radial-gradient( circle closest-side, #ECD078 calc(99% - var(--b)), var(--c) calc(100% - var(--b)) 99%, #0000) var(--_g); mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g); transform: scale(var(--f)); transition: .5s;
}
img:hover { --f: 1.35; /* hover scale */
}
Давайте розберемо це mask
власність. Для початку зауважте, що схоже radial-gradient()
від background
власність є там. Я створив нову змінну, --_g
, для загальних частин, щоб речі були менш захаращеними.
--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);
Далі є a linear-gradient()
там також:
--_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box; mask: linear-gradient(#000 0 0) no-repeat 50% calc(-1 * var(--_o)) / calc(100% / var(--f) - 2 * var(--b)) 50%, radial-gradient( circle closest-side, #000 99%, #0000) var(--_g);
Це створює прямокутну частину маски. Його ширина дорівнює ширині радіального градієнта мінус подвоєна товщина межі:
calc(100% / var(--f) - 2 * var(--b))
Висота прямокутника дорівнює половині, 50%
, від розміру елемента.
Нам також потрібен лінійний градієнт, розміщений у горизонтальному центрі (50%
) і зсув від верху на те саме значення, що й зміщення контуру. Я створив ще одну змінну CSS, --_o
, для зміщення, яке ми визначили раніше:
--_o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));
Однією з заплутаних речей є те, що нам потрібен a негативний зсув для контуру (щоб перемістити його ззовні всередину), але a позитивний зсув для градієнта (для переміщення зверху вниз). Отже, якщо вам цікаво, чому ми множимо зсув, --_o
, по -1
ну, тепер ти знаєш!
Ось демонстрація, щоб проілюструвати конфігурацію градієнта маски:
Наведіть вказівник миші на зображення вище та подивіться, як усе рухається разом. Середнє поле ілюструє шар маски, що складається з двох градієнтів. Уявіть це як видиму частину лівого зображення, і ви отримаєте кінцевий результат справа!
Підводячи підсумок
Ой, ми закінчили! І ми не тільки закінчили з гладкою анімацією наведення, але ми зробили все це за допомогою одного HTML <img>
елемент. Тільки це та менше 20 рядків CSS-обману!
Звичайно, ми покладалися на деякі невеликі хитрощі та математичні формули, щоб досягти такого складного ефекту. Але ми точно знали, що робити, оскільки заздалегідь визначили потрібні елементи.
Чи могли б ми спростити CSS, якби дозволили собі більше HTML? Абсолютно. Але ми тут, щоб вивчати нові прийоми CSS! Це була хороша вправа для вивчення градієнтів CSS, маскування тощо outline
поведінка власності, перетворення та багато іншого. Якщо ви колись відчули, що загубилися, обов’язково перевірте моя серія який використовує ті самі загальні поняття. Іноді допомагає побачити більше прикладів і варіантів використання, щоб переконатися в тому.
Я залишу вам останню демонстрацію, яка використовує фотографії популярних розробників CSS. Не забудьте показати мені демо-версію з вашим власним зображенням, щоб я міг додати її до колекції!
- Розповсюдження контенту та PR на основі SEO. Отримайте посилення сьогодні.
- Платоблокчейн. Web3 Metaverse Intelligence. Розширені знання. Доступ тут.
- джерело: https://css-tricks.com/a-fancy-hover-effect-for-your-avatar/
- 1
- 10
- 11
- 28
- 7
- 9
- 98
- a
- вище
- абсолютно
- досягнутий
- насправді
- доданий
- після
- ВСІ
- Дозволити
- дозволяє
- вже
- завжди
- кількість
- та
- анімація
- Інший
- Застосовувати
- Застосування
- ПЛОЩА
- аватар
- фон
- оскільки
- за
- за лаштунками
- буття
- КРАЩЕ
- Краще
- між
- більший
- border
- дно
- Box
- Перерва
- будувати
- гроно
- випадок
- випадків
- Центр
- складні
- перевірка
- контроль
- Коло
- код
- color
- комбінований
- коментарі
- загальний
- комплекс
- складний
- складається
- поняття
- конфігурація
- заплутаний
- Контейнер
- зміст
- Прохолодно
- може
- Пара
- Курс
- Обкладинки
- створювати
- створений
- створює
- CSS
- В даний час
- Вирізати
- дефолт
- певний
- Визначає
- визначаючи
- безумовно
- деталь
- розробників
- DID
- різний
- Розмір
- безпосередньо
- Ні
- справи
- Не знаю
- вниз
- малювання
- управляти
- край
- ефект
- ефекти
- забезпечувати
- і т.д.
- Навіть
- все
- точно
- приклад
- Приклади
- Здійснювати
- дослідити
- знаменитий
- Рисунок
- філе
- остаточний
- в кінці кінців
- знайти
- Перший
- стежити
- слідує
- від
- перед
- Повний
- Загальне
- отримати
- отримання
- Go
- буде
- добре
- градієнти
- зелений
- Зростає
- Половина
- Жорсткий
- голова
- висота
- допомога
- допомагає
- тут
- приховувати
- дуже
- Hole
- Головна
- сподіваючись
- Горизонтальний
- hover
- Як
- How To
- HTML
- HTTPS
- ідея
- ідентифікований
- ідентифікувати
- зображення
- зображень
- негайно
- важливо
- in
- В інших
- У тому числі
- Augmenter
- початковий
- IT
- тільки один
- тримати
- Дитина
- Знати
- останній
- шар
- макет
- УЧИТЬСЯ
- Залишати
- здавати
- ліній
- трохи
- подивитися
- виглядає як
- ВИГЛЯДИ
- серія
- Підлягає ремонту
- зробити
- РОБОТИ
- багато
- маска
- матч
- математики
- засоби
- Між тим
- Середній
- момент
- більше
- найбільш
- рухатися
- Необхідність
- потреби
- негативний
- Нові
- наступний
- зсув
- ONE
- оригінал
- Інше
- інакше
- план
- контури
- поза
- власний
- частина
- приватність
- частини
- ідеальний
- частин
- plato
- Інформація про дані Платона
- PlatoData
- Play
- будь ласка
- точка
- поп
- популярний
- положення
- позиціонування
- це можливо
- пошта
- потужний
- Практичний
- точно
- досить
- попередній
- раніше
- власність
- Швидко
- досягати
- досяг
- реальний
- рекомендувати
- червоний
- видаляти
- видалення
- повторювати
- представляє
- результат
- Зазначений
- то ж
- шкала
- ваги
- Масштабування
- сцени
- другий
- Здається,
- Серія
- комплект
- Поділитись
- стенограма
- Повинен
- Показувати
- Шоу
- сторона
- Сторони
- підпис
- аналогічний
- спрощений
- з
- один
- Сидячий
- Розмір
- So
- так далеко
- solid
- рішення
- Рішення
- деякі
- що в сім'ї щось
- Простір
- площа
- старт
- Крок
- Як і раніше
- Стоп
- Зупиняє
- просто
- такі
- Приймати
- приймає
- методи
- Команда
- Площа
- Там.
- річ
- речі
- третій
- через
- до
- разом
- топ
- торкатися
- Перетворення
- Перетворення
- перетворень
- перехід
- прозорий
- правда
- us
- використання
- значення
- Цінності
- видимий
- хвилі
- Що
- Що таке
- який
- в той час як
- всі
- волі
- вітер
- цікаво
- слова
- Work
- б
- Неправильно
- Ти
- вашу
- зефірнет