3D Room
Un coin de pièce en CSS 3D — sol quadrillé, mur du fond, mur de gauche et un petit cube violet posé — vu en plongée, qu'on fait tourner en le glissant à la souris ou au doigt (jusqu'à 45° en hauteur, libre sur le côté) ou aux flèches du clavier, et qui revient en douceur à sa vue de départ quand on le lâche.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. 3D comprend 50 effets, dont 8 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
La racine .fx-0028-root (fond #0a0a0f, 300 px de haut au minimum) centre un cadre .room-wrapper de 220 × 220 px qui porte la perspective (600 px). Dedans, .room garde la 3D de ses enfants (transform-style: preserve-3d) et part de rotateX(-15deg) rotateY(-25deg). Trois faces de 180 × 180 px forment le coin : le sol, quadrillé tous les 30 px, couché par rotateX(90deg) translateZ(-90px) ; le mur du fond, reculé de 90 px ; le mur de gauche, tourné de 90° puis reculé de 90 px. Le petit cube de 40 px est un carré violet avancé à translateZ(-40px), devant le mur du fond. Il n'y a que deux murs pour qu'on voie toujours l'intérieur : un troisième cacherait la pièce sous certains angles.
Le script lance une instance par .room-wrapper trouvé sous une racine .fx-0028-root. Au pointerdown (souris, doigt ou stylet), il capture le pointeur : les mouvements suivants lui arrivent même si le doigt sort du cadre. Chaque pixel glissé à l'horizontale tourne la pièce de 0,5° autour de l'axe vertical, sans limite ; chaque pixel vertical l'incline de 0,3°, borné entre −45° (vue d'au-dessus) et +5°. Au relâchement, la pièce revient à sa vue de départ en 0,6 s. Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : un glisser de 120 px à droite et 40 px vers le bas donne rotateX(-27deg) rotateY(35deg), puis le retour à −15° / −25° ; même résultat sur la seconde copie de l'effet, indépendante de la première.
Le cadre porte touch-action: none : un doigt posé sur la pièce la fait tourner au lieu de faire défiler la page (mesuré avec de vrais événements tactiles dans Chromium : 120 px à droite, 24 px vers le bas donnent −22,2° / +35°). Le cadre ne mesure que 220 px de côté : le reste de la page défile normalement. Au clavier, le cadre reçoit le focus (tabindex="0") ; les flèches gauche et droite tournent la pièce de 10°, haut et bas l'inclinent de 10° (mêmes bornes), Échap ou Début ramène la vue de départ, et la pièce y revient aussi quand le focus s'en va. Mesuré dans les trois moteurs : deux fois → puis ↑ donnent −25° / −5°.
Accessibilité
- Clavier : le cadre est focalisable, annoncé par
aria-labelcomme une pièce en 3D à tourner au glisser ou aux flèches, et entouré d'un contour violet de 2 px au focus. Flèches = 10° par appui, Échap ou Début = vue de départ. Tab atteint le cadre dans Chromium, Firefox et WebKit (mesuré). - Mouvement réduit : sous
prefers-reduced-motion: reduce, la pièce suit toujours le geste (c'est l'utilisateur qui la tourne) mais ne glisse plus d'elle-même : un bloc limité à.fx-0028-rootretire la transition et le script, qui lit la même préférence, ramène la vue de départ d'un coup au lieu de 0,6 s d'animation. Rien ne tourne jamais tout seul. - Contenu : les libellés des faces (« Floor », « Wall », « Side ») sont du vrai texte, lu par les lecteurs d'écran, mais la vue en 3D elle-même n'est décrite que par l'
aria-label: si la disposition de la pièce porte une information (surface, hauteur, mobilier), écrivez-la aussi à côté, comme les scènes ci-dessus. - Toucher :
touch-action: noneempêche la page de défiler quand le doigt part de la pièce. Gardez le cadre à une taille raisonnable sur mobile pour laisser de la place au défilement.
Compatibilité navigateur
CSS 3D (perspective, transform-style: preserve-3d, rotateX/Y, translateZ) + 35 lignes de JavaScript (événements pointer avec capture, clavier, matchMedia), aucune dépendance. Mesuré dans Chromium 151 et Firefox 153 : même rendu 3D, mêmes angles au glisser et au clavier, retour à la vue de départ, deux copies indépendantes ; toucher mesuré dans Chromium. Dans WebKit 26, les angles calculés sont identiques, mais le WebKit de Playwright aplatit toute 3D CSS (même un cube témoin) : le rendu sur Safari n'a pas été vérifié sur un vrai Safari.
Sans JavaScript, la pièce reste figée sur sa vue de départ, lisible. Si une règle de votre page ajoute overflow, filter ou une opacity inférieure à 1 sur .room, la 3D est aplatie : les trois faces se superposent à plat (c'est ce que fait transform-style: preserve-3d quand on lui impose l'une de ces propriétés).
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0028-root">
<div class="room-wrapper" data-room="" tabindex="0" role="group" aria-label="3D room: drag, or use the arrow keys, to turn it">
<div class="room">
<div class="room-face room-floor">Floor</div>
<div class="room-face room-back">Wall</div>
<div class="room-face room-left">Side</div>
<div class="room-object">■</div>
</div>
</div>
</div>
Paiement unique, sans abonnement — le code est à toi pour toujours
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
Vue de départ (JS — X0 = -15, Y0 = -25 ; CSS — transform de .room) |
−15° en hauteur, −25° sur le côté | Changez les deux endroits ensemble. −30° / −40° montre davantage le sol (utile pour un plan d'aménagement) ; −5° / −15° donne une vue presque de face sur le mur du fond. |
Sensibilité (JS — .5 et .3 dans pointermove) |
0,5° par pixel à l'horizontale, 0,3° à la verticale | 1° par pixel fait tourner la pièce d'un tour complet en 360 px de glisser ; 0,3° la rend plus calme, pour un cadre étroit sur mobile. |
Limites d'inclinaison (JS — Math.max(-45, Math.min(5, x))) |
−45° à +5° | Au-delà de −60°, on voit la pièce presque d'au-dessus et les murs s'écrasent ; au-delà de +10°, on passe sous le sol, qui n'a pas d'envers soigné. |
Retour au relâchement (JS — turn(X0, Y0, .6)) |
0,6 s, retour systématique | Allongez à 1 s pour un retour plus doux. Pour que la pièce reste où on l'a laissée, supprimez l'appel à turn(X0, Y0, .6) dans release() et gardez Échap pour revenir. |
Taille de la pièce (CSS — .room-wrapper 220 px, faces 180 px, translateZ(-90px)) |
cadre de 220 px, faces de 180 px | Gardez translateZ égal à la moitié de la taille des faces : pour des faces de 260 px, reculez de 130 px. Ou agrandissez tout d'un bloc avec transform: scale() sur le cadre, comme les scènes. |
Faces et objet (CSS — .room-floor, .room-back, .room-left, .room-object) |
sol quadrillé 30 px, murs indigo, cube violet 40 px | Recolorez, changez le quadrillage, écrivez une cote sur une face ; l'objet peut porter un mot si vous l'élargissez (76 × 34 px dans les scènes). Sa profondeur se règle avec translateZ. |
FAQ
turn(X0, Y0, .6) de la fonction release().touch-action: none : un geste qui commence sur la pièce ne fait pas défiler la page. Il ne mesure que 220 px de côté, le reste de la page défile normalement ; ne l'étirez pas sur toute la hauteur d'un écran de téléphone.