У меня есть похожая идея, но реализованная по-другому и с небольшим количеством анимации. Я думаю, что это довольно практично и создает аккуратный эффект наведения, который вы можете использовать на чем-то вроде своего собственного аватара.
Видеть, что? Мы собираемся сделать анимацию масштабирования, в которой аватар, кажется, выпрыгивает прямо из круга, в котором он находится. Круто, правда? Не смотрите на код, а давайте вместе создадим эту анимацию шаг за шагом.
HTML: всего один элемент
Если вы еще не проверили код демо и вам интересно, сколько divs это займет, тогда остановитесь прямо здесь, потому что наша разметка не что иное, как один элемент изображения:
<img src="" alt="">
Да, один элемент! Сложной частью этого упражнения является использование наименьшего возможного количества кода. Если вы были за мной какое-то время вы должны привыкнуть к этому. Я изо всех сил стараюсь найти CSS-решения, которые можно реализовать с помощью наименьшего, наиболее удобного для сопровождения кода.
Я написал серия статей здесь, в CSS-Tricks, где я исследую различные эффекты наведения, используя одну и ту же разметку HTML, содержащую один элемент. Я подробно рассказываю о градиентах, маскировании, отсечении, контурах и даже методах компоновки. Я настоятельно рекомендую проверить их, потому что я буду повторно использовать многие приемы в этом посте.
Квадратный файл изображения с прозрачным фоном лучше всего подойдет для того, что мы делаем. Вот тот, который я использую, если вы хотите начать с него.
Я надеюсь увидеть много примеров того, как это возможно с использованием реальных изображений — поэтому, пожалуйста, поделитесь своим окончательным результатом в комментариях, когда вы закончите, чтобы мы могли создать коллекцию!
Прежде чем перейти к CSS, давайте сначала разберем эффект. Изображение увеличивается при наведении, поэтому мы обязательно воспользуемся transform: scale() там. За аватаром есть круг, и радиальный градиент должен помочь. Наконец, нам нужен способ создать границу в нижней части круга, которая создаст видимость аватара за кругом.
Пока ничего сложного, правда? Давайте двигаться дальше.
Круг
Мы сказали, что фон будет радиальным градиентом. Это прекрасно, потому что мы можем создавать резкие переходы между цветами радиального градиента, что создает впечатление, будто мы рисуем круг со сплошными линиями.
Обратите внимание на переменную CSS, --b, я использую там. Он представляет собой толщину «границы», которая на самом деле просто используется для определения жестких цветовых остановок для красной части радиального градиента.
Следующий шаг — поиграть с размером градиента при наведении. Круг должен сохранять свой размер по мере роста изображения. Поскольку мы применяем scale() преобразование, нам действительно нужно снижение размер круга, потому что в противном случае он увеличивается вместе с аватаром. Таким образом, пока изображение увеличивается, нам нужно, чтобы градиент уменьшался.
Начнем с определения переменной CSS, --f, который определяет «коэффициент масштабирования», и используйте его для установки размера круга. я использую 1 в качестве значения по умолчанию, так как это начальный масштаб для изображения и круга, из которого мы преобразуем.
Вот демонстрация, чтобы проиллюстрировать трюк. Наведите курсор, чтобы увидеть, что происходит за кулисами:
Я добавил третий цвет в radial-gradient чтобы лучше определить область градиента при наведении:
Теперь нам нужно расположить наш фон в центре круга и убедиться, что он занимает всю высоту. Мне нравится объявлять все прямо на background сокращенное свойство, поэтому мы можем добавить наше фоновое позиционирование и убедиться, что оно не повторяется, прикрепив эти значения сразу после radial-gradient():
Фон размещается в центре (50%), имеет ширину, равную calc(100%/var(--f)), и имеет высоту, равную 100%.
Ничто не масштабируется, когда --f равно 1 — опять наш первоначальный масштаб. При этом градиент занимает всю ширину контейнера. Когда мы увеличиваем --f, размер элемента увеличивается — благодаря scale() transform — и размер градиента уменьшается.
Вот что мы получаем, когда применяем все это к нашей демонстрации:
Мы приближаемся! У нас есть эффект переполнения вверху, но нам все еще нужно скрыть нижнюю часть изображения, чтобы оно выглядело так, как будто оно выходит из круга, а не находится перед ним. Это сложная часть всего этого дела, и это то, чем мы собираемся заняться дальше.
Нижняя граница
Сначала я попытался решить эту проблему с помощью border-bottom свойство, но мне не удалось найти способ сопоставить размер границы с размером круга. Вот лучшее, что я мог получить, и вы сразу видите, что это неправильно:
Фактическое решение состоит в том, чтобы использовать outline свойство. Да, outline, Не border. В предыдущая статья, я показываю как outline является мощным и позволяет нам создавать классные эффекты наведения. В сочетании с outline-offset, у нас есть именно то, что нам нужно для нашего эффекта.
Идея состоит в том, чтобы установить outline на изображении и отрегулируйте его смещение, чтобы создать нижнюю границу. Смещение будет зависеть от коэффициента масштабирования так же, как размер градиента.
Теперь у нас есть наша нижняя «граница» (на самом деле outline) в сочетании с «границей», созданной градиентом, чтобы создать полный круг. Нам все еще нужно скрыть части outline (сверху и по бокам), к которым мы скоро вернемся.
Вот наш код, включая еще пару переменных CSS, которые вы можете использовать для настройки размера изображения (--s) и цвет «границы» (--c):
Так как нам нужна круглая нижняя граница, мы добавили border-radius на нижней стороне, что позволяет outline чтобы соответствовать кривизне градиента.
Расчет, используемый на outline-offset намного проще, чем кажется. По умолчанию, outline нарисован внешнюю коробки элемента. А в нашем случае это нужно перекрытие элемент. Точнее, нам нужно, чтобы он следовал кругу, созданному градиентом.
Когда мы масштабируем элемент, мы видим пространство между кругом и краем. Не будем забывать, что идея состоит в том, чтобы сохранить окружность того же размера после выполнения преобразования масштаба, что оставляет нам пространство, которое мы будем использовать для определения смещения контура, как показано на рисунке выше.
Не забываем, что второй элемент масштабируется, поэтому наш результат тоже масштабируется… значит, нам нужно разделить результат на f чтобы получить реальное значение смещения:
Offset = ((f - 1) * S/2) / f = (1 - 1/f) * S/2
Мы добавляем отрицательный знак, так как нам нужно, чтобы контур шел снаружи внутрь:
Offset = (1/f - 1) * S/2
Вот краткая демонстрация, показывающая, как контур следует за градиентом:
Возможно, вы уже видите это, но нам все еще нужно, чтобы нижний контур перекрывал круг, а не позволял ему просачиваться через него. Мы можем сделать это, удалив размер границы из смещения:
В этом верхнем отступе нет особой логики. Идея состоит в том, чтобы контур не касался головы аватара. Я использовал размер элемента, чтобы определить, что пространство всегда имеет одну и ту же пропорцию.
Обратите внимание, что я добавил content-box значение для background:
Нам это нужно, потому что мы добавили отступы, и мы хотим, чтобы фон был установлен только в поле содержимого, поэтому мы должны явно указать фону остановиться на этом.
Добавление маски CSS в микс
Мы дошли до последней части! Все, что нам нужно сделать, это скрыть некоторые части, и все готово. Для этого будем опираться на mask свойство и, конечно же, градиенты.
Вот рисунок, чтобы проиллюстрировать, что нам нужно скрыть или что нам нужно показать, чтобы быть более точным.
Левое изображение — это то, что у нас есть на данный момент, а правое — то, что мы хотим. Зеленая часть иллюстрирует маску, которую мы должны применить к исходному изображению, чтобы получить окончательный результат.
Мы можем выделить две части нашей маски:
Круглая часть внизу, которая имеет тот же размер и кривизну, что и радиальный градиент, который мы использовали для создания круга позади аватара.
Прямоугольник вверху, покрывающий область внутри контура. Обратите внимание, что контур находится за пределами зеленой области вверху — это самая важная часть, поскольку она позволяет обрезать контур так, чтобы была видна только нижняя часть.
Давайте сломаем это mask свойство. Для начала обратите внимание, что аналогичный radial-gradient() из background собственность находится там. Я создал новую переменную, --_g, для общих частей, чтобы сделать вещи менее загроможденными.
Это создает прямоугольную часть маски. Его ширина равна ширине радиального градиента минус удвоенная толщина границы:
calc(100% / var(--f) - 2 * var(--b))
Высота прямоугольника равна половине, 50%, размера элемента.
Нам также нужен линейный градиент, размещенный в горизонтальном центре (50%) и смещение сверху на то же значение, что и смещение контура. Я создал еще одну переменную CSS, --_o, для смещения, которое мы ранее определили:
Одна из запутанных вещей здесь заключается в том, что нам нужен отрицательный смещение для контура (чтобы переместить его снаружи внутрь), но положительный смещение для градиента (для перемещения сверху вниз). Итак, если вам интересно, почему мы умножаем смещение, --_o, от -1, ну теперь вы знаете!
Вот демонстрация, иллюстрирующая конфигурацию градиента маски:
Наведите курсор на выше и посмотрите, как все движется вместе. В средней рамке показан слой маски, состоящий из двух градиентов. Представьте, что это видимая часть левого изображения, а конечный результат вы получите справа!
Подведение итогов
Уф, мы закончили! И мы не только получили плавную анимацию при наведении, но и сделали все это с помощью одного HTML-кода. <img> элемент. Только это и менее 20 строк хитрости CSS!
Конечно, мы полагались на некоторые маленькие хитрости и математические формулы, чтобы добиться такого сложного эффекта. Но мы точно знали, что делать, поскольку заранее определили нужные элементы.
Могли бы мы упростить CSS, если бы позволили себе больше HTML? Абсолютно. Но мы здесь, чтобы изучить новые приемы CSS! Это было хорошим упражнением для изучения CSS-градиентов, маскирования, outline поведение свойств, преобразования и многое другое. Если вы почувствовали себя потерянным в какой-то момент, обязательно загляните моя серия в котором используются одни и те же общие понятия. Иногда полезно увидеть больше примеров и вариантов использования, чтобы понять суть.
Я оставлю вам последнюю демонстрацию, в которой используются фотографии популярных разработчиков CSS. Не забудьте показать мне демо со своим изображением, чтобы я мог добавить его в коллекцию!
Причудливый эффект наведения для вашего аватара
Переиздано Платоном
Вы знаете такой эффект, когда чья-то голова просовывается в круг или отверстие? Знаменитая анимация Порки Свин, где он машет рукой на прощание, выскакивая из ряда красных колец, является прекрасным примером. Килиан Валкхоф на самом деле воссоздал это здесь, на CSS-Tricks, некоторое время назад..
У меня есть похожая идея, но реализованная по-другому и с небольшим количеством анимации. Я думаю, что это довольно практично и создает аккуратный эффект наведения, который вы можете использовать на чем-то вроде своего собственного аватара.
Видеть, что? Мы собираемся сделать анимацию масштабирования, в которой аватар, кажется, выпрыгивает прямо из круга, в котором он находится. Круто, правда? Не смотрите на код, а давайте вместе создадим эту анимацию шаг за шагом.
HTML: всего один элемент
Если вы еще не проверили код демо и вам интересно, сколько
div
s это займет, тогда остановитесь прямо здесь, потому что наша разметка не что иное, как один элемент изображения:Да, один элемент! Сложной частью этого упражнения является использование наименьшего возможного количества кода. Если вы были за мной какое-то время вы должны привыкнуть к этому. Я изо всех сил стараюсь найти CSS-решения, которые можно реализовать с помощью наименьшего, наиболее удобного для сопровождения кода.
Я написал серия статей здесь, в CSS-Tricks, где я исследую различные эффекты наведения, используя одну и ту же разметку HTML, содержащую один элемент. Я подробно рассказываю о градиентах, маскировании, отсечении, контурах и даже методах компоновки. Я настоятельно рекомендую проверить их, потому что я буду повторно использовать многие приемы в этом посте.
Квадратный файл изображения с прозрачным фоном лучше всего подойдет для того, что мы делаем. Вот тот, который я использую, если вы хотите начать с него.
Я надеюсь увидеть много примеров того, как это возможно с использованием реальных изображений — поэтому, пожалуйста, поделитесь своим окончательным результатом в комментариях, когда вы закончите, чтобы мы могли создать коллекцию!
Прежде чем перейти к CSS, давайте сначала разберем эффект. Изображение увеличивается при наведении, поэтому мы обязательно воспользуемся
transform: scale()
там. За аватаром есть круг, и радиальный градиент должен помочь. Наконец, нам нужен способ создать границу в нижней части круга, которая создаст видимость аватара за кругом.Давай приступим к работе!
Эффект масштаба
Начнем с добавления преобразования:
Пока ничего сложного, правда? Давайте двигаться дальше.
Круг
Мы сказали, что фон будет радиальным градиентом. Это прекрасно, потому что мы можем создавать резкие переходы между цветами радиального градиента, что создает впечатление, будто мы рисуем круг со сплошными линиями.
Обратите внимание на переменную CSS,
--b
, я использую там. Он представляет собой толщину «границы», которая на самом деле просто используется для определения жестких цветовых остановок для красной части радиального градиента.Следующий шаг — поиграть с размером градиента при наведении. Круг должен сохранять свой размер по мере роста изображения. Поскольку мы применяем
scale()
преобразование, нам действительно нужно снижение размер круга, потому что в противном случае он увеличивается вместе с аватаром. Таким образом, пока изображение увеличивается, нам нужно, чтобы градиент уменьшался.Начнем с определения переменной CSS,
--f
, который определяет «коэффициент масштабирования», и используйте его для установки размера круга. я использую1
в качестве значения по умолчанию, так как это начальный масштаб для изображения и круга, из которого мы преобразуем.Вот демонстрация, чтобы проиллюстрировать трюк. Наведите курсор, чтобы увидеть, что происходит за кулисами:
Я добавил третий цвет в
radial-gradient
чтобы лучше определить область градиента при наведении:Теперь нам нужно расположить наш фон в центре круга и убедиться, что он занимает всю высоту. Мне нравится объявлять все прямо на
background
сокращенное свойство, поэтому мы можем добавить наше фоновое позиционирование и убедиться, что оно не повторяется, прикрепив эти значения сразу послеradial-gradient()
:Фон размещается в центре (
50%
), имеет ширину, равнуюcalc(100%/var(--f))
, и имеет высоту, равную100%
.Ничто не масштабируется, когда
--f
равно1
— опять наш первоначальный масштаб. При этом градиент занимает всю ширину контейнера. Когда мы увеличиваем--f
, размер элемента увеличивается — благодаряscale()
transform — и размер градиента уменьшается.Вот что мы получаем, когда применяем все это к нашей демонстрации:
Мы приближаемся! У нас есть эффект переполнения вверху, но нам все еще нужно скрыть нижнюю часть изображения, чтобы оно выглядело так, как будто оно выходит из круга, а не находится перед ним. Это сложная часть всего этого дела, и это то, чем мы собираемся заняться дальше.
Нижняя граница
Сначала я попытался решить эту проблему с помощью
border-bottom
свойство, но мне не удалось найти способ сопоставить размер границы с размером круга. Вот лучшее, что я мог получить, и вы сразу видите, что это неправильно:Фактическое решение состоит в том, чтобы использовать
outline
свойство. Да,outline
, Неborder
. В предыдущая статья, я показываю какoutline
является мощным и позволяет нам создавать классные эффекты наведения. В сочетании сoutline-offset
, у нас есть именно то, что нам нужно для нашего эффекта.Идея состоит в том, чтобы установить
outline
на изображении и отрегулируйте его смещение, чтобы создать нижнюю границу. Смещение будет зависеть от коэффициента масштабирования так же, как размер градиента.Теперь у нас есть наша нижняя «граница» (на самом деле
outline
) в сочетании с «границей», созданной градиентом, чтобы создать полный круг. Нам все еще нужно скрыть частиoutline
(сверху и по бокам), к которым мы скоро вернемся.Вот наш код, включая еще пару переменных CSS, которые вы можете использовать для настройки размера изображения (
--s
) и цвет «границы» (--c
):Так как нам нужна круглая нижняя граница, мы добавили
border-radius
на нижней стороне, что позволяетoutline
чтобы соответствовать кривизне градиента.Расчет, используемый на
outline-offset
намного проще, чем кажется. По умолчанию,outline
нарисован внешнюю коробки элемента. А в нашем случае это нужно перекрытие элемент. Точнее, нам нужно, чтобы он следовал кругу, созданному градиентом.Когда мы масштабируем элемент, мы видим пространство между кругом и краем. Не будем забывать, что идея состоит в том, чтобы сохранить окружность того же размера после выполнения преобразования масштаба, что оставляет нам пространство, которое мы будем использовать для определения смещения контура, как показано на рисунке выше.
Не забываем, что второй элемент масштабируется, поэтому наш результат тоже масштабируется… значит, нам нужно разделить результат на
f
чтобы получить реальное значение смещения:Мы добавляем отрицательный знак, так как нам нужно, чтобы контур шел снаружи внутрь:
Вот краткая демонстрация, показывающая, как контур следует за градиентом:
Возможно, вы уже видите это, но нам все еще нужно, чтобы нижний контур перекрывал круг, а не позволял ему просачиваться через него. Мы можем сделать это, удалив размер границы из смещения:
Теперь нам нужно найти, как удалить верхнюю часть из контура. Другими словами, нам нужна только нижняя часть изображения.
outline
.Во-первых, давайте добавим пространство вверху с отступом, чтобы избежать перекрытия вверху:
В этом верхнем отступе нет особой логики. Идея состоит в том, чтобы контур не касался головы аватара. Я использовал размер элемента, чтобы определить, что пространство всегда имеет одну и ту же пропорцию.
Обратите внимание, что я добавил
content-box
значение дляbackground
:Нам это нужно, потому что мы добавили отступы, и мы хотим, чтобы фон был установлен только в поле содержимого, поэтому мы должны явно указать фону остановиться на этом.
Добавление маски CSS в микс
Мы дошли до последней части! Все, что нам нужно сделать, это скрыть некоторые части, и все готово. Для этого будем опираться на
mask
свойство и, конечно же, градиенты.Вот рисунок, чтобы проиллюстрировать, что нам нужно скрыть или что нам нужно показать, чтобы быть более точным.
Левое изображение — это то, что у нас есть на данный момент, а правое — то, что мы хотим. Зеленая часть иллюстрирует маску, которую мы должны применить к исходному изображению, чтобы получить окончательный результат.
Мы можем выделить две части нашей маски:
Вот наш окончательный CSS:
Давайте сломаем это
mask
свойство. Для начала обратите внимание, что аналогичныйradial-gradient()
изbackground
собственность находится там. Я создал новую переменную,--_g
, для общих частей, чтобы сделать вещи менее загроможденными.Далее есть
linear-gradient()
там же:Это создает прямоугольную часть маски. Его ширина равна ширине радиального градиента минус удвоенная толщина границы:
Высота прямоугольника равна половине,
50%
, размера элемента.Нам также нужен линейный градиент, размещенный в горизонтальном центре (
50%
) и смещение сверху на то же значение, что и смещение контура. Я создал еще одну переменную CSS,--_o
, для смещения, которое мы ранее определили:Одна из запутанных вещей здесь заключается в том, что нам нужен отрицательный смещение для контура (чтобы переместить его снаружи внутрь), но положительный смещение для градиента (для перемещения сверху вниз). Итак, если вам интересно, почему мы умножаем смещение,
--_o
, от-1
, ну теперь вы знаете!Вот демонстрация, иллюстрирующая конфигурацию градиента маски:
Наведите курсор на выше и посмотрите, как все движется вместе. В средней рамке показан слой маски, состоящий из двух градиентов. Представьте, что это видимая часть левого изображения, а конечный результат вы получите справа!
Подведение итогов
Уф, мы закончили! И мы не только получили плавную анимацию при наведении, но и сделали все это с помощью одного HTML-кода.
<img>
элемент. Только это и менее 20 строк хитрости CSS!Конечно, мы полагались на некоторые маленькие хитрости и математические формулы, чтобы добиться такого сложного эффекта. Но мы точно знали, что делать, поскольку заранее определили нужные элементы.
Могли бы мы упростить CSS, если бы позволили себе больше HTML? Абсолютно. Но мы здесь, чтобы изучить новые приемы CSS! Это было хорошим упражнением для изучения CSS-градиентов, маскирования,
outline
поведение свойств, преобразования и многое другое. Если вы почувствовали себя потерянным в какой-то момент, обязательно загляните моя серия в котором используются одни и те же общие понятия. Иногда полезно увидеть больше примеров и вариантов использования, чтобы понять суть.Я оставлю вам последнюю демонстрацию, в которой используются фотографии популярных разработчиков CSS. Не забудьте показать мне демо со своим изображением, чтобы я мог добавить его в коллекцию!
🔴 Биткойн вошел в десятку лучших | На этой неделе в криптовалюте — 10 марта 4 г.
Ben & Jerry’s asking public to send letters to governors asking for marijuana clemency – Medical Marijuana Program Connection
Moment Factory использует технологии нового поколения Sphere для переосмысления концертного опыта
Ландо Норрис забрал поул в спринте Гран-при Китая Формулы 1 у Хэмилтона – Autoblog
«Португалия уже начала переход на F-35», - заявил глава ВВС Португалии
Криптовалютный трейдер осужден за мошенничество за использование рынков манго на сумму 110 миллионов долларов – CryptoInfoNet
Пионер биткойнов Хэл Финни посмертно получил новую награду, названную в его честь
Вебинар RWDG: Влияние управления метаданными на управление данными – DATAVERSITY