Изменить начертание шрифта при наведении без сдвига соседних элементов

Часто в дизайне активный элемент навигации (или при наведении) выделяют другим начертанием шрифта, например bold. В таком случае, при смене начертания, элемент становится шире и занимает больше пространства, чем раньше, при этом соседние элементы сдвигаются на некоторое расстояние, что является некорректным поведением

В данной статье покажу приём, который позволит исправить такое поведение

Пример некорректного поведения

Посмотрим пример, в котором попытаемся изменить начертание шрифта на bold при наведении

<div class="nav__ul">
  <ul>
    <li><a href="">Home</a></li>
    <li><a href="">About</a></li>
    <li><a href="">Delivery ECO</a></li>
    <li><a href="">Contacts</a></li>
  </ul>
</div>
.nav__ul ul {
  padding: 0;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  list-style: none;
  flex-wrap: wrap;
}
.nav__ul ul li a {
  color: #8093f1;
  font-size: 24px;
  text-transform: uppercase;
  position: relative;
  white-space: nowrap;
  text-decoration: none;
  font-weight: 300;
  transition: 0.24s;
}
.nav__ul ul li a:hover {
  color: #8093f1;
  font-weight: 900;
}


В результате у нас получается следующее:


При наведении соседние элементы смещаются

Посмотрим ниже, как это исправить



Исправляем некорректное поведение

Для исправления данной проблемы, мы будем использовать data атрибуты для ссылок и псевдоэлемент :after со свойством content: attr();

Для каждой ссылки добавим data атрибут data-title с соответствующим ссылке значением

<div class="nav__ul">
  <ul>
    <li><a href="" data-title="Home">Home</a></li>
    <li><a href="" data-title="About">About</a></li>
    <li><a href="" data-title="Delivery ECO">Delivery ECO</a></li>
    <li><a href="" data-title="Contacts">Contacts</a></li>
  </ul>
</div>


Псевдоэлемент :after, при помощи свойства content: attr(data-title); берёт значение из data атрибута ссылки data-title

Чтобы псевдоэлемент со значением data атрибута располагался точно над элементом ссылки, используем абсолютное позиционирование и display: flex; с соответствующими свойствами для центрирования

Стилизуем псевдоэлемент :after, и назначаем поведение при наведении :hover - при наведении на ссылку текст самой ссылки становится прозрачным, а текст псевдоэлемента заданного цвета

.nav__ul ul {
  padding: 0;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  list-style: none;
  flex-wrap: wrap;
}
.nav__ul ul li a {
  color: #8093f1;
  font-size: 24px;
  text-transform: uppercase;
  position: relative;
  white-space: nowrap;
  text-decoration: none;
  font-weight: 300;
  transition: 0.24s;
}
.nav__ul ul li a:after {
  content: attr(data-title);
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: center;
  text-align: center;
  align-items: center;
  color: transparent;
  font-weight: 900;
  transition: 0.24s;
  transform: scale(0.9);
  transform-origin: center center;
}
.nav__ul ul li a:hover {
  color: transparent;
}
.nav__ul ul li a:hover:after {
  color: #8093f1;
  transform: scale(1);
}


Посмотрим на текущий результат:


Теперь при наведении на элемент, соседние элементы не сдвигаются

С помощью данного приёма можно также добиваться различных интересных визуальных эффектов при наведении



Итоги

Надеюсь, эта небольшая статья сэкономит вам некоторое время, если вы столкнётесь с такой ситуацией

Буду рад, если статья оказалась полезной

Спасибо за ваше внимание и уделённое время!