M4RKYU.SYSEdition 2027
Skip to content
LOCEN/Ontario · CA/▸logs · quick guide to 3d transformations in css3 2ki5StandbyOK/--:--:--EST
M4M4RK_YUportfolio
  • BuildBuild
    BuildOverview
    • WorkSelected case studies and write-ups
    • GamesPlayable prototypes and game-dev logs
  • GalleryGallery
    GalleryOverview
    • PhotosPhoto collections and visual experiments
    • ShopPrints, posters, and one-off objects
  • WritingWriting
    WritingOverview
    • BlogLong-form devlogs and field notes
    • NotesShort observations, links, snippets
  • ResourcesResources
    ResourcesOverview
    • Tools38 in-browser developer utilities
    • LinksDaily-use dev and design bookmarks
  • AboutAbout
  • ContactContact
中文

syndicated · dev.to / @markyu

CSS 3D Transform Bugs Usually Come From Perspective

A practical CSS 3D transform guide explaining perspective, rotateX, rotateY, transform-style, backface visibility, and debugging layout.

Published
May 20 '24
·
Reading time
2 min read
·
Reactions
4
cssfrontendwebdevanimation
View on dev.to

On this page

  • Start With a Card
  • The Three Properties That Matter
  • Rotate X vs Rotate Y
  • Common Mistake: Perspective on the Wrong Element
  • Final Thought

CSS 3D transforms look broken when one property is missing: perspective.

Without perspective, your element can rotate in 3D but still feel flat or strange. The browser is doing math; your eyes are just not getting depth cues.

Start With a Card

<div class="scene">
  <div class="card">
    <div class="face front">Front</div>
    <div class="face back">Back</div>
  </div>
</div>
.scene {
  width: 240px;
  height: 320px;
  perspective: 900px;
}

.card {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 600ms ease;
}

.scene:hover .card {
  transform: rotateY(180deg);
}

.face {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 12px;
  backface-visibility: hidden;
}

.front {
  background: #2563eb;
  color: white;
}

.back {
  background: #111827;
  color: white;
  transform: rotateY(180deg);
}

That is a real 3D card flip.

The Three Properties That Matter

PropertyJob
perspectivegives depth to children
transform-style: preserve-3dkeeps child elements in 3D space
backface-visibility: hiddenhides the mirrored backside

If your card shows mirrored text, check backface-visibility.

If the back face never appears, check the rotateY(180deg) on the back.

If everything looks flat, check perspective.

Rotate X vs Rotate Y

transform: rotateX(45deg);

Rotates around the horizontal axis.

transform: rotateY(45deg);

Rotates around the vertical axis.

transform: rotateZ(45deg);

This is the normal 2D-style rotation most developers already know.

Common Mistake: Perspective on the Wrong Element

This is usually wrong:

.card {
  perspective: 900px;
  transform: rotateY(180deg);
}

Perspective should usually be on the parent:

.scene {
  perspective: 900px;
}

The parent creates the viewing space. The child moves inside it.

Final Thought

CSS 3D is not hard, but it is unforgiving. One missing property can make the whole demo feel fake.

What 3D UI effect do you actually like in production apps: card flips, subtle tilt, or none at all?

Related reading

CSS Heart Animation: Small Demo, Real Animation Lessons

A cleaner CSS heart animation tutorial focused on transform, pseudo-elements, keyframes, and the small mistakes that break simple UI animations.

css

React 19 Micro-Interactions Without Layout Jank

A practical React 19 micro-interactions guide focused on motion boundaries, CSS transitions, optimistic UI, reduced motion, and performance.

react

Next.js Images Without CLS: My LQIP Blur-Up Setup

A practical Next.js image optimization guide for zero CLS layouts, blur placeholders, dimensions, remote images, and production image hygiene.

nextjs

originally published

This post first ran on dev.to. Comments and reactions live there.

Continue on dev.to
PreviousCloud Architecture Choices I Would Not OvercomplicateA practical 2026 cloud architecture guide for developers choosing between client-server, distributed systems, microservices, serverless, and cloud-native platforms.
Back to all posts
NextDebug a Slow MySQL Query Before You Guess at IndexesA practical MySQL workflow for finding slow queries, reading EXPLAIN output, and deciding whether an index actually helps.
Back to archive
M4RKYUM4RKYUM4RKYUM4RKYUM4RKYUM4RKYUM4RKYUM4RKYU
Crafted since 2024
ZhenXiao Mark YuZhenXiao Mark Yu
get in touch

Saw something here?Tell me about it.

It's a portfolio, not a service · but I read every note — drop a line if anything here resonated, or just to say hi.

Start a conversation
open channel

say hi anytime · 2026

--:--:--ESTOntario, Canada
  • Email
  • GitHub
  • dev.to
  • LinkedIn
  • Twitter / X
  • Instagram
  • Facebook
  • YouTube
  • CodePen
  • Spotify
  • Snapchat

Newsletter

Get the occasional dispatch

Notes and logs from m4rkyu.com — short, dated, no noise. Unsubscribe anytime.

Work

Production builds, games, and visual archives.

  • Projects
  • Games
  • Archive
  • Logs

Resources

Daily-use tools and a personal link library.

  • Search
  • Latest
  • Tools
  • Links
  • Notes
  • Topics
  • Shop
RSSJSON feed

Studio

Background, contact, and channels for collaboration.

  • About
  • Contact
  • Changelog
  • Colophon
  • Resumepending

Socials

Find me on the usual feeds.

  • GitHub
  • dev.to
  • LinkedIn
  • Twitter / X
  • Instagram
  • Facebook
  • YouTube
  • CodePen
  • Spotify
  • Snapchat
  • Email
© 2026 ZhenXiao Mark Yumarkyu0615@gmail.com
  • Email
  • GitHub
  • dev.to
  • LinkedIn
  • Twitter / X
  • Instagram
  • Facebook
  • YouTube
  • CodePen
  • Spotify
  • Snapchat
PrivacyTermsBuilt with Next.js 16 · React 19 · Tailwind 4