This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 15k traffic Daily!!!

Cool Hover Effects That Use Background Properties | Style-Tricks


Some time in the past, Geoff wrote an article a couple of cool hover impact. The impact depends on a mixture of CSS pseudo-elements, transforms, and transitions. Plenty of feedback have proven that the identical impact might be executed utilizing background properties. Geoff talked about that was his preliminary thought and that’s what I used to be considering as nicely. I’m not saying the pseudo-element he landed on is unhealthy, however figuring out totally different strategies to attain the identical impact can solely be a great factor.

On this put up, we’ll re-work that hover impact, but additionally develop it into different sorts of hover results that solely use CSS background properties.

You may see the background properties at work in that demo, in addition to how we will use customized properties and the calc() perform to do much more. We’re going to learn to mix all of those so we’re left with properly optimized code!

Hover impact #1

Let’s begin with the primary impact which is the copy of the one detailed by Geoff in his article. The code used to attain that impact is the next:

.hover-1 {
  background: linear-gradient(#1095c1 0 0) var(--p, 0) / var(--p, 0) no-repeat;
  transition: .4s, background-position 0s;
}
.hover-1:hover {
  --p: 100%;
  shade: #fff;
}

If we omit the colour transition (which is elective), we solely want three CSS declarations to attain the impact. You’re most likely shocked how small the code is, however you will notice how we bought there.

First, let’s begin with a easy background-size transition:

We’re animating the dimensions of a linear gradient from 0 100% to 100% 100%. Which means the width goes from 0 to 100% whereas the background itself stays at full peak. Nothing complicated to date.

Let’s begin our optimizations. We first rework our gradient to make use of the colour solely as soon as:

background-image: linear-gradient(#1095c1 0 0);

The syntax may look a bit unusual, however we’re telling the browser that one shade is utilized to 2 shade stops, and that’s sufficient to outline a gradient in CSS. Each shade stops are 0, so the browser mechanically makes the final one 100% and fills our gradient with the identical shade. Shortcuts, FTW!

With background-size, we will omit the peak as a result of gradients are full peak by default. We are able to do a transition from background-size: 0 to background-size: 100%.

.hover-1 {
  background-image: linear-gradient(#1095c1 0 0);
  background-size: 0;
  background-repeat: no-repeat;
  transition: .4s;
}
.hover-1:hover {
  background-size: 100%;
}

Let’s introduce a customized property to keep away from the repetition of background-size:

.hover-1 {
  background-image: linear-gradient(#1095c1 0 0);
  background-size: var(--p, 0%);
  background-repeat: no-repeat;
  transition: .4s;
}
.hover-1:hover {
  --p: 100%;
}

We aren’t defining --p initially, so the fallback worth (0% in our case) will likely be used. On hover, we outline a worth that replaces the fallback one ( 100%).

Now, let’s mix all of the background properties utilizing the shorthand model to get:

.hover-1 {
  background: linear-gradient(#1095c1 0 0) left / var(--p, 0%) no-repeat;
  transition: .4s;
}
.hover-1:hover {
  --p: 100%;
}

We’re getting nearer! Observe that I’ve launched a left worth (for the background-position) which is obligatory when defining the dimensions within the background shorthand. Plus, we’d like it anyway to attain our hover impact.

We have to additionally replace the place on hover. We are able to do this in two steps:

  1. Enhance the dimensions from the suitable on mouse hover.
  2. Lower the dimensions from the left on mouse out.

To do that, we have to replace the background-position on hover as nicely:

We added two issues to our code:

  • A background-position worth of proper on hover
  • A transition-duration of 0s on the background-position

Which means, on hover, we immediately change the background-position from left (see, we would have liked that worth!) to proper so the background’s measurement will improve from the suitable facet. Then, when the mouse cursor leaves the hyperlink, the transition performs in reverse, from proper to left, making it seem that we’re reducing the background’s measurement from the left facet. Our hover impact is finished!

However you mentioned we solely wanted three declarations and there are 4.

That’s true, good catch. The left and proper values might be modified to 0 0 and 100% 0, respectively; and since our gradient is already full peak by default, we will get by utilizing 0 and 100%.

.hover-1 {
  background: linear-gradient(#1095c1 0 0) 0 / var(--p, 0%) no-repeat;
  transition: .4s, background-position 0s;
}
.hover-1:hover {
  --p: 100%;
  background-position: 100%;
}

See how background-position and --p are utilizing the identical values? Now we will scale back the code down to 3 declarations:

.hover-1 {
  background: linear-gradient(#1095c1 0 0) var(--p, 0%) / var(--p,0%) no-repeat;
  transition: .4s, background-position 0s;
}
.hover-1:hover {
  --p: 100%;
}

The customized property --p is defining each the background place and measurement. On hover, It is going to replace each of them as nicely. It is a excellent use case exhibiting how customized properties may help us scale back redundant code and keep away from writing properties greater than as soon as. We outline our setting utilizing customized properties and we solely replace the latter on hover.

However the impact Geoff described is doing the other, ranging from left and ending at proper. How will we do this when it appears we can’t depend on the identical variable?

We are able to nonetheless use one variable and replace our code barely to attain the other impact. What we wish is to go from 100% to 0% as an alternative of 0% to 100%. We have now a distinction of 100% that we will specific utilizing calc(), like this:

.hover-1 {
  background: linear-gradient(#1095c1 0 0) calc(100% - var(--p,0%)) / var(--p,0%) no-repeat;
  transition: .4s, background-position 0s;
}
.hover-1:hover {
  --p: 100%;
}

--p will change from 0% to 100%, however the background’s place will change from 100% to 0%, due to calc().

We nonetheless have three declarations and one customized property, however a unique impact.

Earlier than we transfer to the subsequent hover impact, I wish to spotlight one thing necessary that you’ve got most likely seen. When coping with customized properties, I’m utilizing 0% (with a unit) as an alternative of a unit-less 0. The unit-less zero may go when the customized property is alone, however will fail inside calc() the place we have to explicitly outline the unit. I may have one other article to clarify this quirk however all the time bear in mind so as to add the unit when coping with customized properties. I’ve two solutions on StackOverflow (here and here) that go into extra element.

Hover impact #2

We’d like a extra complicated transition for this impact. Let’s check out a step-by-step illustration to know what is occurring.

Diagram showing the hover effect in three pieces.
Initially, a fixed-height, full-width gradient is exterior of view. Then we transfer the gradient to the suitable to cowl the underside facet. Lastly, we improve the dimensions of the gradient from the fastened peak to 100% to cowl the entire aspect.

We first have a background-position transition adopted by a background-size one. Let’s translate this into code:

.hover-2 {
  background-image: linear-gradient(#1095c1 0 0);
  background-size: 100% .08em; /* .08em is our fastened peak; modify as wanted. */
  background-position: /* ??? */;
  background-repeat: no-repeat;
  transition: background-size .3s, background-position .3s .3s;
}
.hover-2:hover {
  transition: background-size .3s .3s, background-position .3s;
  background-size: 100% 100%;
  background-position: /* ??? */;
}

Observe using two transition values. On hover, we have to first change the place and later the dimensions, which is why we’re including a delay to the dimensions. On mouse out, we do the other.

The query now could be: what values will we use for background-position? We left these clean above. The background-size values are trivial, however the ones for background-position aren’t. And if we maintain the precise configuration we’re unable to maneuver our gradient.

Our gradient has a width equal to 100%, so we can’t use proportion values on background-position to maneuver it.

Proportion values used with background-position are all the time a ache particularly if you use them for the primary time. Their habits is non-intuitive however nicely outlined and simple to know if we get the logic behind it. I feel it could take one other article for a full reason it really works this fashion, however right here’s another “long” explanation I posted over at Stack Overflow. I like to recommend taking a couple of minutes to learn that reply and you’ll thank me later!

The trick is to alter the width to one thing totally different than 100%. Let’s use 200%. We’re not nervous concerning the background exceeding the aspect as a result of the overflow is hidden anyway.

.hover-2 {
  background-image: linear-gradient(#1095c1 0 0);
  background-size: 200% .08em;
  background-position: 200% 100%;
  background-repeat: no-repeat;
  transition: background-size .3s, background-position .3s .3s;
}
.hover-2:hover {
  transition: background-size .3s .3s, background-position .3s;
  background-size: 200% 100%;
  background-position: 100% 100%;
}

And right here’s what we get:

It’s time to optimize our code. If we take the concepts we realized from the primary hover impact, we will use shorthand properties and write fewer declarations to make this work:

.hover-2 {
  background: 
    linear-gradient(#1095c1 0 0) no-repeat
    var(--p, 200%) 100% / 200% var(--p, .08em);
  transition: .3s var(--t, 0s), background-position .3s calc(.3s - var(--t, 0s));
}
.hover-2:hover {
  --p: 100%;
  --t: .3s;
}

We add all of the background properties collectively utilizing the shorthand model then we use --p to specific our values. The sizes change from .08em to 100% and the place from 200% to 100%

I’m additionally utilizing one other variable --t , to optimize the transition property. On mouse hover we’ve got it set to a .3s worth, which provides us this:

transition: .3s .3s, background-position .3s 0s;

On mouse out, --t is undefined, so the fallback worth will likely be used:

transition: .3s 0s, background-position .3s .3s;

Shouldn’t we’ve got background-size within the transition?

That’s certainly one other optimization we will make. If we don’t specify any property it means “all” the properties, so the transition is outlined for “all” the properties (together with background-size and background-position). Then it’s outlined once more for background-position which has similarities to defining it for background-size, then background-position.

“Related” is totally different than saying one thing is the “identical.” You will notice a distinction if you happen to change extra properties on hover, so the final optimization is likely to be unsuitable in some instances.

Can we nonetheless optimize the code and use just one customized property?

Sure, we will! Ana Tudor shared an ideal article explaining the best way to create DRY switching the place one customized property can replace a number of properties. I received’t go into the main points right here, however our code might be revised like this:

.hover-2 {
  background: 
    linear-gradient(#1095c1 0 0) no-repeat
    calc(200% - var(--i, 0) * 100%) 100% / 200% calc(100% * var(--i, 0) + .08em);
  transition: .3s calc(var(--i, 0) * .3s), background-position .3s calc(.3s - calc(var(--i, 0) * .3s));
}
.hover-2:hover {
  --i: 1;
}

The --i customized property is initially undefined, so the fallback worth, 0, is used. On hover although, we change 0 with 1. You are able to do the mathematics for each instances and get the values for each. You may see that variable as a “change” that replace all our values directly on hover.

Once more, we’re again to solely three declarations for a fairly cool hover impact!

Hover impact #3

We’re going to use two gradients as an alternative of 1 for this impact. We are going to see that combining a number of gradients is one other solution to create fancy hover results.

Right here’s a diagram of what we’re doing:

We initially have two gradients that overflow the aspect in order that they’re out of view. Each has a set peak and toes up half of the aspect’s width. Then we slide them into view to make them seen. The primary gradient is positioned on the bottom-left and the second on the top-right. Lastly, we improve the peak to cowl the entire aspect.

Right here’s how that appears in CSS:

.hover-3 {
  background-image:
    linear-gradient(#1095c1 0 0),
    linear-gradient(#1095c1 0 0);
  background-repeat: no-repeat;
  background-size: 50% .08em;
  background-position:
    -100% 100%,
    200% 0;
  transition: background-size .3s, background-position .3s .3s;
}
.hover-3:hover {
  background-size: 50% 100%;
  background-position:
    0 100%,
    100% 0;  
  transition: background-size .3s .3s, background-position .3s;
}

The code is sort of the identical as the opposite hover results we’ve lined. The one distinction is that we’ve got two gradients with two totally different positions. The place values might look unusual however, once more, that’s associated to how percentages work with the background-position property in CSS, so I extremely advocate studying my Stack Overflow answer if you wish to get into the gritty particulars.

Now let’s optimize! You get the concept by now — we’re utilizing shorthand properties, customized properties, and calc() to tidy issues up.

.hover-3 {
  --c: no-repeat linear-gradient(#1095c1 0 0);
  background: 
    var(--c) calc(-100% + var(--p, 0%)) 100% / 50% var(--p, .08em),
    var(--c) calc( 200% - var(--p, 0%)) 0    / 50% var(--p, .08em);
  transition: .3s var(--t, 0s), background-position .3s calc(.3s - var(--t, 0s));
}
.hover-3:hover {
  --p: 100%;
  --t: 0.3s;
}

I’ve added an additional customized property, --c, that defines the gradient because the identical gradient is utilized in each locations.

I’m utilizing 50.1% in that demo as an alternative of 50% for the background measurement as a result of it prevents a spot from exhibiting between the gradients. I additionally added 1% to the positions for related causes.

Let’s do the second optimization by utilizing the change variable:

.hover-3 {
  --c: no-repeat linear-gradient(#1095c1 0 0);
  background: 
    var(--c) calc(-100% + var(--i, 0) * 100%) 100% / 50% calc(100% * var(--i, 0) + .08em),
    var(--c) calc( 200% - var(--i, 0) * 100%) 0 / 50% calc(100% * var(--i, 0) + .08em);
  transition: .3s calc(var(--i, 0) * .3s), background-position .3s calc(.3s - var(--i, 0) * .3s);
}
.hover-3:hover {
  --i: 1;
}

Are you began to see the patterns right here? It’s not a lot that the consequences we’re making are tough. It’s extra the “last step” of code optimization. We begin by writing verbose code with a variety of properties, then scale back it following easy guidelines (e.g. utilizing shorthand, eradicating default values, avoiding redundant values, and many others) to simplify issues down as a lot as attainable.

Hover impact #4

I’ll elevate the issue stage for this final impact, however sufficient from the opposite examples that I doubt you’ll have any points with this one.

This hover impact depends on two conic gradients and extra calculations.

Initially, we’ve got each gradients with zero dimensions in Step 1. We improve the dimensions of every one in Step 2. We maintain rising their widths till they absolutely cowl the aspect, as proven in Step 3. After that, we slide them to the underside to replace their place. That is the “magic” a part of the hover impact. Since each gradients will use the identical coloration, altering their place in Step 4 will make no visible distinction — however we’ll see a distinction as soon as we scale back the dimensions on mouse out throughout Step 5.

When you examine Step 2 and Step 5, you possibly can see that we’ve got a unique inclination. Let’s translate that into code:

.hover-4 {
  background-image:
    conic-gradient(/* ??? */),
    conic-gradient(/* ??? */);
  background-position:
    0 0,
    100% 0;
  background-size: 0% 200%;
  background-repeat: no-repeat;
  transition: background-size .4s, background-position 0s;
}
.hover-4:hover {
  background-size: /* ??? */ 200%;
  background-position:
    0 100%,
    100% 100%;
}

The positions are fairly clear. One gradient begins at high left (0 0) and ends at backside left (0 100%) whereas the opposite begins at high proper (100% 0) and ends at backside proper (100% 100%).

We’re utilizing a transition on the background positions and sizes to disclose them. We solely want a transition worth for the background-size. And like earlier than, background-position wants to alter immediately, so we’re assigning a 0s worth for the transition’s period.

For the sizes, each gradient have to have 0 width and twice the aspect peak (0% 200%). We are going to see later how their sizes change on hover. Let’s first outline the gradient configuration.

The diagram beneath illustrates the configuration of every gradient:

Observe that for the second gradient (indicated in inexperienced), we have to know the peak to make use of it contained in the conic-gradient we’re creating. Because of this, I’m going so as to add a line-height that units the aspect’s peak after which strive that very same worth for the conic gradient values we disregarded.

.hover-4 {
  --c: #1095c1;
  line-height: 1.2em;
  background-image:
    conic-gradient(from -135deg at 100%  50%, var(--c) 90deg, #0000 0),
    conic-gradient(from -135deg at 1.2em 50%, #0000 90deg, var(--c) 0);
  background-position:
    0 0,
    100% 0;
  background-size: 0% 200%;
  background-repeat: no-repeat;
  transition: background-size .4s, background-position 0s;
}
.hover-4:hover {
  background-size: /* ??? */ 200%;
  background-position:
    0 100%,
    100% 100%;
}

The very last thing we’ve got left is to determine the background’s measurement. Intuitively, we might imagine that every gradient must take up half of the aspect’s width however that’s truly not sufficient.

We’re left with a big hole if we use 50% because the background-size worth for each gradients.

We get a spot equal to the peak, so we truly have to do is improve the dimensions of every gradient by half the peak on hover for them to cowl the entire aspect.

.hover-4:hover {
  background-size: calc(50% + .6em) 200%;
  background-position:
    0 100%,
    100% 100%;
}

Right here’s what we get after optimizing them just like the earlier examples:

.hover-4 {
  --c: #1095c1;
  line-height: 1.2em;
  background:
    conic-gradient(from -135deg at 100%  50%, var(--c) 90deg, #0000 0) 
      0  var(--p, 0%) / var(--s, 0%) 200% no-repeat,
    conic-gradient(from -135deg at 1.2em 50%, #0000 90deg, var(--c) 0) 
      100% var(--p, 0%) / var(--s, 0%) 200% no-repeat;
  transition: .4s, background-position 0s;
}
.hover-4:hover {
  --p: 100%;
  --s: calc(50% + .6em);
}

What concerning the model with just one customized property?

I’ll depart that for you! After taking a look at 4 related hover results, you must have the ability to get the ultimate optimization all the way down to a single customized property. Share your work within the remark part! There’s no prize, however we might find yourself with totally different implementations and concepts that profit everybody!

Earlier than we finish, let me share a model of that final hover impact that Ana Tudor cooked up. It’s an enchancment! However notice that it lacks Firefox helps because of a recognized bug. Nonetheless, it’s an ideal concept that exhibits the best way to mix gradients with mix modes to create even cooler hover results.

Wrapping up

We made 4 tremendous cool hover results! And although they’re totally different results, all of them take the identical strategy of utilizing CSS background properties, customized properties, and calc(). Completely different combos allowed us to make totally different variations, all utilizing the identical methods that depart us with clear, maintainable code.

If you wish to get some concepts, I made a collection of 500 (sure, 500!) hover results, 400 of that are executed with out pseudo-elements. The 4 we lined on this article are simply the tip of the iceberg!



The Article was Inspired from tech community site.
Contact us if this is inspired from your article and we will give you credit for it for serving the community.

This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 10k Tech related traffic daily !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?