Free · Fast · Privacy-first

CSS perspective

CSS perspective controls the depth effect applied to 3D transforms.

Live comparison between perspective property and perspective() function

🔒

Adjustable distance value with depth preview

perspective-origin control for vanishing point placement

Side-by-side output for container and element CSS

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.

CSS Perspective Property vs Function, Distance Values, and Vanishing Point Control

The perspective CSS property is applied to the parent container of the elements you want to appear in 3D space. Writing perspective: 600px on a div makes all children with 3D transforms share the same depth context and vanishing point. When you rotate child A with rotateY(30deg) and child B with rotateY(-30deg), both rotate as if viewed from the same position 600px away, so they look like two sides of the same object seen from a single eye point. This is the correct setup for any 3D scene with multiple elements such as card grids with hover depth, CSS cubes, or 3D carousels. The perspective property does not apply to the container itself, only to its direct and indirect 3D-transformed children.

The perspective() function is placed inside an element's own transform list: transform: perspective(600px) rotateY(30deg). This applies a perspective context to that specific element independently. If two elements both have perspective() in their transform lists, each uses its own independent vanishing point. They do not share depth context, so they will not look like parts of the same 3D object when placed side by side. Use perspective() on an element only when that element needs 3D depth without any relationship to other elements in the same container. A single animated card that has no sibling elements needing matching depth is a valid case for the function form.

The perspective-origin property defines where the viewer's eye is positioned relative to the perspective container. It defaults to 50% 50%, placing the eye at the container center, which means 3D elements appear as if viewed straight-on from the middle. Moving perspective-origin to 0% 0% shifts the view to the top-left corner, giving a strong angular perspective. Changing perspective-origin to values outside 0 to 100% creates extreme off-screen vanishing points that can look cinematic but may disorient users on functional UI elements. The generator provides a draggable perspective-origin control so you can position the vanishing point interactively.

Setting perspective on a container has a measurable cost beyond the depth math itself. The browser must establish a 3D rendering context, which promotes the container and any 3D-transformed descendants to compositor layers. On Chromium engines the container also becomes a containing block for fixed-position descendants, which surprises developers who expect their fixed modals to anchor to the viewport. Firefox and Safari follow the same specification but differ in how aggressively they flatten descendants when intermediate properties like opacity or filter appear in the tree. To keep perspective performant, apply it to a single scoped container that holds exactly the 3D children that need it, not to the body or a top-level layout wrapper that wraps unrelated content. Removing perspective when 3D animations finish releases the GPU layers.

How to use this tool

💡

Enter a perspective distance value and adjust the perspective-origin X and Y positions. Use the toggle to switch between the perspective property on the parent and the perspective() function on the element. Preview the depth change in real time and copy the appropriate CSS form for your use case.

How It Works

Step-by-step guide to css perspective:

  1. 1

    Choose the perspective form

    Decide whether to use the perspective property on the parent container (for multiple child elements sharing depth) or the perspective() function on the element itself (for a single isolated 3D element).

  2. 2

    Set the distance value

    Enter a numeric pixel value. Start at 600px and increase for subtler depth or decrease for more dramatic foreshortening. Preview updates in real time.

  3. 3

    Adjust perspective-origin

    Drag the vanishing point control or enter X and Y percentages to shift where the viewer appears to be looking from. Default center is 50% 50%.

  4. 4

    Copy the output

    Click Copy Code to export the perspective declaration. If using the property form, the output includes both the container rule and a sample child element rule with a 3D transform.

Real-world examples

Common situations where this approach makes a real difference:

Shared perspective for a 3D card grid

A portfolio grid has twelve cards that all tilt slightly toward the mouse cursor. The developer sets perspective: 800px on the grid container so all cards share the same vanishing point. JavaScript updates each card's rotateX and rotateY based on cursor distance. Because perspective is on the container, all cards tilt in a coordinated way that makes the grid feel like a physical surface rather than twelve independent floating elements.

Single product card with isolated depth

A standalone product hero element needs a subtle 3D tilt on mouse entry. No other elements on the page use 3D. The developer uses perspective(700px) in the element's transform list rather than setting perspective on a parent that contains unrelated elements. The isolated function form keeps the 3D context scoped to the single element without creating an accidental perspective context for other children of the parent.

Off-center perspective for cinematic hero

A landing page hero section features a 3D tilted device mockup. The designer wants the depth to look as if viewed from the bottom-left for a dynamic composition. The developer sets perspective: 900px on the hero section and perspective-origin: 20% 80%. The device mockup tilts more dramatically on its right and top edges. The generator is used to preview different perspective-origin values until the composition matches the design mockup.

Interactive depth slider for a demo widget

A CSS tutorial page includes an interactive widget where the user drags a slider to adjust the perspective depth and see how different values affect the 3D rotation of a sample element. The developer stores the perspective value in a CSS custom property and uses a range input to update it via JavaScript. The generator provides the initial CSS setup including the custom property declaration, perspective: var(--depth) on the container, and the sample rotateY transform on the child element.

Pro tips

Get better results with these expert suggestions:

1

Scale perspective value proportionally to element size

The perceived depth effect is relative to the element size. A perspective of 400px produces dramatic depth on a 100px card but barely visible depth on a 600px card. A useful heuristic is to set perspective to three to five times the width of the element being transformed. This maintains a consistent depth-to-size ratio across different component sizes in a design system.

2

Avoid setting perspective on the body element

Setting perspective: 600px on the body creates a perspective context that applies to all 3D-transformed elements on the page simultaneously. While convenient, this causes unintended depth effects on any element with a 3D transform, including those that were designed for independent depth. Always scope the perspective property to the specific container that holds the 3D elements it should affect.

3

perspective-origin: 50% 50% is the browser default, so you can omit it

You only need to declare perspective-origin when you want a non-center vanishing point. Many tutorials redundantly include perspective-origin: 50% 50% or perspective-origin: center center. These are identical to the browser default and produce no visual difference. Remove them from your final CSS to keep the stylesheet clean.

4

Combine perspective with CSS custom properties for interactive depth controls

Storing the perspective value in a CSS custom property like --depth: 600px and referencing it as perspective: var(--depth) allows JavaScript to update the depth dynamically. This technique is used for depth parallax effects where scrolling adjusts the perspective to simulate forward motion, changing --depth from 800px to 400px as the user scrolls makes the depth effect intensify progressively.

5

Use 400px to 800px for most UI 3D effects

A perspective of 400px to 800px produces clear, readable depth on most element sizes used in web UI. Values below 300px look exaggerated and uncomfortable for interactive elements. Values above 1200px may produce depth that is too subtle for users to notice. Test the specific element size before deciding on the final value.

6

Move perspective-origin to match interaction direction

If a card grid tilts toward the mouse cursor, the perspective-origin should follow the cursor position dynamically. Setting a static perspective-origin at the container center works for symmetrical tilt effects, but for cursor-tracking depth, update perspective-origin-x and perspective-origin-y via JavaScript on mousemove.

7

perspective: none disables 3D depth projection

Setting perspective: none on a container disables the perspective projection, which effectively flattens all 3D transforms to orthographic projection. This is useful when you need to temporarily disable depth effects on a component without removing the 3D transform values from child elements.

FAQ

Frequently asked questions

The perspective property is set on the parent element and creates a shared depth context for all 3D-transformed children. They all share one vanishing point, making them appear to exist in the same 3D space. The perspective() function is used inside an element's own transform list and creates an independent depth context for that element only. Elements with their own perspective() function do not share depth with siblings. Use the property for multi-element 3D scenes; use the function for a single isolated 3D element.
The perspective value represents the conceptual distance from the viewer's eye to the z=0 plane of the 3D scene, measured in CSS pixels. A value of 400px places the viewer relatively close to the elements, producing dramatic foreshortening where elements at different Z depths look very different in size. A value of 1200px places the viewer far away, producing subtle depth where size differences between Z depths are minimal. The correct value depends on the desired visual intensity of the depth effect and the physical size of the elements.
No. Children that do not have 3D transform functions applied to them are unaffected by the parent's perspective property. Only children with rotateX, rotateY, rotateZ, translateZ, or scale3d produce a visible depth effect under perspective. Flat 2D elements inside a perspective container appear and render normally. The perspective property is inert until a child uses a 3D transform function that makes the depth distortion visible.
Yes. The perspective property is animatable. Transitioning perspective from 1000px to 300px while holding a fixed rotateY angle creates an effect of zooming the viewpoint toward the 3D element, intensifying the depth distortion. This technique produces a cinematic dolly-zoom effect. The animation runs on the main thread rather than the compositor for the perspective property, so use it sparingly and test on lower-powered devices for smooth playback.
perspective-origin defines where the viewer's eye is positioned relative to the perspective container. The default is 50% 50%, placing the eye at the center. Changing it to 0% 0% places the eye at the top-left, creating a view from that corner. The values can be set in percentages, pixels, or CSS keywords like top, left, and center. perspective-origin only has a visible effect when perspective is also set on the same element. It does not affect elements that use the perspective() function form.
Safari on older iOS versions requires -webkit-transform-style: preserve-3d and -webkit-backface-visibility: hidden. Modern Safari 15 and later supports the unprefixed forms. If elements in a preserve-3d container appear flat or if backface-visibility does not hide the reverse face, add the -webkit- prefixed versions alongside the standard properties. This is the most common source of 3D CSS inconsistency between Chrome and Safari on iOS devices.
Setting overflow: hidden on an element that also has the perspective property can clip 3D-transformed children that extend beyond the container boundary due to Z-axis movement or rotation. The clipping is applied in 2D screen space after the 3D projection, not in 3D space. This means an element rotated with rotateY may be clipped in unexpected ways if it overflows the container's 2D bounding box. Remove overflow: hidden from the perspective container and apply clipping to a separate wrapper if needed.
The perspective property requires the element to establish a containing block. It works on block-level elements and elements with display: flex, display: grid, or display: inline-block. Pure inline elements like spans do not reliably establish a perspective context. To use perspective on an inline container, change its display to inline-block or block first. This also applies to the parent element that should receive the perspective property.
Wrap the 3D rotation or perspective animation in @media (prefers-reduced-motion: no-preference) so it only runs when motion is permitted. For users who prefer reduced motion, present the final state directly without depth transition, or replace the 3D effect with a 2D fade. Strong perspective shifts simulate the sensation of moving through space and are among the most likely triggers for motion sickness in vestibular-sensitive users. WCAG 2.3.3 expects this fallback for any non-essential motion that uses parallax or depth. The CSS @media query is the canonical mechanism and requires no JavaScript.
Setting perspective on an element creates a new stacking context for its descendants, the same as any transform value. A child with z-index: 9999 inside a perspective container only stacks against its siblings within that context, not against unrelated elements outside the container. Floating elements like tooltips and dropdowns rendered inside the perspective parent can end up trapped below sibling layout regions despite high z-index values. The fix is to portal the floating element to document.body so it lives outside the stacking context, or restructure the markup so the perspective container does not wrap content that needs to escape its stacking order. A second related symptom is that position: fixed children stop sticking to the viewport: a fixed-position child of a perspective container is anchored against that container instead, which often surprises developers who add a perspective effect to a section that previously hosted a fixed back-to-top button or sticky promo banner.

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