Back to Blog
CSSTransformsAnimationDesign

CSS Transforms Guide

Master CSS transforms for rotating, scaling, skewing, and translating elements.

B
Bootspring Team
Engineering
October 15, 2018
6 min read

CSS transforms allow you to modify elements in 2D and 3D space. Here's how to use them effectively.

Basic Transforms#

1/* Translate (move) */ 2.move { 3 transform: translate(50px, 100px); 4} 5 6.move-x { 7 transform: translateX(50px); 8} 9 10.move-y { 11 transform: translateY(100px); 12} 13 14/* Rotate */ 15.rotate { 16 transform: rotate(45deg); 17} 18 19/* Scale */ 20.scale { 21 transform: scale(1.5); /* Both axes */ 22 transform: scale(1.5, 2); /* X, Y separately */ 23 transform: scaleX(1.5); 24 transform: scaleY(2); 25} 26 27/* Skew */ 28.skew { 29 transform: skew(10deg, 5deg); 30 transform: skewX(10deg); 31 transform: skewY(5deg); 32}

Multiple Transforms#

1/* Chain transforms (order matters!) */ 2.combined { 3 transform: translateX(100px) rotate(45deg) scale(1.5); 4} 5 6/* Different order = different result */ 7.order1 { 8 transform: translateX(100px) rotate(45deg); 9 /* Moves right, then rotates in place */ 10} 11 12.order2 { 13 transform: rotate(45deg) translateX(100px); 14 /* Rotates first, then moves in rotated direction */ 15}

Transform Origin#

1/* Change the point of transformation */ 2.element { 3 transform-origin: center; /* Default */ 4 transform-origin: top left; 5 transform-origin: 50% 50%; 6 transform-origin: 0 0; 7 transform-origin: 100px 50px; 8} 9 10/* Rotate from corner */ 11.card { 12 transform-origin: bottom left; 13 transform: rotate(-10deg); 14} 15 16/* Scale from top */ 17.dropdown { 18 transform-origin: top center; 19 transform: scaleY(0); 20 transition: transform 0.3s; 21} 22 23.dropdown.open { 24 transform: scaleY(1); 25}

3D Transforms#

1/* Enable 3D */ 2.container { 3 perspective: 1000px; 4} 5 6/* 3D rotate */ 7.rotate-3d { 8 transform: rotateX(45deg); /* Rotate around X axis */ 9 transform: rotateY(45deg); /* Rotate around Y axis */ 10 transform: rotateZ(45deg); /* Same as rotate() */ 11 transform: rotate3d(1, 1, 0, 45deg); /* Custom axis */ 12} 13 14/* 3D translate */ 15.translate-3d { 16 transform: translateZ(100px); 17 transform: translate3d(50px, 100px, 200px); 18} 19 20/* 3D scale */ 21.scale-3d { 22 transform: scaleZ(2); 23 transform: scale3d(1, 1.5, 2); 24}

Perspective#

1/* Perspective on container */ 2.scene { 3 perspective: 1000px; /* Distance from viewer */ 4 perspective-origin: 50% 50%; /* Vanishing point */ 5} 6 7.card { 8 transform: rotateY(30deg); 9} 10 11/* Perspective on element */ 12.element { 13 transform: perspective(1000px) rotateY(30deg); 14} 15 16/* Preserve 3D for children */ 17.container { 18 transform-style: preserve-3d; 19} 20 21/* Back face visibility */ 22.card-face { 23 backface-visibility: hidden; 24}

Card Flip Effect#

1.card-container { 2 perspective: 1000px; 3 width: 200px; 4 height: 300px; 5} 6 7.card { 8 position: relative; 9 width: 100%; 10 height: 100%; 11 transform-style: preserve-3d; 12 transition: transform 0.6s; 13} 14 15.card-container:hover .card { 16 transform: rotateY(180deg); 17} 18 19.card-front, 20.card-back { 21 position: absolute; 22 width: 100%; 23 height: 100%; 24 backface-visibility: hidden; 25} 26 27.card-back { 28 transform: rotateY(180deg); 29}

Hover Effects#

1/* Lift effect */ 2.card { 3 transition: transform 0.3s, box-shadow 0.3s; 4} 5 6.card:hover { 7 transform: translateY(-10px); 8 box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2); 9} 10 11/* Scale up */ 12.thumbnail { 13 transition: transform 0.3s; 14} 15 16.thumbnail:hover { 17 transform: scale(1.1); 18} 19 20/* Rotate and scale */ 21.icon { 22 transition: transform 0.3s; 23} 24 25.icon:hover { 26 transform: rotate(15deg) scale(1.2); 27} 28 29/* Tilt effect */ 30.tilt:hover { 31 transform: perspective(500px) rotateX(10deg) rotateY(-10deg); 32}
1/* Grid with hover zoom */ 2.gallery { 3 display: grid; 4 grid-template-columns: repeat(3, 1fr); 5 gap: 1rem; 6} 7 8.gallery-item { 9 overflow: hidden; 10} 11 12.gallery-item img { 13 width: 100%; 14 transition: transform 0.5s ease; 15} 16 17.gallery-item:hover img { 18 transform: scale(1.15); 19} 20 21/* Ken Burns effect */ 22@keyframes kenburns { 23 0% { 24 transform: scale(1) translate(0, 0); 25 } 26 100% { 27 transform: scale(1.3) translate(-5%, -5%); 28 } 29} 30 31.hero-image { 32 animation: kenburns 20s ease-in-out infinite alternate; 33}

Button Transforms#

1/* Press effect */ 2.button { 3 transition: transform 0.1s; 4} 5 6.button:active { 7 transform: scale(0.95); 8} 9 10/* Lift and glow */ 11.button-lift { 12 transition: transform 0.3s, box-shadow 0.3s; 13} 14 15.button-lift:hover { 16 transform: translateY(-3px); 17 box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); 18} 19 20.button-lift:active { 21 transform: translateY(-1px); 22 box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 23} 24 25/* Rotate icon on hover */ 26.button-icon { 27 display: inline-flex; 28 align-items: center; 29 gap: 0.5rem; 30} 31 32.button-icon svg { 33 transition: transform 0.3s; 34} 35 36.button-icon:hover svg { 37 transform: rotate(90deg); 38}

Loading Spinners#

1/* Simple spinner */ 2.spinner { 3 width: 40px; 4 height: 40px; 5 border: 3px solid #f3f3f3; 6 border-top: 3px solid #3498db; 7 border-radius: 50%; 8 animation: spin 1s linear infinite; 9} 10 11@keyframes spin { 12 0% { transform: rotate(0deg); } 13 100% { transform: rotate(360deg); } 14} 15 16/* Pulsing dot */ 17.pulse { 18 width: 20px; 19 height: 20px; 20 background: #3498db; 21 border-radius: 50%; 22 animation: pulse 1.5s ease-in-out infinite; 23} 24 25@keyframes pulse { 26 0%, 100% { transform: scale(1); } 27 50% { transform: scale(1.5); } 28} 29 30/* 3D cube spinner */ 31.cube-spinner { 32 animation: cube-spin 2s infinite ease-in-out; 33 transform-style: preserve-3d; 34} 35 36@keyframes cube-spin { 37 0% { transform: rotateX(0) rotateY(0); } 38 100% { transform: rotateX(360deg) rotateY(360deg); } 39}

Matrix Transform#

1/* 2D Matrix */ 2.matrix { 3 /* matrix(scaleX, skewY, skewX, scaleY, translateX, translateY) */ 4 transform: matrix(1, 0.5, -0.5, 1, 50, 100); 5} 6 7/* 3D Matrix */ 8.matrix3d { 9 /* matrix3d(16 values for 4x4 matrix) */ 10 transform: matrix3d( 11 1, 0, 0, 0, 12 0, 1, 0, 0, 13 0, 0, 1, 0, 14 0, 0, 0, 1 15 ); 16} 17 18/* Use for complex transforms or animation libraries */

Performance Tips#

1/* Use transform for animations (GPU accelerated) */ 2.good { 3 transform: translateX(100px); /* GPU */ 4} 5 6.bad { 7 left: 100px; /* CPU, triggers layout */ 8} 9 10/* Will-change hint */ 11.animated { 12 will-change: transform; 13} 14 15/* Avoid on hover (add on parent hover) */ 16.container:hover .element { 17 will-change: transform; 18} 19 20.container .element { 21 will-change: auto; 22} 23 24/* Force GPU layer */ 25.force-gpu { 26 transform: translateZ(0); 27 /* or */ 28 transform: translate3d(0, 0, 0); 29}

Responsive Transforms#

1/* Adjust transforms for screen size */ 2.element { 3 transform: scale(0.8); 4} 5 6@media (min-width: 768px) { 7 .element { 8 transform: scale(1); 9 } 10} 11 12@media (min-width: 1200px) { 13 .element { 14 transform: scale(1.2); 15 } 16} 17 18/* Use CSS variables */ 19:root { 20 --card-rotation: 0deg; 21} 22 23@media (min-width: 768px) { 24 :root { 25 --card-rotation: -5deg; 26 } 27} 28 29.card { 30 transform: rotate(var(--card-rotation)); 31}

Accessibility#

1/* Respect reduced motion preference */ 2@media (prefers-reduced-motion: reduce) { 3 *, 4 *::before, 5 *::after { 6 animation-duration: 0.01ms !important; 7 animation-iteration-count: 1 !important; 8 transition-duration: 0.01ms !important; 9 } 10 11 .animated { 12 transform: none !important; 13 } 14} 15 16/* Safe transforms for reduced motion */ 17.card { 18 transition: box-shadow 0.3s; 19} 20 21.card:hover { 22 box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); 23} 24 25@media (prefers-reduced-motion: no-preference) { 26 .card { 27 transition: transform 0.3s, box-shadow 0.3s; 28 } 29 30 .card:hover { 31 transform: translateY(-5px); 32 } 33}

Best Practices#

Performance: ✓ Use transform instead of top/left ✓ Use will-change sparingly ✓ Combine transforms in one property ✓ Use translate3d for GPU Design: ✓ Subtle transforms look professional ✓ Match transform-origin to design ✓ Consider 3D perspective ✓ Use transitions for smoothness Accessibility: ✓ Respect prefers-reduced-motion ✓ Don't rely on transforms for content ✓ Ensure clickable areas remain usable ✓ Test with keyboard navigation Avoid: ✗ Overusing transforms ✗ will-change on everything ✗ Transforms that break layout ✗ Motion that causes discomfort

Conclusion#

CSS transforms are powerful for creating engaging visual effects without affecting document flow. Use translate for movement, rotate for angles, scale for sizing, and skew for distortion. Combine with transitions for smooth animations and perspective for 3D effects. Always consider performance by using GPU-accelerated transforms and respecting user motion preferences.

Share this article

Help spread the word about Bootspring