Анимация border в CSS

Анимация border в CSS

От автора: как делается анимация border CSS по состоянию hover? Просто, так ведь? Вы удивитесь. Задача проста – создать кнопку с расширяющейся рамкой при наведении мыши. В сегодняшней статье обсудим реальные CSS советы, которые легко внедрить в любой проект без вмешательства в DOM и подключения JS. Описываемые методы следуют следующим правилам.

Один элемент (без вспомогательных div, псевдоэлементы использовать можно)

Только CSS (без JS)

Работа при любом размере (без ограничения по ширине, высоте и соотношению сторон)

Поддержка прозрачных фонов

Практический курс по верстке адаптивного лендинга с нуля!

Научитесь с нуля верстать адаптивные лендинги на HTML5 и CSS3 за ближайшие 6 дней

Узнать подробнее

Плавный и быстрый переход

Метод 1: анимация border

Самый простой способ анимировать рамку… это анимировать свойство border.

.border-button {
  border: solid 5px #FC5185;
  transition: border-width 0.6s linear;
}

.border-button:hover { border-width: 10px; }

Красиво и просто, но производительность сильно хромает.

Так как border занимает место в макете документа, то изменение border-width вызовет изменение макета. Окружающие элементы сдвинутся от элемента из-за нового размера рамки, что заставляет браузер заново вычислять позиции элементов каждый кадр анимации, если у кнопки не заданы явные размеры.

Перестройка макета не самое плохое, ведь плавный переход «отрывистый». В следующем примере я покажу вам это.

Метод 2: улучшенный border с outline

Как изменить рамку без перестройки макета? С помощью outline! Скорее всего, вы знакомы с outline (удаляете outline по :focus (не стоит этого делать)). Однако outline это внешняя линия, не меняющая размеры и положение элементов в макете.

.border-button {
  outline: solid 5px #FC5185;
  transition: outline 0.6s linear;
  margin: 0.5em; /* Increased margin since the outline expands outside the element */
}

.border-button:hover { outline-width: 10px; }

Если заглянуть в панель разработчика в браузере на вкладку Performance, можно увидеть, что outline не вызывает перестройку макета. Тем не менее, движения все еще выглядят отрывистыми, так как браузеры округляют значения border-width и outline-width, чтобы не было рендера меньше пикселя (между 5 и 6) и плавных переходов между 5.4 и 5.5.

Странно, но Safari часто не рендерит переход outline и оставляет непонятные артифакты.

Анимация border в CSS

Метод 3: кадрирование через clip-path

Steve Gardner создал этот метод. Метод использует clip-path и calc для обрезания рамки вовнутрь. При наведении мыши мы можем показывать полную ширину рамки.

.border-button { 
  /* Full width border and a clip-path visually cutting it down to the starting size */
  border: solid 10px #FC5185; 
  clip-path: polygon( 
 calc(0% + 5px) calc(0% + 5px), /* top left */
 calc(100% - 5px) calc(0% + 5px), /* top right */
 calc(100% - 5px) calc(100% - 5px), /* bottom right */
 calc(0% + 5px) calc(100% - 5px) /* bottom left */
  );
  transition: clip-path 0.6s linear;
}

.border-button:hover {
  /* Clip-path spanning the entire box so it's no longer hiding the full-width border. */
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

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

К сожалению, в IE/Edge до сих пор поддержки нет, однако она в разработке. Вы можете и обязаны поддержать команду Microsoft, проголосовав за добавление masks/clip-path.

Практический курс по верстке адаптивного лендинга с нуля!

Научитесь с нуля верстать адаптивные лендинги на HTML5 и CSS3 за ближайшие 6 дней

Узнать подробнее

Метод 4: фон linear-gradient

Рамку можно имитировать с помощью хитрой комбинации нескольких фонов linear-gradient с правильными размерами. Необходимо 4 отдельных градиента, по одному на сторону. Свойства background-position и background-size устанавливают все градиенты в правильное место и размеры, а их уже можно плавно менять и расширять рамку.

.border-button {
  background-repeat: no-repeat;
 
  /* background-size values will repeat so we only need to declare them once */
  background-size: 
 calc(100% - 10px) 5px, /* top & bottom */
 5px calc(100% - 10px); /* right & left */
 
  background-position: 
 5px 5px, /* top */
 calc(100% - 5px) 5px, /* right */
 5px calc(100% - 5px), /* bottom */
 5px 5px; /* left */
 
  /* Since we're sizing and positioning with the above properties, we only need to set up a simple solid-color gradients for each side */
  background-image: 
 linear-gradient(0deg, #FC5185, #FC5185),
 linear-gradient(0deg, #FC5185, #FC5185),
 linear-gradient(0deg, #FC5185, #FC5185),
 linear-gradient(0deg, #FC5185, #FC5185);
 
  transition: all 0.6s linear;
  transition-property: background-size, background-position;
}

.border-button:hover {
  background-position: 0 0, 100% 0, 0 100%, 0 0;
  background-size: 100% 10px, 10px 100%, 100% 10px, 10px 100%;
}

Метод немного сложный и немного различается в браузерах. Firefox и Safari плавно анимируют faux-border, что нам и нужно. В Chrome анимация дерганая и еще более отрывистая чем в outline и border. IE и Edge вообще отказываются анимировать background, зато эти браузеры правильно задают размеры рамки.

Метод 5: имитация через box-shadow

В спецификации box-shadow скрыто четвертое значение spread-radius. Установите все остальные значения в 0px и создайте рамку через spread-radius. Свойство, как и outline, не влияет на макет.

.border-button {
  box-shadow: 0px 0px 0px 5px #FC5185;
  transition: box-shadow 0.6s linear;
  margin: 0.5em; /* Increased margin since the box-shado expands outside the element, like outline */
}

.border-button:hover { box-shadow: 0px 0px 0px 10px #FC5185; }

Переход box-shadow довольно быстрый и намного плавнее. Исключение Safari – браузер привязывается к целым значениям во время переходов свойств border и outline.

Псевдоэлементы

Несколько техник можно изменить под псевдо-элементы, однако псевдо-элементы вызывают проблемы с производительностью.

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

Я также не нашел способа, как с помощью псевдоэлементов использовать transform анимацию.

А почему не transform: scale?

Можете обратиться в Twitter и предложить transform: scale. Свойства transform и opacity лучше всего анимируются по скорости, так почему не использовать псевдоэлемент и менять размер рамки?

.border-button {
  position: relative;
  margin: 0.5em;
  border: solid 5px transparent;
  background: #3E4377;
}

.border-button:after {
  content: '';
  display: block;
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  border: solid 10px #FC5185;
  margin: -15px;
  z-index: -1;
  transition: transform 0.6s linear;
  transform: scale(0.97, 0.93);
}

.border-button:hover::after { transform: scale(1,1); }

Есть несколько проблем:

Рамка будет видна через прозрачную кнопку. Я специально убрал фон кнопки, чтобы показать, как рамка прячется под кнопкой. Если в вашем дизайне кнопки с фоном, то все будет нормально.

Можно масштабировать рамку до определенного размера. Размеры кнопки могут меняться в зависимости от текста, поэтому нет четкого способа анимировать рамку от 5px до 10px через CSS. В этом примере я добавил немного магии в scale, но пример не универсален.

Рамка анимируется неровно из-за того, что соотношение сторон у кнопки не 1:1. То есть left/right будут больше, чем top/bottom, пока анимация не завершится. Проблема может быть не заметна на большой скорости анимации, правильном соотношении сторон кнопки и размерах рамки.

Если у вашей кнопки заданы размеры, Cher нашла умный способ вычисления точного масштаба. Однако могут возникнуть некоторые ошибки при округлении.

Заключение

Рамка это не просто border. Если вы захотели анимировать рамку, у вас может возникнуть несколько проблем. Описанные здесь методы помогут сделать это, но они не идеальны. Ваш выбор зависит от требований проекта. Я составил таблицу сравнения, чтобы помочь вам с выбором.

Я рекомендую использовать box-shadow – лучшая смесь простоты, эффекта анимации, скорости и поддержки.

Автор: Stephen Shaw

Источник: https://css-tricks.com/

Редакция: Команда webformyself.

Практический курс по верстке адаптивного лендинга с нуля!

Научитесь с нуля верстать адаптивные лендинги на HTML5 и CSS3 за ближайшие 6 дней

Узнать подробнее

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree