Animated Background Stripes That Transition on Hover
How often to do you reach for the CSS
background-size property? If you’re like me — and probably lots of other front-end folks — then it’s usually when you
background-size: cover an image to fill the space of an entire element.
Well, I was presented with an interesting challenge that required more advanced background sizing: background stripes that transition on hover. Check this out and hover it with your cursor:
There’s a lot more going on there than the size of the background, but that was the trick I needed to get the stripes to transition. I thought I’d show you how I arrived there, not only because I think it’s a really nice visual effect, but because it required me to get creative with gradients and blend modes that I think you might enjoy.
Let’s start with a very basic setup to keep things simple. I’m talking about a single
<div> in the HTML that’s styled as a green square:
If your mind went straight to a CSS linear gradient when you saw those stripes, then we’re already on the same page. We can’t exactly do a repeating gradient in this case since we want the stripes to occupy uneven amounts of space and transition them, but we can create five stripes by chaining five backgrounds on top of our existing background color and placing them to the top-right of the container:
I made horizontal stripes, but we could also go vertical with the approach we’re covering here. And we can simplify this quite a bit with custom properties:
--gt value is the gradient and
--n is a constant we’re using to nudge the stripes downward so they are offset vertically. And you may have noticed that I haven’t set a true gradient, but rather solid black stripes in the
linear-gradient() function — that’s intentional and we’ll get to why I did that in a bit.
One more thing we ought to do before moving on is prevent our backgrounds from repeating; otherwise, they’ll tile and fill the entire space:
We could have set
background-repeat in the
background shorthand, but I decided to break it out here to keep things easy to read.
We technically have stripes, but it’s pretty tough to tell because there’s no spacing between them and they cover the entire container. It’s more like we have a solid black square.
This is where we get to use the
background-size property. We want to set both the height and the width of the stripes and the property supports a two-value syntax that allows us to do exactly that. And, we can chain those sizes by comma separating them the same way we did on
Let’s start simple by setting the widths first. Using the single-value syntax for
background-size sets the width and defaults the height to
auto. I’m using totally arbitrary values here, so set the values to what works best for your design:
If you’re using the same values that I am, you’ll get this:
Doesn’t exactly look like we set the width for all the stripes, does it? That’s because of the
auto height behavior of the single-value syntax. The second stripe is wider than the others below it, and it is covering them. We ought to set the heights so we can see our work. They should all be the same height and we can actually re-use our
--n variable, again, to keep things simple:
Ah, much better!
This is a totally optional step if your design doesn’t require gaps between the stripes, but mine did and it’s not overly complicated. We change the height of each stripe’s
background-size a smidge, decreasing the value so they fall short of filling the full vertical space.
We can continue to use our
--n variable, but subtract a small amount, say
calc() to get what we want.
That’s a lot of repetition we can eliminate with another variable:
Now let’s swap the
palegreen background color we’ve been using for visual purposes up to this point for white.
A black and white pattern like this is perfect for masking and blending. To do that, we’re first going to wrap our
<div> in a new parent container and introduce a second
<div> under it:
We’re going to do a little CSS re-factoring here. Now that we have a new parent container, we can pass the fixed
height properties we were using on our
<div> over there:
To get that working, I’ll apply the real gradient we want to see on the first
<div> while applying the style rules from our initial
<div> on the new one, using the
If we stop here, we actually won’t see any visual difference from what we had before. That’s because we haven’t done the actual blending yet. So, let’s do that now using the
screen blend mode:
I used a beige background color in the demo I showed at the beginning of this article. That slightly darker sort of off-white coloring allows a little color to bleed through the rest of the background:
The last piece of this puzzle is the hover effect that widens the stripes to full width. First, let’s write out our selector for it. We want this to happen when the parent container (
<section> in our case) is hovered. When it’s hovered, we’ll change the background size of the stripes contained in the second
We’ll want to change the
background-size of the stripes to the full width of the container while maintaining the same height:
That “snaps” the background to full-width. If we add a little
transition to this, then we see the stripes expand on hover:
Here’s that final demo once again:
Pretty neat, right? I certainly think so. What I like about this, too, is that it’s pretty maintainable and customizable. For example, we can alter the height, colors, and direction of the stripes by changing a few values. You might even variablize a few more things in there — like the colors and widths — to make it even more configurable.
I’m really interested if you would have approached this a different way. If so, please share in the comments! It’d be neat to see how many variations we can collect.
If you need help creating a digital marketing strategy for your business, don’t hesitate to contact one of Digidude’s consultants.