Free · Fast · Privacy-first

CSS Translate Transform

The CSS translate() function moves an element from its current position without affecting surrounding elements in the document flow.

Supports px, %, em, rem, and vw/vh length units

🔒

translateX and translateY for single-axis motion

Percentage values relative to the element for size-independent centering

GPU-composited: no layout cost on transition or animation

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local
FreeNo signupWhite-label

Add this Transform Gen to your website

Drop the Transform Gen 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.

  • Files stay 100% in the visitor's browser
  • Responsive — adapts to any container width
  • Free forever, no API key needed

Embed code

<iframe
  src="https://www.fixtools.io/css-tool/transform-gen?embed=1"
  width="100%"
  height="780"
  frameborder="0"
  style="border:0;border-radius:16px;max-width:900px;"
  title="Transform Gen by FixTools"
  loading="lazy"
  allow="clipboard-write"
></iframe>

Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.

How translate() Differs from margin and position, and Why Percentage Values Enable Centering

CSS positioning properties like left, top, margin-left, and margin-top all affect document flow in some way. Changing margin-top pushes the element down and pulls all subsequent siblings with it. Changing top on a positioned element moves it visually but causes a repaint and in some cases a layout recalculation. Changing transform: translateY() moves the element visually without touching its layout box. The element's original space in the document remains unchanged, and no sibling elements are affected. This makes translate the only correct approach for animated motion: it provides pure visual movement at compositor speed without the side effects of layout property changes.

Percentage values in translate() are calculated relative to the element itself. translate(50%, 0) moves an element to the right by half of its own width, regardless of the parent container size. This is distinct from left: 50%, which is calculated relative to the containing block. The self-relative calculation is what makes translate(-50%, -50%) the canonical CSS centering technique. Paired with position: absolute and top: 50%; left: 50%, it places the element's top-left corner at the container center, then shifts the element back by half its own width and height, centering it precisely. This works regardless of the element's dimensions, unlike negative margin centering which requires knowing the element's size in advance.

translateZ() moves an element along the Z axis, toward or away from the viewer in 3D space. Positive values bring the element closer and make it appear larger under perspective projection; negative values push it back and make it appear smaller. translateZ() requires a perspective context on the parent to produce a visible effect. It is used to layer elements in 3D scenes, create depth in card stacks, and simulate parallax scrolling. translate3d(x, y, z) is the shorthand form that sets all three axes at once and is marginally more efficient than writing separate translate and translateZ values because it generates a single matrix operation.

Translate is the cheapest transform from a paint perspective because the browser does not need to re-rasterize the element to apply a new offset. The compositor simply repositions the existing texture on the GPU. This is what makes drag-and-drop interactions feel instant when implemented with transform: translate() driven by pointer events. Compare that to changing left and top during drag, which forces a relayout for every pointer move event and noticeably stalls on lists with more than a few dozen items. For high-frequency motion like scroll-linked animations or pointer-tracking effects, translate combined with transform: translate3d(0, 0, 0) on the moving element guarantees a stable compositor layer that the GPU can update at refresh rate without dropping frames.

How to use this tool

💡

Enter X and Y offset values and select the unit from the dropdown. Use the axis buttons to switch to translateX or translateY for single-axis movement. Preview the offset in the canvas and click Copy Code to export the CSS.

How It Works

Step-by-step guide to css translate transform:

  1. 1

    Enter offset values

    Type X and Y offset values in the input fields. Positive X moves right, negative X moves left. Positive Y moves down, negative Y moves up.

  2. 2

    Choose the unit

    Select px for fixed offsets, % for size-relative offsets, or em/rem for typography-relative movement. Percentage is most useful for centering and responsive motion.

  3. 3

    Switch to single-axis if needed

    Click the translateX or translateY button to generate a single-axis function instead of the two-value translate(). This produces cleaner code when only one axis of movement is needed.

  4. 4

    Copy and apply

    Click Copy Code to copy the translate declaration. Add it to your selector or keyframe stop. Pair with transition: transform for interactive motion.

Real-world examples

Common situations where this approach makes a real difference:

Centering a modal dialog

A modal needs to be centered both horizontally and vertically without knowing its dimensions at authoring time. The developer sets position: fixed; top: 50%; left: 50% on the modal, then uses the generator to produce transform: translate(-50%, -50%). This shifts the modal back by half its own width and height, centering it precisely. The approach works regardless of modal content length because the percentage translate always refers to the modal's current dimensions.

Slide-in notification toast

A toast notification enters from the bottom-right of the screen. The base state uses transform: translateY(120%) to hide the toast below the viewport. When a notification arrives, a show class is added that sets transform: translateY(0). The transition: transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1) on the base element gives the entrance a slight overshoot bounce that feels lively. The generator is used to confirm translateY(120%) is enough to push the toast fully off-screen.

Animated tab indicator underline

A tab bar has an underline indicator that slides to the active tab. The indicator is an absolutely positioned div that uses translateX() to move to the correct tab position. JavaScript calculates the X offset of the active tab and sets a CSS custom property. The CSS reads transform: translateX(var(--tab-offset)). The generator is used during development to test specific offset values and confirm the transition timing looks right before the JavaScript calculation is written.

Parallax scroll layer offset

A landing page background layer scrolls slower than the foreground content to create a parallax effect. JavaScript reads window.scrollY and sets a CSS custom property equal to scrollY multiplied by a parallax factor of 0.4. The background layer uses transform: translateY(var(--parallax-y)). The developer uses the generator to test what translateY values look appropriate at different scroll depths before writing the scroll listener. Translate is used specifically because it runs on the compositor and produces smooth scrolling.

Pro tips

Get better results with these expert suggestions:

1

Centering with translate is immune to size changes

The pattern position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) centers an element in its container regardless of the element's dimensions. Unlike margin-based centering, it requires no knowledge of the element's width or height. This makes it robust for dynamic content where the element size is unknown at authoring time, such as tooltips, popovers, and modals with variable content.

2

Use the standalone translate property to compose with other transforms

CSS Transforms Level 2 introduced a standalone translate property. Writing translate: -50% -50% does not override a transform: rotate(45deg) on the same element. The two properties compose automatically. This is valuable in animation scenarios where a keyframe animation controls rotation while JavaScript or a state class controls the position independently, without each overriding the other.

3

Percentage translate values are relative to the element, not the parent

This is the most commonly misunderstood aspect of translate. translate(10%, 0) moves the element by 10% of its own width. left: 10% would move it by 10% of the parent width. For an element that is 200px wide inside a 1000px container, translate(10%, 0) moves it 20px while left: 10% would move it 100px. Always factor this into calculations when combining translate with other positioning properties.

4

Slide-out animations need a matching transition on the base element

If you add transform: translateX(100%) to a leaving class and want the slide-out to animate, the transition must be on the base element selector, not only on the leaving class. The browser applies the transition when the computed transform value changes from the base state to the leaving state. If transition is only on the leaving class, the element may snap directly to the translated position without animating.

5

Use translate for all motion animations, not left or top

Moving an element by changing left or top triggers layout recalculation on every frame. Changing translate moves the element on the compositor with no layout cost. Replace all animated left/top changes with translateX/translateY. The visual effect is identical but the performance is dramatically better, especially on mobile.

6

Combine translate with opacity for slide-in animations

A slide-in effect transitions translateX(-20px) to translateX(0) while opacity goes from 0 to 1 over 250ms. Both properties run on the compositor. The small translate distance prevents the element from appearing to teleport in from far off-screen. The opacity fade softens the entrance and makes the motion feel natural.

7

Use translate3d instead of translateZ alone for promotion hints

Some older browser heuristics promote elements to a compositor layer when they use translate3d but not translateZ. Writing translate3d(0, 0, 0) is a well-known forced-promotion hack. Modern browsers handle this automatically for animated transforms, but if you encounter a specific jank issue, translate3d(0, 0, 0) on a static element can force promotion as a last resort.

FAQ

Frequently asked questions

The translate() function accepts any CSS length unit: px for fixed pixel values, % for values relative to the element's own size, em for values relative to the element's font size, rem for values relative to the root font size, and viewport units like vw and vh. Percentage values are the most distinctive because they reference the element itself rather than the parent container. translate(-50%, -50%) always shifts the element by exactly half its own width and height regardless of what size it is.
Left and top change the element's position in the layout coordinate system and can trigger layout recalculation. translate() changes only the visual rendering position without touching the layout box. The element still occupies its original layout space. Additionally, translate is processed by the GPU compositor when animated, meaning the browser does not need to run layout or paint on each animation frame. Animating left or top forces CPU-side layout work on every frame, which is significantly more expensive.
When combined with position: absolute; top: 50%; left: 50%, the top and left values place the element's top-left corner at the center of its containing block. The element is then off-center because it extends to the right and down from that point. translate(-50%, -50%) moves the element left by half its own width and up by half its own height, which shifts its center to align with the containing block's center. Because the percentage is relative to the element, this works for any element size.
They are identical in effect. translateX(50px) and translate(50px, 0) both move the element 50px to the right. translateX() is cleaner when you only need horizontal movement. The same applies to translateY(): it is equivalent to translate(0, n). Use the single-axis forms when the intent is unambiguous and you want to avoid writing an explicit zero for the unused axis.
Yes. A large translate value will move the element visually outside the viewport. The element still occupies its original layout space, so it will not collapse the document. This is used for slide-out animations: translating an element beyond the viewport edge hides it without removing it from the DOM. Use overflow: hidden on the body or a wrapper element to prevent scrollbars from appearing when the translated element is outside the normal scroll area.
Yes. translateZ(n) moves the element along the depth axis in 3D space. Positive values bring the element closer to the viewer under perspective projection, making it appear larger. Negative values push it back. This only produces a visible effect when a perspective context is set on a parent element. translate3d(x, y, z) is the three-axis shorthand that combines translateX, translateY, and translateZ into one function call. The browser computes a single matrix operation for translate3d, which is marginally more efficient than separate functions.
No. Since translate does not change the layout position, it does not affect scroll boundaries. An element translated beyond the viewport with transform: translateX(200vw) does not cause horizontal scrolling because the browser uses the element's original layout position to compute scroll area, not the translated visual position. If you want the translated position to cause scrolling, you must use left or margin instead. This is also why hiding elements off-screen with translate requires overflow: hidden on a parent to prevent visible overflow.
When you provide one value to translate(), the second value defaults to 0. translate(50px) is equivalent to translate(50px, 0). For clarity, prefer translateX(50px) when you only intend horizontal movement, as it makes the intent explicit. The two-value form translate(50px, 30px) is required when moving on both axes simultaneously. Mixing units is also valid: translate(50px, 10%) moves 50 pixels horizontally and 10% of the element's own height vertically.
No. The standalone translate property introduced in CSS Transforms Level 2 composes with the transform property rather than overriding it. An element can have transform: rotate(45deg) and translate: 50px 0 simultaneously, and both apply. This is different from having two rules that both set the transform property: the latter rule wins and overrides the former. The standalone translate, rotate, and scale properties were added specifically to allow independent composition without conflicts in design systems and animation libraries.
Wrap the transition on the base element in @media (prefers-reduced-motion: no-preference) so the slide motion only applies when motion is permitted. For users who have requested reduced motion, set the element to its final translate position directly without any transition. A pure opacity fade is an acceptable fallback that conveys entrance without lateral motion, which is the most disorienting type for users with vestibular conditions. Avoid bouncy easing curves for translate animations entirely when reduced motion is requested, since overshoot bounces are particularly uncomfortable. The media feature is supported in every modern browser back to 2019.
Any non-default transform on an element, including translate, creates a containing block for fixed-position descendants. The fixed child anchors to the transformed parent rather than to the viewport, breaking the expected sticky-to-viewport behavior. This is defined by the CSS specification and behaves identically in Chrome, Firefox, and Safari. The fix is to portal the fixed element out of the transformed parent into the document body using a React portal, a Vue teleport, or plain DOM appendChild. Alternatively, remove the translate from the parent and apply it elsewhere. The standalone translate property has the same effect.

Related guides

More use-case guides for the same tool:

Ready to get started?

Open the full Transform Gen — free, no account needed, works on any device.

Open Transform Gen →

Free · No account needed · Works on any device