При наведении бордер css

Animating Border

I proposed this challenge in the Animation at Work Slack and again on Twitter. Though there was no consensus on the best approach, I did receive some really clever ideas by some phenomenal developers.

Method 1: Animating border

The most straightforward way to animate a border is… well, by animating border .

.border-button < border: solid 5px #FC5185; transition: border-width 0.6s linear; >.border-button:hover

Nice and simple, but there are some big performance issues.

Since border takes up space in the document’s layout, changing the border-width will trigger layout. Nearby elements will shift around because of the new border size, making browser reposition those elements every frame of the animation unless you set an explicit size on the button.

As if triggering layout wasn’t bad enough, the transition itself feels “stepped”. I’ll show why in the next example.

Method 2: Better border with outline

How can we change the border without triggering layout? By using outline instead! You’re probably most familiar with outline from removing it on :focus styles (though you shouldn’t), but outline is an outer line that doesn’t change an element’s size or position in the layout.

.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

A quick check in Dev Tools’ Performance tab shows the outline transition does not trigger layout. Regardless, the movement still seems stepped because browsers are rounding the border-width and outline-width values so you don’t get sub-pixel rendering between 5 and 6 or smooth transitions from 5.4 to 5.5 .

Strangely, Safari often doesn’t render the outline transition and occasionally leaves crazy artifacts.

border artifact in safari

Method 3: Cut it with clip-path

First implemented by Steve Gardner, this method uses clip-path with calc to trim the border down so on hover we can transition to reveal the full border.

.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 technique is the smoothest and most performant method so far, but does come with a few caveats. Rounding errors may cause a little unevenness, depending on the exact size. The border also has to be full size from the start, which may make exact positioning tricky.

Unfortunately there’s no IE/Edge support yet, though it seems to be in development. You can and should encourage Microsoft’s team to implement those features by voting for masks/clip-path to be added.

Method 4: linear-gradient background

We can simulate a border using a clever combination of multiple linear-gradient backgrounds properly sized. In total we have four separate gradients, one for each side. The background-position and background-size properties get each gradient in the right spot and the right size, which can then be transitioned to make the border expand.

.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

This method is quite difficult to set up and has quite a few cross-browser differences. Firefox and Safari animate the faux-border smoothly, exactly the effect we’re looking for. Chrome’s animation is jerky and even more stepped than the outline and border transitions. IE and Edge refuse to animate the background at all, but they do give the proper border expansion effect.

Method 5: Fake it with box-shadow

Hidden within box-shadow ‘s spec is a fourth value for spread-radius . Set all the other length values to 0px and use the spread-radius to build your border alternative that, like outline , won’t affect layout.

.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

The transition with box-shadow is adequately performant and feels much smoother, except in Safari where it’s snapping to whole-values during the transition like border and outline .

Several of these techniques can be modified to use a pseudo-element instead, but pseudo-elements ended up causing some additional performance issues in my tests.

For the box-shadow method, the transition occasionally triggered paint in a much larger area than necessary. Reinier Kaper pointed out that a pseudo-element can help isolate the paint to a more specific area. As I ran further tests, box-shadow was no longer causing paint in large areas of the document and the complication of the pseudo-element ended up being less performant. The change in paint and performance may have been due to a Chrome update, so feel free to test for yourself.

I also could not find a way to utilize pseudo-elements in a way that would allow for transform based animation.

You may be firing up Twitter to helpfully suggest using transform: scale for this. Since transform and opacity are the best style properties to animate for performance, why not use a pseudo-element and have the border scale up & down?

.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
  1. The border will show through a transparent button. I forced a background on the button to show how the border is hiding behind the button. If your design calls for buttons with a full background, then this could work.
  2. You can’t scale the border to specific sizes. Since the button’s dimensions vary with the text, there’s no way to animate the border from exactly 5px to 10px using only CSS. In this example I’ve done some magic-numbers on the scale to get it to appear right, but that won’t be universal.
  3. The border animates unevenly because the button’s aspect ratio isn’t 1:1. This usually means the left/right will appear larger than the top/bottom until the animation completes. This may not be an issue depending on how fast your transition is, the button’s aspect ratio, and how big your border is.

If your button has set dimensions, Cher pointed out a clever way to calculate the exact scales needed, though it may be subject to some rounding errors.

If we loosen our rules a bit, there are many interesting ways you can animate borders. Codrops consistently does outstanding work in this area, usually utilizing SVGs and JavaScript. The end results are very satisfying, though they can be a bit complex to implement. Here are a few worth checking out:

There’s more to borders than simply border , but if you want to animate a border you may have some trouble. The methods covered here will help, though none of them are a perfect solution. Which you choose will depend on your project’s requirements, so I’ve laid out a comparison table to help you decide.

My recommendation would be to use box-shadow, which has the best overall balance of ease-of-implementation, animation effect, performance and browser support.

Do you have another way of creating an animated border? Perhaps a clever way to utilize transforms for moving a border? Comment below or reach me on Twitter to share your solution to the challenge.

Источник

Анимация border в CSS

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

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

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

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

Онлайн курс по JavaScript

Научитесь создавать приложения со сложными интерфейсами

Это основной язык для современной веб-разработки — почти 100% сайтов работает на JavaScript. Освойте его с нуля всего за 4 месяца, и вы сможете зарабатывать от 70 000 рублей.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

/* Since we’re sizing and positioning with the above properties, we only need to set up a simple solid-color gradients for each side */

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

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

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

margin : 0.5em ; /* Increased margin since the box-shado expands outside the element, like outline */

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

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

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

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

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

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

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

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

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

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

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

Заключение

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

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

Автор: Stephen Shaw

Онлайн курс по JavaScript

Научитесь создавать приложения со сложными интерфейсами

Это основной язык для современной веб-разработки — почти 100% сайтов работает на JavaScript. Освойте его с нуля всего за 4 месяца, и вы сможете зарабатывать от 70 000 рублей.

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

Источник

Читайте также:  Python argparse list of values
Оцените статью