How To Animate A Div On Hover
Transitioning border
for a hover state. Simple, correct? Y'all might exist unpleasantly surprised.
The Claiming
The challenge is simple: building a button with an expanding edge on hover.
This commodity volition focus on 18-carat CSS tricks that would be easy to drop into whatsoever projection without having to touch the DOM or utilize JavaScript. The methods covered here volition follow these rules
- Unmarried element (no helper divs, but psuedo-elements are allowed)
- CSS only (no JavaScript)
- Works for any size (not restricted to a specific width, height, or attribute ratio)
- Supports transparent backgrounds
- Smooth and performant transition
I proposed this challenge in the Animation at Work Slack and again on Twitter. Though at that place was no consensus on the all-time arroyo, I did receive some really clever ideas by some phenomenal developers.
Method 1: Animating border
The nigh straightforward fashion to animate a border is… well, past animative border
.
.border-button { edge: solid 5px #FC5185; transition: edge-width 0.6s linear; } .border-button:hover { border-width: 10px; }
See the Pen by Shaw (@shshaw) on CodePen.
Nice and uncomplicated, but at that place are some big performance issues.
Since border
takes upwardly infinite in the document'south layout, changing the border-width
will trigger layout. Nearby elements will shift around considering of the new border size, making browser reposition those elements every frame of the animation unless you set an explicit size on the button.
Equally if triggering layout wasn't bad plenty, the transition itself feels "stepped". I'll evidence why in the adjacent example.
Method 2: Amend edge
with outline
How can we change the border without triggering layout? By using outline
instead! You're probably almost familiar with outline
from removing it on :focus
styles (though you lot shouldn't), but outline
is an outer line that doesn't modify an element's size or position in the layout.
.border-push 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; }
See the Pen by Shaw (@shshaw) on CodePen.
A quick check in Dev Tools' Performance tab shows the outline
transition does non trigger layout. Regardless, the movement still seems stepped considering browsers are rounding the border-width
and outline-width
values so you don't get sub-pixel rendering between 5
and half dozen
or smooth transitions from 5.4
to v.5
.
See the Pen by Shaw (@shshaw) on CodePen.
Strangely, Safari often doesn't render the outline
transition and occasionally leaves crazy artifacts.
Method iii: Cut it with clip-path
Beginning 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 information technology down to the starting size */ border: solid 10px #FC5185; prune-path: polygon( calc(0% + 5px) calc(0% + 5px), /* acme left */ calc(100% - 5px) calc(0% + 5px), /* summit right */ calc(100% - 5px) calc(100% - 5px), /* bottom correct */ calc(0% + 5px) calc(100% - 5px) /* bottom left */ ); transition: clip-path 0.6s linear; } .edge-push button:hover { /* Clip-path spanning the unabridged box then it's no longer hiding the full-width border. */ clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
See the Pen by Shaw (@shshaw) on CodePen.
clip-path
technique is the smoothest and most performant method and so far, but does come with a few caveats. Rounding errors may cause a little unevenness, depending on the exact size. The edge also has to exist full size from the start, which may make verbal positioning tricky.
Unfortunately there's no IE/Edge back up nevertheless, 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 tin simulate a border using a clever combination of multiple linear-gradient
backgrounds properly sized. In total we have four separate gradients, 1 for each side. The background-position
and background-size
properties get each gradient in the right spot and the correct size, which can then be transitioned to make the border expand.
.border-button { background-repeat: no-repeat; /* background-size values will echo so we just demand to declare them one time */ groundwork-size: calc(100% - 10px) 5px, /* tiptop & bottom */ 5px calc(100% - 10px); /* right & left */ groundwork-position: 5px 5px, /* summit */ calc(100% - 5px) 5px, /* right */ 5px calc(100% - 5px), /* lesser */ 5px 5px; /* left */ /* Since we're sizing and positioning with the to a higher place properties, we just need to set up a unproblematic solid-color gradients for each side */ groundwork-epitome: 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-belongings: background-size, groundwork-position; } .border-push:hover { background-position: 0 0, 100% 0, 0 100%, 0 0; background-size: 100% 10px, 10px 100%, 100% 10px, 10px 100%; }
See the Pen by Shaw (@shshaw) on CodePen.
This method is quite hard to prepare and has quite a few cantankerous-browser differences. Firefox and Safari animate the false-border smoothly, exactly the upshot nosotros're looking for. Chrome's animation is jerky and fifty-fifty more stepped than the outline
and border
transitions. IE and Border decline to animate the groundwork
at all, but they do requite the proper border expansion effect.
Method v: False it with box-shadow
Hidden inside box-shadow
'due south spec is a quaternary value for spread-radius
. Set up all the other length values to 0px
and utilize the spread-radius to build your border
culling that, like outline
, won't bear upon layout.
.edge-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; }
Run across the Pen past Shaw (@shshaw) on CodePen.
The transition with box-shadow
is adequately performant and feels much smoother, except in Safari where it'due south snapping to whole-values during the transition like border
and outline
.
Pseudo-Elements
Several of these techniques can be modified to apply a pseudo-chemical element instead, simply pseudo-elements ended upward 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 assistance isolate the paint to a more than specific surface area. Equally I ran farther tests, box-shadow
was no longer causing paint in large areas of the certificate and the complication of the pseudo-element concluded up existence less performant. The change in pigment and performance may have been due to a Chrome update, so feel costless to test for yourself.
I also could not find a mode to utilize pseudo-elements in a manner that would allow for transform
based animation.
Why not transform: scale
?
You may be firing up Twitter to helpfully suggest using transform: scale
for this. Since transform
and opacity
are the best way properties to animate for functioning, why non apply 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; superlative: 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: calibration(ane,1); }
See the Pen by Shaw (@shshaw) on CodePen.
There are a few problems:
- The border will prove through a transparent button. I forced a background on the button to show how the border is hiding backside the button. If your design calls for buttons with a full background, then this could work.
- You can't scale the border to specific sizes. Since the push button's dimensions vary with the text, at that place's no style to animate the edge from exactly 5px to 10px using but CSS. In this example I've done some magic-numbers on the
scale
to get it to appear right, merely that won't exist universal. - The border animates unevenly considering the button'due south aspect ratio isn't 1:1. This normally means the left/right volition appear larger than the elevation/bottom until the animation completes. This may not be an upshot depending on how fast your transition is, the button's aspect ratio, and how big your border is.
If your push has set dimensions, Cher pointed out a clever way to calculate the verbal scales needed, though information technology may be discipline to some rounding errors.
Beyond CSS
If nosotros loosen our rules a bit, there are many interesting ways yous tin can breathing borders. Codrops consistently does outstanding work in this area, usually utilizing SVGs and JavaScript. The cease results are very satisfying, though they can be a bit complex to implement. Here are a few worth checking out:
- Artistic Buttons
- Button Styles Inspiration
- Blithe Checkboxes
- Distorted Push button Furnishings
- Progress Button Styles
Conclusion
At that place's more to borders than simply border
, but if you want to animate a border yous may have some problem. The methods covered here will help, though none of them are a perfect solution. Which you lot choose will depend on your projection'southward requirements, so I've laid out a comparing table to aid you decide.
Encounter the Pen past Shaw (@shshaw) on CodePen.
My recommendation would be to use box-shadow,
which has the best overall remainder of ease-of-implementation, animation effect, functioning and browser back up.
Exercise you have another way of creating an animated border? Peradventure a clever way to utilize transforms for moving a border? Comment below or reach me on Twitter to share your solution to the challenge.
Special cheers to Martin Pitt, Steve Gardner, Cher, Reinier Kaper, Joseph Rex, David Khourshid, and the Animation at Work customs.
Source: https://css-tricks.com/animating-border/
Posted by: suzukiwhourpel2001.blogspot.com
0 Response to "How To Animate A Div On Hover"
Post a Comment