Html css hover transition

An Interactive Guide to CSS Transitions

The world of web animations has become a sprawling jungle of tools and technologies. Libraries like GSAP and Framer Motion and React Spring have sprung up to help us add motion to the DOM.

The most fundamental and critical piece, though, is the humble CSS transition. It’s the first animation tool that most front-end devs learn, and it’s a workhorse. Even the most grizzled, weathered animation veterans still reach for this tool often.

There’s a surprising amount of depth to this topic. In this tutorial, we’ll dig in and learn a bit more about CSS transitions, and how we can use them to create lush, polished animations.

This tutorial is meant to be accessible to developers of all experience levels. It can be thought of as «CSS transitions 101». That said, I’ve sprinkled in some interesting and obscure tidbits — no matter your experience level, I bet you’ll learn something!

The main ingredient we need to create an animation is some CSS that changes. Here’s an example of a button that moves on hover, without animating:

Code Playground

button class="btn">
Hello World
button>
style>
.btn
width: 100px;
height: 100px;
border-radius: 50%;
border: none;
background: slateblue;
color: white;
font-size: 20px;
font-weight: 500;
line-height: 1;
>
.btn:hover
transform: translateY(-10px);
>
style>

This snippet uses the :hover pseudoclass to specify an additional CSS declaration when the user’s mouse rests atop our button, similar to an onMouseEnter event in JavaScript. To shift the element up, we use transform: translateY(-10px) . While we could have used margin-top for this, transform: translate is a better tool for the job. We’ll see why later. By default, changes in CSS happen instantaneously. In the blink of an eye, our button has teleported to a new position! This is incongruous with the natural world, where things happen gradually. We can instruct the browser to interpolate from one state to another with the aptly-named transition property:

Code Playground

button class="btn">
Hello World
button>
style>
.btn
/*
All of the base styles have
moved to the “CSS” tab above.
*/
transition: transform 250ms;
>
.btn:hover
transform: translateY(-10px);
>
style>

If you plan on animating multiple properties, you can pass it a comma-separated list:

transition-property takes a special value: all . When all is specified, any CSS property that changes will be transitioned. It can be tempting to use this value, as it saves us a good chunk of typing if we’re animating multiple properties, but I recommend not using it. As your product evolves, you (or someone on your team) will likely wind up updating this code at some point in the future. An unexpected animation could slip through. Animation is like salt: too much of it spoils the dish. It pays to be really precise with the properties we animate.

When we tell an element to transition from one position to another, the browser needs to work out what each «intermediary» frame should look like. For example: let’s say that we’re moving an element from left to right, over a 1-second duration. A smooth animation should run at 60fps * , which means we’ll need to come up with 60 individual positions between the start and end. Let’s start by having them be evenly-spaced: To clarify what’s going on here: each faded circle represents a moment in time. As the circle moves from left to right, these are the frames that were shown to the user. It’s like a flipbook. In this animation, we’re using a linear timing function. This means that the element moves at a constant pace; our circle moves by the same amount each frame. There are several timing functions available to us in CSS. We can specify which one we want to use with the transition-timing-function property:

linear is rarely the best choice — after all, pretty much nothing in the real world moves this way * . Good animations mimic the natural world, so we should pick something more organic! Let’s run through our options.

ease-out comes charging in like a wild bull, but it runs out of energy. By the end, it’s pootering along like a sleepy turtle. Try scrubbing with the timeline; notice how drastic the movement is in the first few frames, and how subtle it becomes towards the end. If we were to graph the displacement of the element over time, it’d look something like this: When would you use ease-out ? It’s most commonly used when something is entering from off-screen (eg. a modal appearing). It produces the effect that something came hustling in from far away, and settles in front of the user.

ease-in , unsurprisingly, is the opposite of ease-out . It starts slow and speeds up: As we saw, ease-out is useful for things that enter into view from offscreen. ease-in , naturally, is useful for the opposite: moving something beyond the bounds of the viewport. This combo is useful when something is entering and exiting the viewport, like a modal. We’ll look at how to mix and match timing functions shortly. Note that ease-in is pretty much exclusively useful for animations that end with the element offscreen or invisible; otherwise, the sudden stop can be jarring.

Next up, ease-in-out . It’s the combination of the previous two timing functions: This timing function is symmetrical. It has an equal amount of acceleration and deceleration. I find this curve most useful for anything that happens in a loop (eg. an element fading in and out, over and over). It’s a big step-up over linear , but before you go slapping it on everything, let’s look at one more option.

If I had a bone to pick with the CSS language authors when it comes to transitions, it’s that ease is poorly named. It isn’t descriptive at all; literally all timing functions are eases of one sort or another! That nitpick aside, ease is awesome. Unlike ease-in-out , it isn’t symmetrical; it features a brief ramp-up, and a lot of deceleration. ease is the default value — if you don’t specify a timing function, ease gets used. Honestly, this feels right to me. ease is a great option in most cases. If an element moves, and isn’t entering or exiting the viewport, ease is usually a good choice.

An important note about all of these demos: time is constant. Timing functions describe how a value should get from 0 to 1 over a fixed time interval, not how quickly the animation should complete. Some timing functions may feel faster or slower, but in these examples, they all take exactly 1 second to complete.

If the provided built-in options don’t suit your needs, you can define your own custom easing curve, using the cubic bézier timing function!

All of the values we’ve seen so far are really just presets for this cubic-bezier function. It takes 4 numbers, representing 2 control points. Bézier curves are really nifty, but they’re beyond the scope of this tutorial. I’ll be writing more about them soon though! In the meantime, you can start creating your own Bézier timing functions using this wonderful helper from Lea Verou:

Once you come up with an animation curve you’re satisfied with, click “Copy” at the top and paste it into your CSS! You can also pick from this extended set of timing functions. Though beware: a few of the more outlandish options won’t work in CSS. When starting out with custom Bézier curves, it can be hard to come up with a curve that feels natural. With some practice, however, this is an incredibly expressive tool.

I have a confession to make: the demonstrations above, showing the different timing functions, were exaggerated. In truth, timing functions like ease-in are more subtle than depicted, but I wanted to emphasize the effect to make it easier to understand. The cubic-bezier timing function makes that possible! Show more

Some CSS properties are wayyy more expensive to animate than others. For example, height is a very expensive property because it affects layout. When an element’s height shrinks, it causes a chain reaction; all of its siblings will also need to move up, to fill the space!

Other properties, like background-color , are somewhat expensive to animate. They don’t affect layout, but they do require a fresh coat of paint on every frame, which isn’t cheap.

Two properties — transform and opacity — are very cheap to animate. If an animation currently tweaks a property like width or left , it can be greatly improved by moving it to transform (though it isn’t always possible to achieve the exact same effect).

Be sure to test your animations on the lowest-end device that your site/app targets. Your development machine is likely many times faster than it.

If you’re interested in learning more about animation performance, I gave a talk on this subject at React Rally. It goes deep into this topic:

Depending on your browser and OS, you may have noticed a curious little imperfection in some of the earlier examples:

Pay close attention to the letters. Notice how they appear to glitch slightly at the start and end of the transition, as if everything was locking into place?

This happens because of a hand-off between the computer’s CPU and GPU. Let me explain.

When we animate an element using transform and opacity , the browser will sometimes try to optimize this animation. Instead of rasterizing the pixels on every frame, it transfers everything to the GPU as a texture. GPUs are very good at doing these kinds of texture-based transformations, and as a result, we get a very slick, very performant animation. This is known as “hardware acceleration”.

Here’s the problem: GPUs and CPUs render things slightly differently. When the CPU hands it to the GPU, and vice versa, you get a snap of things shifting slightly.

We can fix this problem by adding the following CSS property:

will-change is a property that allows us to hint to the browser that we’re going to animate the selected element, and that it should optimize for this case.

In practice, what this means is that the browser will let the GPU handle this element all the time. No more handing-off between CPU and GPU, no more telltale “snapping into place”.

will-change lets us be intentional about which elements should be hardware-accelerated. Browsers have their own inscrutable logic around this stuff, and I’d rather not leave it up to chance.

There’s another benefit to hardware acceleration: we can take advantage of sub-pixel rendering.

Check out these two boxes. They shift down when you hover/focus them. One of them is hardware-accelerated, and the other one isn’t.

Источник

Читайте также:  Mr. Camel
Оцените статью