Tag: Animate

Animate Text on Scroll

We covered the idea of animating curved text not long ago when a fun New York Times article came out. All I did was peek into how they did it and extract the relevant parts to a more isolated demo.

That demo is here:

See the Pen
Selfie Crawl
by Chris Coyier (@chriscoyier)
on CodePen.

@keyframers covered it much nicer than I did and made this video. (Seriously, it’s so clear and concise — it’s a great watch.)

I particularly like how quick’n’easy creating, exporting, optimizing, and integrating the actual SVG codes in their demonstration.

Their final demo:

See the Pen
SVG textPath Animation on Scroll Tutorial | Keyssentials: Web Animation Tips by @keyframers
by @keyframers (@keyframers)
on CodePen.

The post Animate Text on Scroll appeared first on CSS-Tricks.

CSS-Tricks

, ,

How to Animate on the Web With Greensock

There are truly thousands of ways to animate on the web. We’ve covered a comparison of different animation technologies here before. Today, we’re going to dive into a step-by-step guide of one of my favorite ways to get it done: using GreenSock.

(They don’t pay me or anything, I just really enjoy using them.)

Why do I prefer Greensock to other methods? Technically speaking, it’s often the best tool for the job. It’s usage is extremely straightforward, even for complex movement. Here are a few more reasons why I prefer using it:

  • You can use them on DOM elements as well as within WebGL/Canvas/Three.js contexts.
  • The easing is very sophisticated. CSS animations are limited to two bezier handles for ease, meaning if you want, say, a bounce effect, you would have to make keyframes up and down and up and down for each pass. GreenSock allows multiple bezier handles to create advanced effects. A bounce is a single line of code. You can see what I mean by checking out their ease visualizer.
  • You can sequence movement on a timeline. CSS animations can get a little spaghetti when you have to coordinate several things at once. GreenSock remains very legible and allows you to control the timeline itself. You can even animate your animations! 🤯
  • It will perform some calculations under the hood to prevent strange cross-browser behavior as well as things that the spec dictates should be true aren’t — like the way that stacking transforms work.
  • It offers a lot of advanced functionality, in the form of plugins, that you can use if you’d like to take your work a step further — things like Morphing SVG shapes, drawing SVG paths, dragging and dropping, inertia, and more.

People sometimes ask me why I’d use this particular library over all of the other choices. It’s further along than most others — they’ve been around since the Flash was still a thing. This demo reel is pretty inspiring, and also gets the point across that serious web animators do tend to reach for this tool:

What follows is a breakdown of how to create movement on the web, distilled down to the smallest units I could make them. Let’s get started!

Animating a DOM element

Consider a ball that we with a <div> that’s styled with a border-radius value of 50%. Here’s how we would scale and move it with Greensock:

<div class="ball"></div>
gsap.to('.ball', {   duration: 1,   x: 200,   scale: 2 })

See the Pen
Greensock Tutorial 1
by Sarah Drasner (@sdras)
on CodePen.

In this case, we’re telling GreenSock (gsap) to take the element with the class of .ball move it .to() a few different properties. We’ve shortened the CSS properties of transform: translateX(200px) to a streamlined x: 200 (note there’s no need for the units, but you can pass them as a string). We’re also not writing transform: scale(2). Here’s a reference of the transforms you might want to use with animations, and their corresponding CSS syntax:

x: 100 // transform: translateX(100px) y: 100 // transform: translateY(100px) z: 100 // transform: translateZ(100px) // you do not need the null transform hack or hardware acceleration, it comes baked in with // force3d:true. If you want to unset this, force3d:false scale: 2 // transform: scale(2) scaleX: 2 // transform: scaleX(2) scaleY: 2 // transform: scaleY(2) scaleZ: 2 // transform: scaleZ(2) skew: 15 // transform: skew(15deg) skewX: 15 // transform: skewX(15deg) skewY: 15 // transform: skewY(15deg) rotation: 180 // transform: rotate(180deg) rotationX: 180 // transform: rotateX(180deg) rotationY: 180 // transform: rotateY(180deg) rotationZ: 180 // transform: rotateZ(180deg) perspective: 1000 // transform: perspective(1000px) transformOrigin: '50% 50%' // transform-origin: 50% 50%

Duration is what you might think it is: it’s a one-second stretch of time.

So, OK, how would we animate, say, an SVG? Let’s consider the same code above as an SVG:

<svg viewBox="0 0 500 400">   <circle class="ball" cx="80" cy="80" r="80" /> </svg>
gsap.to('.ball', {   duration: 1,   x: 200,   scale: 2 })

See the Pen
Greensock Tutorial 2
by Sarah Drasner (@sdras)
on CodePen.

From an animation perspective, it’s actually exactly the same. It’s grabbing the element with the class .ball on it, and translating those properties. Since SVGs are literally DOM elements, we can slap a class on any one of them and animate them just the same way!

Great! We’re cooking with gas.

Eases

I mentioned before that eases are one of my favorite features, let’s take a look at how we’d use them.

Let’s take the original ball. Maybe we want to try one of those more unique bounce eases. It would go like this:

gsap.to('.ball', {   duration: 1.5,   x: 200,   scale: 2,   ease: 'bounce' })

See the Pen
Greensock Tutorial 3
by Sarah Drasner (@sdras)
on CodePen.

That’s it! This version of GreenSock assumes that you want to use ease-out timing (which is better for entrances), so it applies that as a default. All you have to do is specify “bounce” as a string and you’re off to the races.

You might have noticed we also lengthened the duration a bit as well. That’s because the ball has to do more “work” in between the initial and end states. A one-second duration, though lovely for linear or sine easing, is a little too quick for a bounce or an elastic ease.

Delays and Timelines

I mentioned that the default ease-out timing function is good for entrances. What about an ease-in or ease-in-out exit? Let’s do that as well.

gsap.to('.ball', {   duration: 1.5,   x: 200,   scale: 2,   ease: 'bounce' })  gsap.to('.ball', {   duration: 1.5,   delay: 1.5,   x: 0,   scale: 1,   ease: 'back.inOut(3)' })

You might have noticed a few things happening. For example, we didn’t use bounce.in on the second-to-last line (ease: 'back.inOut(3)'). Instead, we used another ease called back for ease-in-out. We also passed in a configuration option because, as you can see with Greensock’s ease visualizer tool, we’re not limited to just the default configuration for that ease. We can adjust it to our needs. Neat!

You may have also noticed that we chained the animations using a delay. We took the length of the duration of the first animation and made sure the next one has a delay of that matches. Now, that works here, but that’s pretty brittle. What if we want to change the length of the first one? Well, now we’ve got to go back through and change the delay that follows. And what if we have another animation after that? And another one after that? Well, we’d have to go back through and calculate all the other delays down the line. That’s a lot of manual work.

We can offload that work to the computer. Some of my more complex animations are hundreds of chained animations! If I finish my work and want to adjust something in the beginning, I don’t want to have to go back through everything. Enter timelines:

gsap   .timeline()   .to(‘.ball’, {     duration: 1.5,     x: 200,     scale: 2,     ease: "bounce"   })   .to(‘.ball’, {     duration: 1.5,     x: 0,     scale: 1,     ease: "back.inOut(3)"   });

See the Pen
Greensock Tutorial 4
by Sarah Drasner (@sdras)
on CodePen.

This instantiates a timeline and then chains the two animations off of it.

But we still have a bit of repetition where we keep using the same duration in each animation. Let’s create a default for that as an option passed to the timeline.

gsap   .timeline({     defaults: {       duration: 1.5     }   })   .to('.ball', {     x: 200,     scale: 2,     ease: "bounce"   })   .to('.ball', {     x: 0,     scale: 1,     ease: "back.inOut(3)"   });

See the Pen
Greensock Tutorial 4
by Sarah Drasner (@sdras)
on CodePen.

That’s pretty cool! Alright, you are probably starting to see how things are built this way. While it might not be a big deal in an animation this simple, defaults and timelines in really complex animations can truly keep code maintainable.

Now, what if we want to mirror this motion in the other direction with the ball, and just… keep it going? In other words, what if we want a loop? That’s when we add repeat: -1, which can be applied either to a single animation or to the entire timeline.

gsap   .timeline({     repeat: -1,     defaults: {       duration: 1.5     }   })   .to('.ball', {     x: 200,     scale: 2,     ease: "bounce"   })   .to('.ball', {     x: 0,     scale: 1,     ease: "back.inOut(3)"   })   .to('.ball', {     x: -200,     scale: 2,     ease: "bounce"   })   .to('.ball', {     x: 0,     scale: 1,     ease: "back.inOut(3)"   });

See the Pen
Greensock Tutorial 5
by Sarah Drasner (@sdras)
on CodePen.

We could also not only make it repeat, but repeat and play back and forth, like a yoyo. That’s why we call this yoyo: true. To make the point clear, we’ll show this with just the first animation. You can see it plays forward, and then it plays in reverse.

gsap   .timeline({     repeat: -1,     yoyo: true,     defaults: {       duration: 1.5     }   })   .to('.ball', {     x: 200,     scale: 2,     ease: "bounce"   })

See the Pen
Greensock Tutorial 6
by Sarah Drasner (@sdras)
on CodePen.

Overlaps and Labels

It’s great that we can chain animations with ease, but real-life motion doesn’t exactly work this way. If you walk across the room to get a cup of water, you don’t walk. Then stop. Then pick up the water. Then drink it. You’re more likely to do things in one continuous movement. So let’s talk briefly about how to overlap movement and make things fire at once.

If we want to be sure things fire a little before and after each other on a timeline, we can use an incrementer or decrementer. If we take the followingexampxle that shows three balls animating one after another, it feels a little stiff.

gsap   .timeline({     defaults: {       duration: 1.5     }   })   .to('.ball', {     x: 300,     scale: 2,     ease: "bounce"   })   .to('.ball2', {     x: 300,     scale: 2,     ease: "bounce"   })   .to('.ball3', {     x: 300,     scale: 2,     ease: "bounce"   })

See the Pen
Greensock Tutorial 8
by Sarah Drasner (@sdras)
on CodePen.

Tbigns get smoother if we overlap the movement just slightly using those decrementers passed as strings:

gsap   .timeline({     defaults: {       duration: 1.5     }   })   .to('.ball', {     x: 300,     scale: 2,     ease: "bounce"   })   .to('.ball2', {     x: 300,     scale: 2,     ease: "bounce"   }, '-=1')   .to('.ball3', {     x: 300,     scale: 2,     ease: "bounce"   }, '-=1')

See the Pen
Greensock Tutorial 9
by Sarah Drasner (@sdras)
on CodePen.

Another way we can do this is to use something called a label. Labels make sure things fire off at a particular point in time in the playhead of the animation. It looks like this:.add('labelName')

gsap   .timeline({     defaults: {       duration: 1.5     }   })   .add('start')   .to('.ball', {     x: 300,     scale: 2,     ease: "bounce"   }, 'start')   .to('.ball2', {     x: 300,     scale: 2,     ease: "bounce"   }, 'start')   .to('.ball3', {     x: 300,     scale: 2,     ease: "bounce"   }, 'start')

See the Pen
Greensock Tutorial 10
by Sarah Drasner (@sdras)
on CodePen.

We can even increment and decrement from the label. I actually do this a lot in my animations. It looks like this: 'start+=0.25'

gsap   .timeline({     defaults: {       duration: 1.5     }   })   .add('start')   .to('.ball', {     x: 300,     scale: 2,     ease: "bounce"   }, 'start')   .to('.ball2', {     x: 300,     scale: 2,     ease: "bounce"   }, 'start+=0.25')   .to('.ball3', {     x: 300,     scale: 2,     ease: "bounce"   }, 'start+=0.5')

Whew! We’re able to do so much with this! Here’s an example of an animation that puts a lot of these premises together, with a bit of interaction using vanilla JavaScript. Be sure to click on the bell.

See the Pen
phone interaction upgrade
by Sarah Drasner (@sdras)
on CodePen.

If you’re looking more for framework-based animation with GreenSock, here’s an article I wrote that covers this in Vue, and a talk I gave that addresses React — it’s a couple of years old but the base premises still apply.

But there’s still so much we haven’t cover, including staggers, morphing SVG, drawing SVG, throwing things around the screen, moving things along a path, animating text… you name it! I’d suggest heading over to GreenSock’s documentation for those details. I also have a course on Frontend Masters that covers all of these in much more depth and the materials are open source on my GitHub. I also have a lot of Pens that are open source for you to fork and play with.

I hope this gets you started working with animation on the web! I can’t wait to see what you make!

The post How to Animate on the Web With Greensock appeared first on CSS-Tricks.

CSS-Tricks

,
[Top]

Link Underlines That Animate Into Block Backgrounds

It’s a cool little effect. The default link style has an underline (which is a good idea) and then on :hover you see the underline essentially thicken up turning into almost what it would have looked liked if you used a background-color on the link instead.

Here’s an example of the effect on the Superfriendly site:

A journey:

  • The Superfriendly site does it with box-shadow. Turning box-shadow: inset 0 -0.07em 0 #0078d6; into box-shadow: inset 0 -0.85em 0 #a2d5fe; with a transition. Andres Cuervo ported that idea to a Pen. (I forked it to fix the “start offset” idea that was broken-seeming to me on the original).
  • You might be tempted to draw the line with a pseudo-element that’s, say, absolutely positioned within the relatively positioned link. Then you animate its height or scaleY or something. Here’s that kind of idea. Your enemy here is going to be links that break onto new lines, which box-shadow seems to handle more elegantly.
  • Another idea would be using linear-gradient with hard color stops to kinda “fake” the drawing of a line that’s positioned to look like an underline. Then the gradient can be animated to cover the element on hover, probably by moving its background-position. Here’s that kind of idea and another example we wrote up a little while back. This handles line breaks nicer than the previous method.
  • The default text-decoration: underline; has a distinct advantage these days: text-decoration-skip-ink! It has become the default behavior for links to have the underlines deftly skip around the decenders in text, making for much nicer looking underlines than any of these techniques (also: borders) can pull off. There are properties that are somewhat new that you may not be aware of that give you more control over the underline that we have traditionally had, like text-decoration-color. But there is more, like thickness and offset, that make this effect possible! Miriam Suzanne has a demo of exactly this, which only works in Firefox Nightly at the moment, but should be making the rounds soon enough.

Summary: If you need to do this effect right now in the most browsers you can, the box-shadow technique is probably best. If it’s just an enhancement that can wait a bit, using text-decoration-thickness / text-decoration-offset / text-decoration-color with a transition is a better option for aesthetics, control, and being able to understand the code at first glance.

The post Link Underlines That Animate Into Block Backgrounds appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Animate a Blob of Text with SVG and Text Clipping

I came across this neat little animation in a designer newsletter — unfortunately, I lost track of the source, so please give a shout out if you recognize it! In it, a block of text appears to bleed into view with a swirl of colors, then goes out the same way it came in. It’s a slick effect and one I wanted to recreate in code.

The approach I took was to use SVG text as a clip path for an SVG background. We must use SVG text because CSS currently only allows us to animate the background with text clipping if the background is a GIF, which we’re not going to do.

Our first task is to create a background of different SVG shapes. Oval-y blobs work pretty well. The thing to make sure of is to match the size the artboard/canvas in whatever illustration app you’re using to the same dimension as the viewBox you want the final work to be. (In Inkscape, this option is under the Scale section of Document Properties.)

The goal is to cover most of the artboard with a variety of shapes. I’ve found that it looks best if some of the shapes overlap.

Next, we’ll create some text in a <clipPath>, group the objects that make up the background inside a <g> element, and apply a CSS clip-path on that group. Altogether it looks something like this:

<svg viewbox="0 0 700 225">      <clipPath id="textClip" class="filled-heading">     <text y="70">We are</text>     <text y="140">Creators</text>     <text y="210">+Innovators</text>   </clipPath>       <g id="background" clip-path="url(#textClip)">     <path d="m449.78..." />        </g> </svg>

At this point, all we get is some plain text because we haven’t gotten around to the background animation quite yet.

So what about that animation? We can use a relatively simple CSS animation like this:

/* Animate the background shapes */ #background path {   animation: pulse 4s cubic-bezier(0.455, 0.030, 0.515, 0.955) infinite;    /* Necessary to keep the SVG objects in place while scaling */   transform-origin: 50% 50%;   transform-box: fill-box; }  @keyframes pulse {   /* Rotating it along with the scale makes it a little bit more fancy */   0%, 100% { transform: scale(0) rotate(33deg); }   35%, 65% { transform: scale(1) rotate(0deg); } }

So far, so good.

transform-box: fill-box; is not supported in Internet Explorer or Edge at this point, so if you need to support those browsers, you’ll need to use a JavaScript workaround, like this one.

See the Pen
Animated blob SVG text clipping effect – Pt. 1
by Zach Saucier (@Zeaklous)
on CodePen.

We could start painting things in by hard-coding color values using a text or vector editor, but it’s more fun to color the shapes dynamically. Something like this:

// Define an array of colors const colors = ['#f5a147','#51cad8','#112b39']; // Select the SVG paths var blobs = document.querySelectorAll("path");  // Randomly apply colors to the SVG fill property blobs.forEach(blob => {   blob.style.fill = colors[Math.floor(Math.random() * colors.length)]; });

In order to change the text values for each iteration, we need to first add them to the SVG clip path.

<clipPath id="text" class="filled-heading">   <text y="70">We are</text>   <text y="140">Creators</text>   <text y="210">+Innovators</text>      <text y="70">We are</text>   <text y="140">Movers</text>   <text y="210">+Shakers</text>      <text y="70">We are</text>   <text y="140">Stylish</text>   <text y="210">+Techy</text> </clipPath>

Then we can either use CSS or JavaScript to reveal the lines of text in our preferred order. Unfortunately, we can’t surround each section of <text> using a <g> element because <g> elements don’t work inside of a clipPath. For this post, we’re going to split things up into three CSS animations, one for each group of three paths:

/* Selects paths 1-3 */ #textClip text:nth-of-type(n + 1):nth-of-type(-n + 3) {   animation: showFirst 12s infinite; }  /* Selects paths 4-6 */ #textClip text:nth-of-type(n + 4):nth-of-type(-n + 6) {   animation: showSecond 12s infinite; }  /* Selects paths 7-9 */ #textClip text:nth-of-type(n + 7):nth-of-type(-n + 9) {   animation: showThird 12s infinite; }  @keyframes showFirst {   0%, 33% {     opacity: 1;   }   33.0001%, 100% { opacity: 0; } }  @keyframes showSecond {   33.0001%, 66% {     opacity: 1;   }   0%, 33%, 66.0001%, 100% { opacity: 0; } }  @keyframes showThird {   66.0001%, 99.999% {     opacity: 1;   }   0%, 66%, 100% { opacity: 0; } }

That does the trick!

See the Pen
Animated blob SVG text clipping effect – Pt. 2
by Zach Saucier (@Zeaklous)
on CodePen.

At this point, we can have a little fun. For example, we can swap backgrounds for a different effect. I used Inkscape’s star tool with three to four points to generate some random shapes (using Inkscape’s random parameter) and then colored them using a palette from one of the many color scheme generators (I used Palx) to produce this version:

See the Pen
Animated blob SVG text clipping effect – Pt. 3
by Zach Saucier (@Zeaklous)
on CodePen.

The backgrounds don’t even need to fill up the entire background, depending on the effect that we want to create. For example, we could duplicate the text using a element and fill in the text using that as seen in this demo.

Or we could mix it up by rotating the background blobs like this:

See the Pen
Animated blob SVG text clipping effect – Pt. 5
by Zach Saucier (@Zeaklous)
on CodePen.

To make the colors change for every new set of words, we could use either a CSS or JavaScript for the animation. I used JavaScript (and moved the CSS animation that was hiding the text lines to the JavaScript):

See the Pen
Animated blob SVG text clipping effect – Pt. 6
by Zach Saucier (@Zeaklous)
on CodePen.

To center the text horizontally, add x="50%" text-anchor="middle" to each <text> element (Demo). Centering it vertically would take more manual calculation since we’re working with a multi-line format.

One of the nice things about this approach is that, since it uses SVG, it is responsive by default!

P.S. After I made this approach and was looking for the original GIF author, I came across another recreation by Martí Fenosa doing the same effect using a different approach. Check his demo out as well because it’s clever!

The post Animate a Blob of Text with SVG and Text Clipping appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]