Développement

15 CSS micro-interactions without a single line of JavaScript (which required a lib yesterday)

The underline that slides, the map that flips to 3D, the animated input without display: none cobbled together: 15 micro-interactions in pure CSS, at 60 fps, without a single line of JavaScript.

5 déc 20258 min de lecturePASCAL POTVIN
Écouter l'article

The invisible detail that no longer requires JavaScript

Micro-interactions are what separate a functional interface from a memorable one: a button that responds to a hover, an underline that slides, an element that lights up on focus. They are not decorative - they provide the feedback that guides the user and signals what is interactive. What has changed, and this is the whole point of 2026, is that we now code them without JavaScript. The effects for which I used to import an animation library two years ago now fit into a few lines of CSS, and run at 60 frames per second without touching the main thread.

Here I present fifteen effects I use regularly, grouped into three families. The aim is not to copy them as they are, but to understand how they work so that you can create your own variations.

Five text and underline effects

My favorite is animated underlining via pseudo-element: a line that extends under the word using a transform: scaleX transition, with the origin on the left so that the animation starts from the beginning.

css .link { position: relative; } .link::after { content: ""; position: absolute; left: 0; bottom: -2px; width: 100%; height: 2px; background: currentColor; transform: scaleX(0); transform-origin: left; transition: transform .25s ease; } .link:hover::after { transform: scaleX(1); }


The other four follow the same philosophy: a split text color where a pseudo-element with clip-path reveals a second color from left to right; a fat animation via variable font, where the @property rule makes font-variation-settings interpolable to go from 400 to 700 without jumping; a shimmer combining background-clip: text and a background-position animation; and an elevation effect where the text rises a few pixels in translateY while a soft shadow appears. All are based on transform, opacity and color - so they're free on the performance side.

## Five effects for buttons and cards

The sweep button is a timeless classic: a pseudo-element that expands from 0 to 100% of the surface in scaleX on hover. The gradient border rotation uses an animated conic-gradient via @property for a continuously rotating gradient border. The card tilt in 3D perspective is the most impactful: a perspective on the parent, a subtle rotateX/rotateY on the card, a scale(1.02) and a box-shadow that intensifies to give a physical materiality. I add the glassmorphism intensify - backdrop-filter: blur() which goes from 8 to 16 pixels at the hover - but sparingly: it only makes sense on a content-rich background, and falls flat on a plain surface. The fifth plays on a drop shadow that unfolds to suggest elevation.

## Five effects with the new CSS specifications

This is where 2026 makes the difference. Clip-path morph deforms a shape on hover by animating the coordinates of a polygon() - provided the same number of points are used in both states. Staggered child animation shifts the animation of each child according to its index, triggered by the parent using the :has() selector, now Baseline. border-radius morph transforms a rectangle into an organic blob by transitioning asymmetrical radii.

But the real gift is the animated, no-frills input. The @starting-style rule coupled with transition-behavior: allow-discrete has become Baseline with Firefox 129 - finally allowing you to animate an element that appears from display: none, which required JavaScript yesterday.

css
.toast {
  opacity: 1;
  transition: opacity .3s, display .3s allow-discrete;
}
@starting-style {
  .toast { opacity: 0; }
}

There's still one wall that's just fallen down: animate to height: auto. The interpolate-size properties and the calc-size() function make it possible - an accordion that opens smoothly without knowing its height in advance. Beware, however: this isn't Baseline yet, so I use it as a progressive enhancement with a fallback, never as a base.

Performance and accessibility: the two non-negotiable rules

The performance of CSS animations hinges on a single rule: never animate a property that triggers a layout recalculation. transform, opacity and filter are composed by the GPU and run at 60 frames per second without blocking the main thread; animating width, height, top, left, padding or margin causes costly reflows. will-change prepares the browser but consumes GPU memory - use sparingly, and remove after animation.

!prefers-reduced-motion is not optional

All animation must respect prefers-reduced-motion. A single global block that forces durations to zero for sensitive users covers the entire site - and this isn't an option, it's an accessibility obligation. Motion that delights the majority can trigger nausea in others.

Two words on the near horizon. Scroll-driven animations link an animation to scrolling via scroll() and view(); they've been running in Chrome and Edge since 115 and in Safari 26, but remain behind a flag in Firefox - this is precisely one of the Interop 2026 projects, the joint effort of the three engines to align their support. CSS Anchor Positioning is already delivered in Safari and Chrome (Firefox in progress): tooltips, popovers and contextual menus are positioned and animated in pure CSS, without JavaScript position calculation. The basic lesson remains the same: modern CSS has reached the point where the majority of micro-interactions do not require JavaScript, which makes for lighter code, better performance and simpler maintenance. The best ones are those that the user feels without being able to name them. Less is more: aim for subtlety, not spectacle.

§ COMMENTAIRES

Laisser un commentaire