Hover effects seem simple until you need to choose between a CSS transition and a CSS animation, or until a multi-step hover sequence reverses incorrectly when the cursor leaves.
Loading Animation Builder…
Live preview element you can hover directly in the tool
Side-by-side mode comparing transition and animation approaches
Control over enter and exit sequences independently
Generates complete :hover CSS for both approaches
Drop the Animation Builder into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.
Embed code
<iframe
src="https://www.fixtools.io/css-tool/animation-builder?embed=1"
width="100%"
height="780"
frameborder="0"
style="border:0;border-radius:16px;max-width:900px;"
title="Animation Builder by FixTools"
loading="lazy"
allow="clipboard-write"
></iframe>Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.
A CSS transition interpolates between two states when a property value changes. For hover effects, that change happens when the :hover pseudo-class activates, and the reverse happens when the cursor leaves. The transition is defined on the base element selector, not on the :hover selector: transition: transform 250ms ease-out on the element tells the browser to animate any transform change smoothly. When :hover adds a transform value, the transition plays forward. When :hover is removed, the same transition plays in reverse automatically. This automatic reversal is the defining feature of transitions: they require no separate exit animation and always return cleanly to the base state. A CSS animation by contrast runs a @keyframes sequence independently. The animation can be placed on the :hover selector to start when the cursor enters, but when the cursor leaves and :hover is removed, the animation stops immediately and the element snaps back to its base style unless a separate exit animation is defined.
When to use transitions for hover effects: any single-step property change that should reverse cleanly when the cursor leaves. This covers the vast majority of UI hover effects: colour changes on buttons and links, scale increases on cards, shadow lifts, border-radius changes, and opacity shifts on overlay labels. Transitions handle these with two declarations (one on the base element, one on :hover) and the browser manages the interpolation in both directions with no additional code. The transition approach is correct when the exit should exactly mirror the entrance.
When to use animation on hover: multi-step effects with distinct enter sequences, effects that should complete regardless of whether the cursor stays, or enter and exit sequences that are intentionally different. An example is a button where hovering triggers an underline that sweeps from left to right (not just appearing), and removing hover triggers a separate sweep from right to left. Both sequences require separate @keyframes blocks, and the enter animation is applied on :hover while the exit animation is applied using a class toggled by JavaScript. CSS alone cannot define a separate exit animation for :hover removal; JavaScript is required to add the exit class before the :hover state clears.
Touch device behaviour is the most overlooked factor in hover animation design. Mobile and tablet users have no cursor, and the way mobile browsers expose the :hover state is inconsistent and frequently surprising. iOS Safari triggers :hover on the first tap and clears it on the next tap elsewhere, meaning a hover animation may stick visibly after the user interacts. Android Chrome behaves differently in different versions. The reliable solution is to wrap all hover animation rules in a media query that targets devices with a real pointer: @media (hover: hover) and (pointer: fine). Outside that query, provide tap feedback through :active states or focus-visible styles instead. This separation keeps the desktop experience polished while preventing the sticky-hover bug on touch devices that frustrates mobile users and looks like a stylesheet error.
Choose transition or animation mode. For transitions, set the property, duration, and easing. For animations, build the @keyframes enter sequence and optionally a separate exit sequence. Hover over the preview to test, then copy the code.
Step-by-step guide to css hover animation:
Choose transition or animation approach
Select transitions for simple property changes that should reverse on hover-out. Select animations for multi-step hover sequences or effects that should complete regardless of cursor position.
Define the hover state
For transitions: set the target property value in the :hover selector and the transition duration and easing on the base selector. For animations: build the @keyframes enter sequence and set it on the :hover selector.
Test the hover in the live preview
Hover over the preview element to test the enter sequence. Move the cursor away to test the exit. Verify that the exit is smooth and complete for transitions, or that the animation behaves correctly when interrupted for animations.
Copy the generated CSS
Click Copy Code. For animation-based hover effects, add a JavaScript class toggle if you need a custom exit animation sequence separate from the CSS :hover removal snap-back.
Common situations where this approach makes a real difference:
Product card hover lift
An e-commerce developer adds a card lift using transition: transform 180ms ease-out, box-shadow 180ms ease-out on the card. The :hover state adds translateY(-6px) and an elevated box-shadow. The transition reverses automatically on hover-out. No JavaScript is needed. The 180ms duration matches the speed of a mouse movement, making the card feel responsive to the cursor rather than delayed.
Navigation link underline sweep
A design agency site uses a CSS animation on nav link :hover to sweep an underline from left to right using a scaleX(0) to scaleX(1) @keyframes on a ::after pseudo-element. The enter animation plays in 200ms. On hover-out, a JavaScript mouseleave handler applies a reverse-sweep class that plays the exit animation before removing both classes, giving the underline a directional sweep both in and out.
Icon button scale and colour shift
A dashboard toolbar uses transition: transform 150ms ease-out, color 150ms ease-out on icon buttons. The :hover state adds scale(1.12) and a blue accent colour. The transition approach handles both properties simultaneously with one declaration per property. The 150ms duration makes the response feel immediate, matching the fast interaction tempo of a toolbar used repeatedly throughout a session.
Feature list item reveal
A pricing page feature list uses a hover animation that slides a background highlight from left to right across each list item using a scaleX keyframe on a positioned ::before pseudo-element. The animation plays on :hover and completes in 250ms. Because the cursor may leave before the animation finishes, animation-fill-mode: forwards holds the highlight in the completed state briefly, making the interaction feel deliberate rather than interrupted.
Use this when building card hover lifts, button colour transitions, link underline reveals, or any multi-step hover sequence that needs to play a specific enter or exit sequence rather than simply reversing.
Get better results with these expert suggestions:
Use transition for hover, animation only when the exit needs custom behaviour
The default choice for any hover effect should be a CSS transition. Reach for @keyframes hover animations only when the exit sequence cannot be a simple reversal. Transitions require less code, have no snap-back issue, and are easier for other developers to read and maintain in a shared stylesheet.
Apply transition to specific properties, not all
Using transition: all is tempting but dangerous. It causes the browser to interpolate every CSS property change, including unintentional ones triggered by JavaScript or parent state changes. Specify exactly which properties should animate: transition: transform 200ms ease-out, box-shadow 200ms ease-out. This gives predictable behaviour and avoids unexpected transitions when other styles change.
Test hover animations at 0.25x speed in DevTools
Open the Animations panel in Chrome DevTools, hover the element, and set playback to 25%. This reveals whether the easing curve is correct at each stage and whether the exit reversal is smooth. Issues that appear as a slight jank at full speed become obvious at slow motion and are much easier to debug before shipping.
Account for rapid cursor movement in hover animation design
Users sometimes move the cursor quickly across multiple elements. Test what happens when the cursor enters and exits an element within 50ms, before any animation starts or completes. Transitions handle this cleanly by reversing mid-play. Animations may leave an element in an intermediate state if the class is removed before the @keyframes finishes. Design for rapid mousing by keeping hover animations under 250ms.
More use-case guides for the same tool:
Other tools you might find useful:
CSS Transform Generator
Build transform values to use inside your keyframes.
CSS Gradient Generator
Generate gradient backgrounds for animated elements.
HTML Element Builder
Build the HTML element you want to apply your animation to. Test hover animations on touchscreens to verify they degrade gracefully. Hover effects should never be the only feedback signal for an interaction. For touchscreen users, hover styles map to focus styles after tap. Design hover effects with this fallback in mind so the interface still feels responsive even without a true hover interaction.
Open the full Animation Builder — free, no account needed, works on any device.
Open Animation Builder →Free · No account needed · Works on any device