Transforms 3D CSS
Optional Advanced acabou de afinar ponteiro, caret e cromo nativo. Esta última sessão opcional é outra caixa: transforms 3D. Dás a um cartão um ponto de fuga e inclinas-no em profundidade. Não refazes a lição 2D de translate / scale no hover, nem escolhes cursores ou pegas de resize.
Resposta direta
Os transforms 3D em CSS usam a mesma propriedade transform que o 2D, mais profundidade. Põe perspective num pai para os filhos partilharem um ponto de fuga (perspective-origin move-o). rotateX e rotateY inclinham nos eixos horizontal e vertical; rotateZ é o giro plano que já conheces. translateZ aproxima ou afasta do observador. transform-style: preserve-3d mantém os filhos numa cena em vez de os achatar. backface-visibility: hidden esconde uma face quando se vira — útil num cartão de duas faces. O lugar no layout fica, como no 2D. Ângulos modestos. Respeita prefers-reduced-motion.
Porquê não é movimento 2D nem cromo de UI
A lição de transforms 2D ensinou movimento no plano: translate, rotate, scale, skew e transform-origin como dobradiça. Continua a valer. O 3D acrescenta uma perspective tipo câmara e eixos extra. O CSS de interface era cromo de interação (cursor, resize, caret-color, appearance). Um cartão rodado não precisa de uma mão mentirosa, e a pega de um textarea não é ponto de fuga. Se só queres um salto de 2px, fica no 2D.
Perspective — a câmara no pai
perspective é um comprimento: valores mais pequenos sentem-se mais perto e dramáticos; maiores, mais planos. Põe-na no palco, não em cada face, para os irmãos partilharem um ponto de fuga.
.stage {
perspective: 800px;
perspective-origin: 50% 40%;
}
.card-3d {
transform: rotateY(18deg);
transform-origin: center;
}
Também podes escrever transform: perspective(800px) rotateY(18deg) num único elemento. Essa câmara só pertence a essa caixa. Para um cubo ou uma fila de ladrilhos, perspective no pai é mais calma. perspective-origin é o primo do ponto de fuga de transform-origin — não substitui o pivô da face que roda.
Eixos — rotateX, rotateY, rotateZ
Pensa num livro. rotateY abre a capa esquerda–direita. rotateX acena-a para ti ou para longe. rotateZ gira na página — o rotate() 2D que já sabes.
.tile-y {
transform: rotateY(-22deg);
}
.tile-x {
transform: rotateX(12deg);
}
.tile-z {
transform: rotateZ(8deg);
}
Encadeia com funções 2D quando precisares: rotateY(16deg) translateZ(24px). A ordem conta — as posteriores correm no espaço local das anteriores. Uma só lista transform, como na lição 2D. Um rotateX(80deg) enorme num artigo inteiro é feira, não UI.
translateZ — distância, não um empurrão de layout
Com perspective, um translateZ positivo costuma vir para o observador. Os vizinhos do documento não abrem espaço; só a pintura se move, como o translate 2D.
.stage {
perspective: 900px;
}
.pop-face {
transform: translateZ(40px) rotateY(-8deg);
}
.back-face {
transform: translateZ(-28px);
}
Usa translateZ para separar faces de uma cena, não para fingir margin ou um z-index do dia a dia. z-index continua a ordenar caixas sobrepostas no layout 2D; a distância 3D é outro botão. Se o trabalho é «subir um chip 2px», o translateY da lição 2D chega.
preserve-3d — guarda a cena, não achates
Por omissão, um pai achata filhos transformados (transform-style: flat). A relação 3D perde-se. Para um cubo, uma capa empilhada ou um cartão de duas faces, põe preserve-3d no invólucro que roda.
.scene {
perspective: 700px;
}
.rig {
transform-style: preserve-3d;
transition: transform 0.45s ease;
}
.rig.is-flipped {
transform: rotateY(180deg);
}
.face {
position: absolute;
inset: 0;
backface-visibility: hidden;
}
Cada ancestral que deva guardar profundidade precisa de preserve-3d — um pai flat esquecido carimba o cubo em poster. Divisão comum: perspective no palco exterior e preserve-3d na armação interior: câmara fora, juntas dentro.
backface-visibility — esconde o verso
Quando uma face passa dos 90°, verias o espelho. backface-visibility: hidden tira esse verso. Emparelha duas faces: frente rotateY(0), verso rotateY(180deg), ambas position: absolute na mesma armação.
.card-rig {
position: relative;
transform-style: preserve-3d;
}
.card-front,
.card-back {
position: absolute;
inset: 0;
backface-visibility: hidden;
}
.card-back {
transform: rotateY(180deg);
}
Sem versos escondidos aparece um fantasma da frente. Isto não é user-select: none nem appearance: none. Escondes uma face pintada em 3D; não tiras a pele a uma caixa de verificação.
3D vs transform 2D vs cromo de UI
📊 3D vs 2D transform vs UI chrome
| Tool | Job | Poor fit |
|---|---|---|
perspective + rotateX / rotateY / translateZ |
Cena de profundidade: inclinação, distância, ponto de fuga partilhado | Hover quotidiano de 2px; forma do ponteiro |
2D translate / rotate / scale / skew |
Movimento no plano; dobradiça de origin | Cubo sem preserve-3d |
transform-style / backface-visibility |
Faces 3D aninhadas; esconder o verso | Cor do caret; resize de textarea |
UI (cursor, resize, appearance…) |
Cromo de interação em controlos | Pontos de fuga; virar cartão |
Optional Advanced já estilizou controlos. Effects & Motion já ensinou o mapeamento 2D. Esta sessão é a camada de profundidade sobre transform. cursor: pointer num título porque tem rotateY não o torna 3D. perspective num login não substitui resize num campo de notas.
Hábitos calmos
Mantém a perspective em centenas de píxeis para cartões de UI (600px–1200px é uma faixa sã). Não ponhas perspective: 40px em body. Junta :hover ou uma classe a um transition curto em transform — como no 2D. Corta o enfeite com prefers-reduced-motion: reduce (none ou um empurrão 2D mínimo). O foco de teclado continua a precisar de um anel visível; um flip não é estilo de foco.
.preview {
perspective: 1000px;
}
.preview .plate {
transition: transform 0.3s ease;
}
.preview:hover .plate {
transform: rotateY(-10deg) rotateX(4deg);
}
@media (prefers-reduced-motion: reduce) {
.preview .plate,
.preview:hover .plate {
transition: none;
transform: none;
}
}
Esse hover é uma inclinação, não o lift 2D translateY(-0.15rem) do chip nem resize: vertical num campo. Se quem prefere menos movimento quiser um cartão quieto, acredita.
Experimenta tu
- Envolve um cartão em
.stage { perspective: 800px; }e põerotateY(20deg)no filho — depois passaperspectivepara otransformdo filho e compara ladrilhos irmãos. - Monta um cartão de duas faces:
preserve-3dna armação,backface-visibility: hiddenem ambas, versorotateY(180deg). - Acrescenta
translateZ(32px)no plano da frente; confirma que os vizinhos de layout não se mexem. - Vira com uma classe +
transition: transform— depois achata comprefers-reduced-motion. - Não resolvas isto com
cursor,resizeou só um hover 2DtranslateY.
Erros comuns
perspective: 50pxembodyaté entortar a página toda- Esquecer
preserve-3dno invólucro e estranhar um cubo chato - Tratar o lift 2D do chip (
translateY) como lição 3D - Usar cromo de UI (
cursor,resize,appearance) no lugar da profundidade backface-visibilityno palco em vez das faces- Ignorar
prefers-reduced-motionem flips grandes derotateY - Esperar que o 3D mude o fluxo do documento como
margin
Resumo
- Os transforms 3D dão profundidade a
transform: perspective,rotateX/rotateY,translateZ - perspective na cena pai; preserve-3d para as faces aninhadas ficarem nesse espaço
- backface-visibility: hidden esconde uma face que se virou
- Nem lição de hover 2D nem cromo de interface
- Ângulos modestos; respeitar movimento reduzido
- Última sessão CSS deste curso — Optional Advanced acaba aqui; não há mais slug CSS no mapa
🧠 Teste Seu Conhecimento
Teste Seu Conhecimento
Desafie-se com este questionário interativo e veja o quão bem você entende o tópico
📝 Instruções
- Leia cada pergunta cuidadosamente
- Selecione a melhor resposta para cada pergunta
- Você pode refazer o quiz quantas vezes quiser
- Seu progresso será mostrado no topo