perspective-origin

Sets the vanishing point position for 3D transforms. The easiest way to think about it is where the viewer's eye is standing. poc is the default, and moving the vanishing point makes the very same rotation look as if it were shot from a different angle.

Class List

ClassCSSDescription
pocperspective-origin: centercenter vanishing point (default)
potperspective-origin: toptop vanishing point
pobperspective-origin: bottombottom vanishing point
polperspective-origin: leftleft vanishing point
porperspective-origin: rightright vanishing point

Live Demo

Both boxes carry exactly the same rotation, but only the left container has perspective. Move the vanishing point with the buttons.

With perspective

Plane

Every change of the vanishing point makes the same rotation look shot from a different angle.

Without perspective

Plane

The parent has no perspective, so changing the vanishing point does nothing at all.

This is the single most common problem with perspective-origin. The class applies just fine, but with no perspective on the parent there is no projection to move, so nothing appears to happen.

Class Details

pocperspective-origin: center

Places the vanishing point in the middle of the element. It is the initial value and represents a viewer standing straight in front of the subject. Write it out to cancel a different origin set by an ancestor.

<!-- Default viewpoint: the camera sits straight in front of the box -->
<div class="per80rem poc">
  <div class="tsp3d trx20deg w30rem h20rem bg18181B br8px">Card</div>
</div>

potperspective-origin: top

Raises the vanishing point. The viewer looks down onto the subject, which suits cards that should read as lying flat on a desk.

<!-- Camera raised above the element: you look down onto it -->
<div class="per80rem pot">
  <div class="tsp3d trx20deg w30rem h20rem bg18181B br8px">Table top view</div>
</div>

pobperspective-origin: bottom

Lowers the vanishing point. The viewer looks up at the subject, giving a tall and imposing feel that works well for large hero banners.

<!-- Camera below the element: a hero shot looking upward -->
<div class="per80rem pob">
  <div class="tsp3d trx20deg w30rem h20rem bg18181B br8px">Looking up</div>
</div>

polperspective-origin: left

Moves the vanishing point to the left. The viewer stands on the left, so the right face of the element opens up. Useful for 3D elements placed on the left of the screen.

<!-- Camera shifted to the left: the right side of the box opens up -->
<div class="per80rem pol">
  <div class="tsp3d try30deg w30rem h20rem bg18181B br8px">Seen from the left</div>
</div>

porperspective-origin: right

Moves the vanishing point to the right, mirroring the left variant. Use the two together for symmetric layouts such as a pair of cards angled toward each other.

<!-- Camera shifted to the right: mirrors the left variant.
     Useful for a facing pair, such as two cards angled toward each other. -->
<div class="df gap2rem">
  <div class="per80rem pol">
    <div class="tsp3d try30deg w30rem h20rem bg18181B br8px">Left card</div>
  </div>
  <div class="per80rem por">
    <div class="tsp3d try30deg w30rem h20rem bg18181B br8px">Right card</div>
  </div>
</div>

Usage Examples

perspective-origin is applied to the parent element that has the perspective property set, and the child must carry a 3D transform.

<!-- Default center viewpoint -->
<div class="per80rem poc">
  <div class="tsp3d trx20deg w30rem h20rem bg18181B br8px">3D rotated element</div>
</div>

<!-- Viewpoint moved to the left edge -->
<div class="per80rem pol">
  <div class="tsp3d try30deg w30rem h20rem bg18181B br8px">Viewed from the left</div>
</div>

Practical example: 3D product shelf

Setting perspective and its origin once on the container makes several cards read as one scene. Giving each card its own perspective looks wrong, as if every card were shot with a separate camera.

<!-- Product shelf: one shared vanishing point above the row makes the
     whole set of cards read as a single scene instead of five separate
     rotations. The perspective and its origin live on the container. -->
<section class="per100rem pot">
  <div class="tsp3d df gap16px">
    <article class="trx20deg fs0 w28rem h30rem br8px oh bg18181B">
      <img src="/shoe-1.jpg" alt="" class="w100p h20rem ofc">
      <p class="p16px fs14px cFAFAFA">Runner</p>
    </article>
    <article class="trx20deg fs0 w28rem h30rem br8px oh bg18181B">
      <img src="/shoe-2.jpg" alt="" class="w100p h20rem ofc">
      <p class="p16px fs14px cFAFAFA">Trainer</p>
    </article>
  </div>
</section>

Pitfalls

Nothing happens without perspective on the parent

perspective-origin only relocates the reference point of the projection. Without a perspective class such as per80rem on the parent there is no projection at all, so the origin is meaningless. Check this first when nothing seems to change.

perspective-origin is not transform-origin

perspective-origin sits on the parent and decides where the viewer stands, while transform-origin sits on the element itself and decides where its rotation axis runs. Swapping them will not give you what you want.

It has no effect on 2D transforms

If the child uses no 3D transform such as rotateX, rotateY, or translateZ, moving the vanishing point changes nothing. When several layers need to share the same depth, add tsp3d as well.