I really like the truth that CSS is lastly reclaiming management over visible interactions, taking cost of the styling, the animation, and the accessibility precisely because it ought to. At this time, native browser capabilities permit us to maneuver the heavy lifting away from the JavaScript primary thread and nearer to the GPU. By letting the browser’s engine optimize efficiency below the hood, we save power and processing energy whereas constructing code that’s strong, accessible, and unbiased of exterior libraries that may deprecate tomorrow.
We now have 3D, trendy structure methods, clip-paths, transforms, customized properties, scroll-driven animations, view-transitions, @property — and we are able to animate virtually something, even to auto-height!
And, after all, there’s SVG, which isn’t new, however permits us to construct total web sites by way of illustrations and animations. Take the instance beneath: it’s responsive, light-weight, accessible, and powered primarily by CSS Grid + SVG.
We are able to even construct an total online game together with the UI utilizing solely SVG:
What follows just isn’t an entire information to trendy CSS, however an opinionated number of methods I attain for once I need a web site to really feel alive and be remembered. There are lots of methods to create memorable experiences. Typically it’s so simple as a kind that completes easily. However right here I’m within the expressive finish of the spectrum.
Movement as Communication: Defining Your Intent
Earlier than we dive into the technical aspect, I wish to make clear one thing: we shouldn’t transfer issues simply because we are able to.
Every little thing communicates, and our animations are not any exception. We should take the time to design actions that assist the message we wish to convey with the intention to preserve our intents tightly scoped with out overdoing it.
Right here’s a technique I exploit when planning the design and animation of a web site.
Think about we’re engaged on a undertaking for a nature occasion centered on mushrooms. The design language adjustments utterly relying on the “vibe”: promoting a “Psychedelic Mushroom Rave” is worlds aside from a “Non secular Mushroom Retreat” centered on ancestral medication.
Each design resolution communicates. I prefer to create what I name key phrase lists to outline my intent and scope. For instance, I would break issues down into completely different choices:
Possibility A: The Psychedelic Occasion
- Visuals: Colourful, saturated, high-contrast, illustrations, distortions
- Motion: Quick, frantic, unpredictable, morphing, rhythmic, synced loops, hypnotic
- Feeling: Enjoyable, chaotic, energetic, stimulating, stunning
- Typography: Funk, “psych-rock”
- Type References: Pop Artwork, 60s/70s op artwork, rave flyers
- Actions: Dancing
- Extras: Emojis, movies (e.g., Worry and Loathing in Las Vegas)
Possibility B: The Non secular Retreat
- Visuals: Earth tones, impartial tones, de-saturated, photograph-heavy, nature, whitespace
- Motion: Gradual, fluid, natural, respiration, delicate parallax, easy scrolling.
- Feeling: Calm, serene, introspective, contemplative, protected
- Typography: Elegant Serif, minimalist sans-serif, huge spacing, legible
- Type References: Scandinavian design, Japanese Wabi-sabi, wellness/spa aesthetics, botanical books
- Actions: Respiration
- Extras: Therapeutic sounds, movie (e.g., Eat Pray Love)
That is the type of train I do to information my design and animation choices. The lists will assist me choose every thing from which CSS properties I plan to make use of and tips on how to use them. I even share them with the shopper and, collectively, we select a course.
Let’s say we go along with Possibility A and have a look at just a few examples of what I feel are important components for creating memorable consumer experiences.
Break up Textual content Animations
These animations grew to become well-liked due to the GSAP SplitText plugin. It splits textual content by character (or phrases, or strains in the event you like) so we are able to create attention-grabbing textual content results, like staggered animations.
This strategy wraps every letter in “Hola” in a span. From there, every span is inline-styled with a customized property indexing the spans so as. Which is one thing that may get rather a lot simpler when the sibling-index() operate positive aspects broad browser assist.
However for now, every customized property worth acts as a multiplier that will increase an animation-delay, staggering every span. On this case we fade in every character because it strikes up.
.reveal-text span {
animation: slideUp 0.6s ease-out forwards;
animation-delay: calc(var(--i) * 0.1s);
show: inline-block;
opacity: 0;
remodel: translateY(3rem);
}
@keyframes slideUp {
to {
opacity: 1;
remodel: translateY(0);
}
}
Accessibility is the difficult half right here. The intuition is to cover all the person spans from assistive know-how with aria-hidden="true" and add a visually hidden model of the total phrase for display screen readers:
.sr-only {
place: absolute;
width: 1px;
peak: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
However be warned: this sample doesn’t assure a superb expertise throughout all display screen readers. Adrian Roselli examined GSAP’s SplitText throughout eight display screen reader and browser mixtures and located it solely labored appropriately in two of them. Should you ship this method, check it with actual assistive know-how.
If that threat feels too excessive, there’s a really intelligent different from Preethi value understanding that makes use of the letter-spacing property. It accepts unfavourable values that collapse characters on prime of one another, hiding them with out touching the DOM in any respect. Animate it again to 0 and also you get an analogous reveal impact with out accessibility overhead.
What can be nice is a pseudo-selector like ::nth-letter to focus on particular person glyphs straight from CSS the way in which ::first-letter selects the primary character. However sadly, there’s no ::nth-letter… no less than but.
Keep in mind to respect the consumer’s movement preferences on each animation:
@media (prefers-reduced-motion: cut back) {
.reveal-text span {
animation: none; /* or a softer animation */
}
}
And right here we go:
It won't scale an excessive amount of when we've got numerous textual content and completely different animations we wish to apply. For the psychedelic occasion, I wished to attempt splitting textual content with SMIL, nevertheless it was verbose. That is the code for animating two letters alone:
Add position="img" and a to the , and wrap the person letters in . That provides display screen readers one clear label to learn. It really works effectively in some mixtures and badly in others, so if the textual content is important, don’t animate it.
Right here is the entire code. It’s simpler to put in writing it when you could have an AI to do it for you:
For longer textual content, a library like GSAP offers you extra management, however the identical accessibility dangers we mentioned earlier apply, and the outcomes throughout display screen readers are inconsistent:
const splitFirst = SplitText.create('.splitfirst', {
kind: "chars",
});
const splitLast = SplitText.create('.splitlast', {
kind: "chars, strains",
masks: "strains"
});
const tween = gsap.timeline()
.from(splitFirst.chars, {
xPercent: 100,
stagger: 0.1,
opacity: 0,
period: 1,
})
.from(splitLast.chars, {
yPercent: 100,
stagger: 0.1,
opacity: 0,
period: 1,
});
This may be a pleasant strategy for Possibility B if we had gone that route. See how “serene” issues really feel because the textual content fades in.
Masking & Clipping
The clip-path and masks properties permit us to cover parts of a component, however they work on essentially completely different rules. Clipping is a binary resolution: pixels are both absolutely seen or utterly gone, making it the best alternative for clear geometric shapes, like polygons, circles, or SVG paths, the place the browser also can optimize rendering extra effectively. Masking, however, makes use of luminance or alpha channel values: white reveals, black hides, and every thing in between produces partial transparency. This makes it the software for comfortable edges, gradient fades, and irregular textures. Remember the fact that when you've got a really complicated vector form, it could be extra performant to make use of a masks than a vector clip-path. Sarah Drasner has a pleasant write-up on when it is sensible to make use of one over the opposite.
Our undertaking is a really clear use case for clip-path. We now have a circle form that begins with clip-path: circle(0%), which makes the factor invisible (the clipping circle has zero radius). Over the period of the animation it expands to circle(100%), which absolutely reveals the factor because the circle grows outward from its heart. In the meantime, we fade issues in with the assistance of opacity.
#rainbow, #flooring, #mushroom, #flores {
opacity: 0;
animation: maskAnim 2s ease-in forwards;
}
@keyframes maskAnim {
0%, 1% {
clip-path: circle(0%);
opacity: 1;
}
100% {
clip-path: circle(100%);
opacity: 1;
}
}
Be aware: The 1% keyframe is there to verify the browser begins the clip-path interpolation from circle(0%) somewhat than from no matter worth the factor would possibly have already got. With out it, some browsers will unexpectedly soar on the very begin. A cleaner different is to make use of animation-fill-mode: each as a result of it locks the factor in its from state earlier than the animation begins.
From there, we apply the identical animation to the completely different SVG teams in our illustration:
...
...
...
...
How psychedelic is that this?!
Scroll-driven animations are nice as a result of we are able to join an animation’s progress to the consumer’s scrolling as a substitute of a typical timeline that runs and stops.
We are able to use it for delicate and considerably “trippy” motion, like a lightweight parallax impact. On this case, we are able to make issues that seem nearer to the consumer transfer sooner than those which are extra distant.
That is the total CSS:
#estrellas, #arcoiris, .text-line, #fecha, #arco, #flores, #dir, #piso, #barras {
animation: moveUp each;
animation-timeline: view();
}
@keyframes moveUp {
from { remodel: translateY(var(--offset)); opacity: 0; }
to { remodel: translateY(0); opacity: 1; }
}
#estrellas { --offset: 10vh; }
#arcoiris { --offset: 20vh; }
#fecha { --offset: 45vh; }
#arco { --offset: 50vh; }
#dir { --offset: 50vh; }
#flores { --offset: 65vh; }
#piso { --offset: 85vh; }
#barras { --offset: 90vh; }
The animation-timeline: view() says that issues ought to begin the animation as quickly as a component enters the scrollport when the consumer scrolls into it, and absolutely completes when it scrolls out of view. To make issues transfer at completely different velocities, we place them at completely different offsets utilizing an listed --offset customized property like we did earlier for splitting textual content.
3D Transforms
This one is trickier and we have to keep watch over efficiency. A software like Layoutit can assist carry the elevate as a result of it has a voxels and terrain generator constructed completely with CSS 3D. It may possibly go even additional when it’s complemented with VoxCSS, a full voxel engine that renders 3D cuboids utilizing solely CSS Grid layers and transforms with out the complexity of Canvas or WebGL.
Let’s put collectively some mixture scrolling and 3D results. It’s the type of factor that helps the “hypnotic” and “dancing” concepts within the Possibility A key phrase record. Examine this out:
Right here, I’ve arrange a scene with depth utilizing the perspective property after which wrap all of the youngster parts contained in the scene in a 3D house with transform-style: preserve-3d. This manner, all of the youngster picture parts rotate and translate alongside the depth axis (or z-axis).
Let’s join that to a scroll-driven animation that makes use of remodel: rotateY:
.scene {
perspective: 1200px;
}
.img-wrapper {
transform-style: preserve-3d;
animation: rotateImg linear;
animation-timeline: scroll();
> img {
remodel: rotateY(270deg) translate3d(0, 50px, var(--distance));
}
> img:nth-child(2) {
remodel: rotateY(180deg) translate3d(0, 50px, var(--distance));
}
}
/* and many others. */
@keyframes rotateImg {
to { remodel: rotateY(360deg); }
}
Customized Cursors
cursor could be probably the most unused CSS properties. There are many cursor varieties we are able to use, though there are undoubtedly opinions on simply how far to go along with this.
And we are able to use it to mess around with the pictures, displaying completely different cursors on completely different containers when the consumer hovers them. I might personally use an SVG and PNG picture for transparency assist, although the property helps any raster picture.
It’s value noting that cursor sizes range by browser: Firefox caps customized cursors at 32×32px, whereas Chrome helps as much as 128×128px. Most browsers refuse to show — or will downscale — cursors which are bigger than 32×32px on high-DPI (retina) screens. Preserving your cursor at 32×32px is the most secure alternative to make sure consistency.
For instance:
.box1 {
cursor: url(knowledge:picture/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAZCAMAAAD63NUrAAAACVBMVEX///8AAAD///9+749PAAAAAXRSTlMAQObYZgAAAFZJREFUeNqdzksKwDAIAFHH+x+6lIYOVPOhs5OHJnES/5UkYKEkU7xjijSIm50iFh4fAXgYDd/yumVVRSwsqq/nRA3xVK0oo06d5U6DpQZ7PV7lMxH7LkaQAbYFwryzAAAAAElFTkSuQmCC),auto;
}
We are able to even set a number of fallbacks to make sure the widest stage of browser assist:
physique {
cursor: url('path-to-image.png'), url('path-to-image-2.svg'), url('path-to-image-3.jpeg'), auto;
}
Whereas that is cool and all, we've got to maintain accessibility in thoughts for one thing that adjustments default net habits like this. Customized cursors might be enjoyable to use to very particular parts somewhat than wholesale throughout the board.
Bonus: Anchor Positioning
Another factor earlier than we wrap up. I’ve been taking part in with CSS Anchor Positioning, impressed by a Kevin Powell demo. We are able to use it to connect a single pseudo-element to a currently-hovered merchandise as a substitute of attaching a pseudo-element for every merchandise. In different phrases, we create a single factor and anchor it to a hovered factor, like highlighting playing cards:
That opens up attention-grabbing prospects, like with the ability to transition the hover state between playing cards. On this case, I’m utilizing the linear() operate to get that pure bounce with assist from Easing Wizard.
Conclusion
The technical obstacles for creating memorable net experiences are largely gone now. I hope every thing we’ve coated right here offers you an concept of simply how far we are able to go along with trendy CSS options that utterly take away the necessity for extra JavaScript. We now have extra prospects than ever earlier than, all with out the necessity for complicated technical overhead like days previous.
So, as a substitute of asking, is that this doable?, a very powerful query turns into, does this motion inform a greater story? If sure, ship it. Use these instruments not as a result of you possibly can, however as a result of they assist you inform a greater story, one which can also be accessible and performant.
And, after all, every thing in right here is only a handful of how to try this. However what kind of memorable experiences have you ever utilized in your work? Or what have you ever seen on different websites?





![How creators and entrepreneurs are utilizing AI to hurry up & succeed [data]](https://blog.aimactgrow.com/wp-content/uploads/2025/06/Untitled20design-Apr-07-2023-08-24-35-4586-PM-120x86.png)



