In my final article we noticed how CSS background
properties permit us to create cool hover results. This time, we are going to concentrate on the CSS text-shadow
property to discover much more attention-grabbing hovers. You might be most likely questioning how including shadow to textual content can probably give us a cool impact, however right here’s the catch: we’re not truly going to make any shadows for these textual content hover results.
text-shadow
however no textual content shadows?
Let me clear the confusion by exhibiting the hover results we’re going to construct within the following demo:
With out trying on the code lots of you’ll, intuitively, suppose that for every hover impact we’re duplicating the textual content after which independently animating them. Now, when you test the code you will note that not one of the textual content is definitely duplicated within the HTML. And did you discover that there isn’t any use of content material: "textual content"
within the CSS?
The textual content layers are utterly made with text-shadow
!
Hover impact #1
Let’s choose 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
) with the intention to conceal it. After that, I’m utilizing text-shadow
to create two shadows the place I’m defining solely two size values for each. 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 capable of declare within the introduction that there aren’t any shadows in right here. What we’re doing is much less of a “traditional” shadow than it’s a easy solution to duplicate the textual content.
We now have two textual content layers that we transfer on hover. If we conceal 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 really perfect 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 are able to 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 in 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 might be 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 might be solely used for optimization functions that we don’t want to vary (like --_t
). In different phrases, the underscore is a part of the variable identify and has no particular which means.
We are able to additionally replace the code to get the alternative impact the place the duplicated textual content slides in from the highest as an alternative:
All we did is a small replace to the text-shadow
property — we didn’t contact anything!
Hover impact #2
For this one, we are going to animate two properties: text-shadow
and background
. Regarding the text-shadow
, we nonetheless have two layers just like the earlier instance, however this time we are going to transfer solely one in all them whereas making the colour of the opposite one clear through 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 completed right here is mix the CSS text-shadow
and background
properties to create a cool hover impact. Plus, we had been in a position to make use of CSS variables to optimize the code.
If the background
syntax appears to be like unusual to you, I extremely advocate studying my earlier article. The subsequent hover impact additionally depends on an animation I detailed in that article. Until you might be snug with CSS background
trickery, I’d counsel studying that article earlier than persevering with this one for extra context.
Within the earlier article, you present us learn how to use just one variable to create the hover impact — is it attainable to do this right here?
Sure, completely! We are able to certainly use that very same DRY switching approach 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 mix 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 consequences 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 could look advanced and troublesome however, ultimately, it’s merely two comparatively straightforward results made into one.
Optimizing the code with the DRY switching variable approach must also be a simple process if we think about the earlier optimizations we’ve already completed:
.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 higher perceive what is going on:
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 detrimental 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! Be aware that we have to first run the clip-path
animation after which every little thing else. For that reason, 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 supply the impact since backgrounds are clipped to the content material space by default. In the meantime, box-shadow
can go outdoors 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;
}
In case you look intently 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 means. 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 unique approach with background
that produces the identical impact. As an alternative of animating the dimensions from 0%
to 100%
, we’re animating the place
.
If we don’t specify a dimension on our gradient, then it take up the complete width and peak 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 checklist!
Within the demos, you additionally used
inset(0 0 1px 0)
… why?
I typically add or take away a couple of pixels or percentages right here and there to refine something that appears off. On this case, a foul line was showing on the backside and including 1px
eliminated it.
What concerning the DRY change variable optimization?
I’m leaving this process for you! After these 4 hover results and the earlier article, it is best to have the ability to 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 the way it’s completed with out trying on the code? It’s train, so don’t cheat!
Wrapping up
We checked out a bunch of examples that present how one aspect and few strains of CSS are sufficient to create some fairly complex-looking hover results on textual content parts — no pseudo parts wanted! We had been even capable of mix methods to attain much more advanced animations with a small quantity of effort.
In case you’re taken with going deeper than the 4 text-shadow
hover results on this article, test my assortment of 500 hover results the place I’m exploring all types of various methods.