4 способа анимировать текст ссылки при наведении

Css
article image

Давайте сделаем CSS-эффект замены цвета ссылки при наведении, но что бы он менялся не резко, как обычно, а плавно.

Есть 4 способа добиться желаемого эффекта. Разберем их все, учитывая такие факторы как удобство, производительность и поддержка браузера

Сделам это!

Способ 1: Использование background-clip: text

На момент написания статьи свойство background-clip: text является экспериментальным и не поддерживается в Internet Explorer 11 и ниже.

Разметка состоит всего лишь из одного тега <a> создающего ссылку.

1
<a href="#">Наведи на меня</a>

Можем приступить к стилизации. Свойство overflow: hidden; обзерает любой контент выходящий за границы ссылки при наведении и не только:

1
2
3
4
5
6
7
8
a {
  position: relative;
  display: inline-block;
  font-size: 2em;
  font-weight: 800;
  color: royalblue;
  overflow: hidden;
}

Мы должны задать градиент с резким переходом на 50% от цвета, который будет при наведении к первоначальному цвету ссылки.

1
2
3
a {
  background: linear-gradient(to right, midnightblue, midnightblue 50%, royalblue 50%);
}

Давайте обрежем градиент, оставив текст при помощи background-clip. Мы так же используем свойства background-size и background-position для отображения начального цвета:

1
2
3
4
5
6
7
a {
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-size: 200% 100%;
  background-position: 100%;
}

И наконец, добавим свойство transition для плавного перехода и background-position для псевдокласса :hover для изменения ссылки слева направо.

1
2
3
4
5
6
a {
  transition: background-position 275ms ease;
}
a:hover {
  background-position: 0 100%;
}

Необходимо отметить, что в Chrome и Safari использование такого метода приведет к тому, что подчеркивание текста и тень будут обрезаться.

Способ 2: Использование ширины и высоты

Этот метод использует data-attribute, содержащий тот же текст, что и ссылка и установку ширины (для заполнения тексте с лева напрово или наоборт) или высоты (для зполнения сверху вниз или снизу вверх) от 0 до 100% при наведении.

Первоначальная разметка:

1
<a href="#" data-content="Наведи на меня">Наведи на меня</a>

CSS тот же, что и в предыдущем способе, но без свойства background. Подчеркиевание будет работать корректно:

1
2
3
4
5
6
7
8
9
a {
  position: relative;
  display: inline-block;
  font-size: 2em;
  color: royalblue;
  font-weight: 800;
  text-decoration: underline;
  overflow: hidden;
}

Контент из data-content будет расположен поверх текста ссылки. Для отображения содежимого нашего атрибута в свойстве content псевдоэлемента ::before, мы используем функцию attr():

1
2
3
4
5
6
7
8
9
10
a::before {
  position: absolute;
  content: attr(data-content); /* Выведет содержимое data-content */
  top: 0;
  left: 0;
  color: midnightblue;
  text-decoration: underline;
  overflow: hidden;
  transition: width 275ms ease;
}

Что бы текст не переносился на другую строку, применим свойство white-space: nowrap. Так же для изменения цвета заливки, задаем цвет для псевдоэлемента ::before и начальную шириную, равную 0%:

1
2
3
4
5
a::before {
  /* Same as before */
  width: 0;
  white-space: nowrap;
}

Для самого же эффекта, применим свойство width со значением 100% для ::before при наведении.

Хотя этот способ и выполняет поставленную задачу, анимировать такие свойства как ширина и высота, не является хорошей практикой и не дает максимальной производительности анимации в 60fps.

Применить разные стили подчеркивания можно с помощью свойства clip-path. Ниже приведены несколько таких примеров.

See the Pen Link Fill on Hover by Katherine Kato (@kathykato) on CodePen.

Способ 3: Использование clip-path

Для этого способа мы нам пригодится CSS-свойство clip-path с многоугольной формой.

Рзаметка остается прежней. Мы так же будет использовать псевдоэлемент ::before, но стили будут другими:

1
2
3
4
5
6
7
8
a::before {
  position: absolute;
  content: attr(data-content);
  color: midnightblue;
  text-decoration: underline;
  clip-path: polygon(0 0, 0 0, 0% 100%, 0 100%);
  transition: clip-path 275ms ease;
}

В отличии от предыдущего метода, text-decoration применим к псевдоэлементу ::before, что бы при наведении подчеркивание так же менялось.

Теперь давайте обратим внимание на CSS-свойсто clip-path:

1
clip-path: polygon(0 0, 0 0, 0% 100%, 0 100%);

Коодританы полигона clip-path опредеяем в процентах:

0 0 - верхняя левая точка

0 0 - верхняя правая точка

100% 0 - нижняя правая точка

0 100% - нижняя левая точка

Направление эффекта заполнения можно изменить, изменив коодинаты точек. Далее, когда мы уже имеем представление о координатах полигона, заставим его расширяться при наведении:

1
2
3
a:hover::before {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

See the Pen Hover Text Fill Effects with CSS (clip-path) by Katherine Kato (@kathykato) on CodePen.

Данный способ работает очень хорошо, но стоит обратить внимание на поддержку этого свойства браузерами. Использовать свойство clip-path на много лучше, чем альтернативу основанную на значениях ширины и высоты.

Способ 4: Использование transform

Данный метод подразумевает маскировку с помощью элеметна <span>. Поскольку мы будет дублировать контент в двух элементах, применим атрибут aria-hidden="true" для того, что бы на специальных программах для чтения, текст не читался дважды:

1
<a href="#"><span data-content="Наведи на меня" aria-hidden="true"></span>Наведи на меня</a>

Стили для элемента span будут содержать сдвиг, что бы переход начинался слева.

1
2
3
4
5
6
7
8
span {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  transform: translateX(-100%);
  transition: transform 275ms ease;
}

Далее нам нужно заставить span двигаться, как показано ниже:

Для этого применим CSS-функцию translateX() со значением 0:

1
2
3
a:hover span {
  transform: translateX(0);
}

Нам так же необходим псевдоэлемент ::before для элемента <span> и атрибут data-content, использованный ранее. Установим позицию по оси X в 100%

1
2
3
4
5
6
7
8
span::before { 
  display: inline-block;
  content: attr(data-content);
  color: midnightblue;
  transform: translateX(100%);
  transition: transform 275ms ease;
  text-decoration: underline;
}

Как и у элемента <span>, положение псевдоэлемента ::before будет установлено в translateX(0):

1
2
3
a:hover span::before {
  transform: translateX(0);
}

See the Pen Hover Text Fill Effects with CSS (transform) by Katherine Kato (@kathykato) on CodePen.

Не смотря на то, что этот способ является наиболее кроссбраузерным, в нем больше кода, чем в остальных. Тем не менее анимирование свойств transform благоприятнее сказывыается на производительности, потому как не делает перерисовок и обеспечивает плавность переходов.

В качестве итога

Мы рассмотрели 4 разных подхода для получения одного эффекта, который добаляет ссылкам некой интерактивности.

Источник: https://css-tricks.com/4-ways-to-animate-the-color-of-a-text-link-on-hover/