Have you ever tried to animate a container’s width or height with Motion and run into this? The container just snaps to its new size. The text animates in fine, but the container itself jumps. That’s because width and height are not animatable when set toDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/raphaelsalaja/userinterface-wiki/llms.txt
Use this file to discover all available pages before exploring further.
auto. The browser doesn’t know how to interpolate between a fixed value and “whatever the content needs.”
A smoother approach has the container animate to fit the content. So how do we achieve this?
Building a useMeasure Hook
Before we get into the animation part, we need a way to track an element’s dimensions. The browser has a native API for this calledResizeObserver. It watches an element and fires a callback whenever its size changes. We can wrap this in a small hook.
ref callback and a bounds object. Attach the ref to any element and bounds will always reflect its current width and height. When the content inside that element changes and causes a resize, the observer fires, state updates, and your component re-renders with the new values.
Integrating with Motion
Now for the animation. The core idea is two divs. An outer div that you animate, and an inner div that you measure. Attach theref from useMeasure to the inner div, the hook gives you bounds.width and bounds.height which update whenever the content changes, pass those values to Motion’s animate prop on the outer div.
Animating Width
Buttons that change their label are a common use case. Loading states, confirmation messages, multi-step forms. Without animated bounds the button jumps between widths. With this pattern, it slides.One thing to note is that I’m checking
bounds.width > 0 before animating. This avoids an animation from 0 on the initial render. You want the first frame to just show the button at its natural size, not animate in from nothing.Animating Height
Height is where this pattern really shines. Expandable sections, accordions, FAQs, details panels. Anywhere content reveals or hides itself. The same pattern applies. Measure the inner content, animate the outer container.Gotchas
Finally, don’t overuse this pattern. It’s a subtle effect that should be used sparingly. Use it when it makes sense, like for buttons, accordions, or other interactive elements.
Resources
- ResizeObserver - MDN documentation
- react-use-measure - Alternative library maintained by Poimandres