4 Cool Hover Effects That Use CSS Text Shadow | Style-Tricks

In my final article we noticed how CSS background properties enable us to create cool hover results. This time, we are going to deal with the CSS text-shadow property to discover much more attention-grabbing hovers. You might be in all probability questioning how including shadow to textual content can presumably give us a cool impact, however right here’s the catch: we’re not really going to make any shadows for these textual content hover results.

text-shadow however no textual content shadows?

Let me clear the confusion by displaying the hover results we’re going to construct within the following demo:

With out wanting on the code lots of you’ll, intuitively, assume that for every hover impact we’re duplicating the textual content after which independently animating them. Now, if you happen to examine the code you will note that not one of the textual content is definitely duplicated within the HTML. And did you discover that there is no such thing as a use of content material: "textual content" within the CSS?

The textual content layers are utterly made with text-shadow!

Hover impact #1

Let’s decide aside the CSS:

.hover-1 {
  line-height: 1.2em;
  shade: #0000;
  text-shadow: 
    0 0 #000, 
    0 1.2em #1095c1;
  overflow: hidden;
  transition: .3s;
}
.hover-1:hover {
  text-shadow: 
    0 -1.2em #000, 
    0 0 #1095c1;
}

The very first thing to note is that I’m making the colour of the particular textual content clear (utilizing #0000) in an effort to disguise it. After that, I’m utilizing text-shadow to create two shadows the place I’m defining solely two size values for every one. Which means there’s no blur radius, making for a pointy, crisp shadow that successfully produces a duplicate of the textual content with the desired shade.

That’s why I used to be in a position to declare within the introduction that there aren’t any shadows in right here. What we’re doing is much less of a “basic” shadow than it’s a easy approach to duplicate the textual content.

Diagram of the start and end of the hover effect.

We now have two textual content layers that we transfer on hover. If we disguise the overflow, then the duplicated textual content is out of view and the motion makes it seem as if the precise textual content is being changed by different textual content. That is the principle trick that that makes the entire examples on this article work.

Let’s optimize our code. I’m utilizing the worth 1.2em so much to outline the peak and the offset of the shadows, making it a super candidate for a CSS customized property (which we’re calling --h):

.hover-1 {
  --h: 1.2em;

  line-height: var(--h);
  shade: #0000;
  text-shadow: 
    0 0 #000, 
    0 var(--h) #1095c1;
  overflow: hidden;
  transition: .3s;
}
.hover-1:hover {
  text-shadow: 
    0 calc(-1 * var(--h)) #000, 
    0 0 #1095c1;
}

We will nonetheless go additional and apply extra calc()-ulations to streamline issues to the place we solely use the text-shadow as soon as. (We did the identical within the earlier article.)

.hover-1 {
  --h: 1.2em;   

  line-height: var(--h);
  shade: #0000;
  text-shadow: 
    0 calc(-1*var(--_t, 0em)) #000, 
    0 calc(var(--h) - var(--_t, 0em)) #1095c1;
  overflow: hidden;
  transition: .3s;
}
.hover-1:hover {
  --_t: var(--h);
}

In case you’re questioning why I’m including an underscore to the --_t variable, it’s only a naming conference I’m utilizing to tell apart between the variables we use to manage the impact that the person can replace (like --h) and the interior variables which are solely used for optimization functions that we don’t want to alter (like --_t ). In different phrases, the underscore is a part of the variable title and has no particular that means.

We will additionally replace the code to get the alternative impact the place the duplicated textual content slides in from the highest as a substitute:

All we did is a small replace to the text-shadow property — we didn’t contact the rest!

Hover impact #2

For this one, we are going to animate two properties: text-shadow and background. In regards to the text-shadow, we nonetheless have two layers just like the earlier instance, however this time we are going to transfer solely one in every of them whereas making the colour of the opposite one clear in the course of the swap.

.hover-2 {
  /* the peak */
  --h: 1.2em;

  line-height: var(--h);
  shade: #0000;
  text-shadow: 
    0 var(--_t, var(--h)) #fff,
    0 0 var(--_c, #000);
  transition: 0.3s;
}
.hover-2:hover {
  --_t: 0;
  --_c: #0000;
}

On hover, we transfer the white textual content layer to the highest whereas altering the colour of the opposite one to clear. To this, we add a background-size animation utilized to a gradient:

And at last, we add overflow: hidden to maintain the animation solely seen contained in the aspect’s boundaries:

.hover-2 {
  /* the peak */
  --h: 1.2em;

  line-height: var(--h);
  shade: #0000;
  text-shadow: 
    0 var(--_t,var(--h)) #fff,
    0 0 var(--_c, #000);
  background: 
    linear-gradient(#1095c1 0 0) 
    backside/100% var(--_d, 0) no-repeat;
  overflow: hidden;
  transition: 0.3s;
}
.hover-2:hover {
  --_d: 100%;
  --_t: 0;
  --_c: #0000;
}

What we’ve accomplished right here is mix the CSS text-shadow and background properties to create a cool hover impact. Plus, we had been ready to make use of CSS variables to optimize the code.

If the background syntax seems to be unusual to you, I extremely suggest studying my earlier article. The following hover impact additionally depends on an animation I detailed in that article. Until you’re comfy with CSS background trickery, I’d recommend studying that article earlier than persevering with this one for extra context.

Within the earlier article, you present us how you can use just one variable to create the hover impact — is it attainable to do this right here?

Sure, completely! We will certainly use that very same DRY switching method in order that we’re solely working with a single CSS customized property that merely switches values on hover:

.hover-2 {
  /* the peak */
  --h: 1.2em;

  line-height: var(--h);
  shade: #0000;
  text-shadow: 
    0 var(--_i, var(--h)) #fff,
    0 0 rgb(0 0 0 / calc(var(--_i, 1) * 100%) );
  background: 
    linear-gradient(#1095c1 0 0) 
    backside/100% calc(100% - var(--_i, 1) * 100%) no-repeat;
  overflow: hidden;
  transition: 0.3s;
}
.hover-2:hover {
  --_i: 0;
}

Hover impact #3

This hover impact is nothing however a mixture of two results we’ve already made: the second hover impact of the earlier article and the primary hover impact on this article.

.hover-3 {
  /* the colour  */
  --c: #1095c1;
  /* the peak */
  --h: 1.2em;

  /* The primary hover impact on this article */
  line-height: var(--h);  
  shade: #0000;
  overflow: hidden;
  text-shadow: 
    0 calc(-1 * var(--_t, 0em)) var(--c), 
    0 calc(var(--h) - var(--_t, 0em)) #fff;
  /* The second hover impact from the earlier article */
  background: 
    linear-gradient(var(--c) 0 0) no-repeat 
    calc(200% - var(--_p, 0%)) 100% / 200% var(--_p, .08em);
  transition: .3s var(--_s, 0s), background-position .3s calc(.3s - var(--_s, 0s));
}
.hover-3:hover {
  --_t: var(--h);
  --_p: 100%;
  --_s: .3s
}

All I did was copy and paste the results from these different examples and make minor changes to the variable names. They make for a neat hover impact after they’re mixed! At first look, such an impact might look complicated and troublesome however, in the long run, it’s merely two comparatively simple results made into one.

Optimizing the code with the DRY switching variable method also needs to be a straightforward activity if we think about the earlier optimizations we’ve already accomplished:

.hover-3 {
  /* the colour  */
  --c: #1095c1;
  /* the peak */
  --h: 1.2em;

  line-height: var(--h);  
  shade: #0000;
  overflow: hidden;
  text-shadow: 
    0 calc(-1 * var(--h) * var(--_i, 0)) var(--c), 
    0 calc(var(--h) * (1 - var(--_i, 0))) #fff;
  background: 
    linear-gradient(var(--c) 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-3:hover {
  --_i: 1;
}

Hover impact #4

This hover impact is an enchancment of the second. First, let’s introduce a clip-path animation to disclose one of many textual content layers earlier than it strikes:

Right here’s one other illustration to raised perceive what is occurring:

Diagram of the start and end of the text hover.

Initially, we use inset(0 0 0 0) which has similarities to overflow: hidden in that each one we see is the precise textual content. On hover, we replace the the third worth (which signify the underside offset) utilizing a adverse worth equal to the peak to disclose the textual content layer positioned on the backside.

From there, we are able to add this to the second hover impact we made on this article, and that is what we get:

We’re getting nearer! Observe that we have to first run the clip-path animation after which the whole lot else. Because of this, we are able to add a delay to all of the properties on hover, besides clip-path:

transition: 0.4s 0.4s, clip-path 0.4s;

And on mouse out, we do the alternative:

transition: 0.4s, clip-path 0.4s 0.4s;

The ultimate contact is so as to add a box-shadow to create the sliding impact of the blue rectangle. Sadly, background is unable to provide the impact since backgrounds are clipped to the content material space by default. In the meantime, box-shadow can go exterior the content material space.

.hover-4 {
  /* the colour  */
  --c: #1095c1;
  /* the peak */
  --h: 1.2em;
  
  line-height: var(--h);
  shade: #0000;
  text-shadow: 
    0 var(--_t, var(--h)) #fff,
    0 0 var(--_c, #000);
  box-shadow: 0 var(--_t, var(--h)) var(--c);
  clip-path: inset(0 0 0 0);
  background: linear-gradient(var(--c) 0 0) 0 var(--_t, var(--h)) no-repeat;
  transition: 0.4s, clip-path 0.4s 0.4s;
}
.hover-4:hover {
  --_t: 0;
  --_c: #0000;
  clip-path: inset(0 0 calc(-1 * var(--h)) 0);
  transition: 0.4s 0.4s, clip-path 0.4s;
}

Should you look carefully on the box-shadow, you will note it has the identical values because the white textual content layer inside text-shadow. That is logical since each want to maneuver the identical approach. Each will slide to the highest. Then the box-shadow goes behind the aspect whereas text-shadow winds up on the highest.

Here’s a demo with some modified values to visualise how the layers transfer:

Wait, The background syntax is a bit totally different from the one used within the second hover impact!

Good catch! Sure, we’re utilizing a distinct method with background that produces the identical impact. As a substitute of animating the scale from 0% to 100%, we’re animating the place.

If we don’t specify a measurement on our gradient, then it take up the total width and top by default. Since we all know the peak of our aspect (--h) we are able to create a sliding impact by updating the place from 0 var(--h) to 0 0.

.hover-4 {
  /* ... */
  background: linear-gradient(var(--c) 0 0) 0 var(--_t, var(--h)) no-repeat;
}
.hover-4:hover {
  --_t: 0;
}

We might have used the background-size animation to get the identical impact, however we simply added one other trick to our record!

Within the demos, you additionally used inset(0 0 1px 0)… why?

I typically add or take away just a few pixels or percentages right here and there to refine something that appears off. On this case, a nasty line was showing on the backside and including 1px eliminated it.

What in regards to the DRY swap variable optimization?

I’m leaving this activity for you! After these 4 hover results and the earlier article, it is best to be capable of replace the code so it solely makes use of one variable. I’d like to see you try it within the feedback!

Your flip!

Let me share one final hover impact which is one other model of the earlier one. Are you able to learn how it’s accomplished with out wanting on the code? It’s a very good train, so don’t cheat!

Wrapping up

We checked out a bunch of examples that present how one aspect and few traces of CSS are sufficient to create some fairly complex-looking hover results on textual content parts — no pseudo parts wanted! We had been even in a position to mix methods to realize much more complicated animations with a small quantity of effort.

Should you’re taken with going deeper than the 4 text-shadow hover results on this article, examine my assortment of 500 hover effects the place I’m exploring all types of various methods.

Add a Comment

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