CSS поддерживает трёхмерное пространство. С помощью perspective, transform-style: preserve-3d и 3D-функций трансформации можно создавать перелистывание карточек, 3D-карусели и другие эффекты.
perspective задаёт расстояние от зрителя до плоскости Z=0. Чем меньше значение, тем сильнее выражен 3D-эффект:
/* На родителе — создаёт перспективу для всех детей */
.scene {
perspective: 800px; /* Расстояние зрителя */
perspective-origin: 50% 50%; /* Точка схода (по умолчанию центр) */
}
/* Или на самом элементе через transform */
.card {
transform: perspective(800px) rotateY(45deg);
}Без этого свойства дочерние элементы «сплющиваются» в плоскость родителя:
.card {
transform-style: preserve-3d; /* Дети живут в 3D-пространстве родителя */
/* flat — по умолчанию, дети проецируются на 2D */
}/* Вращение вокруг осей */
transform: rotateX(45deg); /* Наклон вперёд/назад */
transform: rotateY(45deg); /* Поворот влево/вправо (как дверь) */
transform: rotateZ(45deg); /* Обычное вращение (= rotate()) */
transform: rotate3d(1, 1, 0, 45deg); /* Вращение вокруг произвольной оси */
/* Перемещение по оси Z */
transform: translateZ(100px); /* Ближе к зрителю */
transform: translateZ(-100px); /* Дальше от зрителя */
transform: translate3d(x, y, z);
/* Масштабирование */
transform: scaleZ(2); /* Масштаб по оси Z */
transform: scale3d(1, 1, 2);Классический паттерн: карточка с лицевой и обратной сторонами:
.card-scene {
perspective: 1000px;
width: 200px;
height: 280px;
}
.card {
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.6s ease;
position: relative;
}
.card.flipped {
transform: rotateY(180deg);
}
/* Лицевая и обратная стороны */
.card__front,
.card__back {
position: absolute;
inset: 0;
backface-visibility: hidden; /* Прячем сторону, повёрнутую от зрителя */
border-radius: 12px;
}
.card__back {
transform: rotateY(180deg); /* Обратная сторона изначально повёрнута */
background: #7b2ff7;
color: white;
}backface-visibility: hidden; /* Прячет элемент, когда он повёрнут к нам спиной */
backface-visibility: visible; /* Показывает (зеркально отражённый) */.carousel {
transform-style: preserve-3d;
/* Каждая панель повёрнута на свой угол и отодвинута по Z */
}
/* 4 панели, каждая 90° друг от друга */
.panel:nth-child(1) { transform: rotateY(0deg) translateZ(300px); }
.panel:nth-child(2) { transform: rotateY(90deg) translateZ(300px); }
.panel:nth-child(3) { transform: rotateY(180deg) translateZ(300px); }
.panel:nth-child(4) { transform: rotateY(270deg) translateZ(300px); }.card {
will-change: transform; /* Браузер заранее создаёт GPU-слой */
}Используй с умом: избыток will-change увеличивает потребление памяти GPU.
Интерактивная 3D-карточка с переворотом и вычислением матриц трансформации
// 3D Card Flip через CSS transform-style: preserve-3d
const style = document.createElement('style')
style.textContent = `
.scene {
perspective: 800px;
width: 180px;
height: 240px;
margin: 20px;
cursor: pointer;
}
.card-3d {
width: 100%; height: 100%;
transform-style: preserve-3d;
transition: transform 0.7s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
}
.card-3d.flipped { transform: rotateY(180deg); }
.face {
position: absolute; inset: 0;
backface-visibility: hidden;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-family: sans-serif;
font-weight: 700;
font-size: 18px;
box-shadow: 0 8px 32px rgba(0,0,0,0.15);
}
.front { background: linear-gradient(135deg, #7b2ff7, #06b6d4); color: white; }
.back { background: linear-gradient(135deg, #f59e0b, #ef4444); color: white;
transform: rotateY(180deg); }
`
document.head.appendChild(style)
const scene = document.createElement('div')
scene.className = 'scene'
document.body.appendChild(scene)
const card = document.createElement('div')
card.className = 'card-3d'
scene.appendChild(card)
const front = document.createElement('div')
front.className = 'face front'
front.textContent = 'Лицо'
card.appendChild(front)
const back = document.createElement('div')
back.className = 'face back'
back.textContent = 'Обратная'
card.appendChild(back)
// Переворот по клику
let isFlipped = false
scene.addEventListener('click', () => {
isFlipped = !isFlipped
card.classList.toggle('flipped', isFlipped)
console.log('Перевёрнута:', isFlipped)
console.log('transform:', getComputedStyle(card).transform)
})
// Симуляция 3D-матрицы вращения по Y
function rotateYMatrix(angleDeg) {
const a = angleDeg * Math.PI / 180
return {
m11: Math.cos(a), m13: Math.sin(a),
m31: -Math.sin(a), m33: Math.cos(a),
m22: 1, m44: 1,
}
}
console.log('Матрица rotateY(0deg):', rotateYMatrix(0))
console.log('Матрица rotateY(90deg):', rotateYMatrix(90))
console.log('Матрица rotateY(180deg):', rotateYMatrix(180))
console.log('Кликни на карточку чтобы перевернуть её')
// backface-visibility: когда |cos(angle)| < 0 — лицо от нас
function isFaceVisible(angleDeg) {
return Math.cos(angleDeg * Math.PI / 180) >= 0
}
console.log('Front visible at 0°:', isFaceVisible(0)) // true
console.log('Front visible at 90°:', isFaceVisible(90)) // false (граница)
console.log('Front visible at 180°:', isFaceVisible(180)) // falseCSS поддерживает трёхмерное пространство. С помощью perspective, transform-style: preserve-3d и 3D-функций трансформации можно создавать перелистывание карточек, 3D-карусели и другие эффекты.
perspective задаёт расстояние от зрителя до плоскости Z=0. Чем меньше значение, тем сильнее выражен 3D-эффект:
/* На родителе — создаёт перспективу для всех детей */
.scene {
perspective: 800px; /* Расстояние зрителя */
perspective-origin: 50% 50%; /* Точка схода (по умолчанию центр) */
}
/* Или на самом элементе через transform */
.card {
transform: perspective(800px) rotateY(45deg);
}Без этого свойства дочерние элементы «сплющиваются» в плоскость родителя:
.card {
transform-style: preserve-3d; /* Дети живут в 3D-пространстве родителя */
/* flat — по умолчанию, дети проецируются на 2D */
}/* Вращение вокруг осей */
transform: rotateX(45deg); /* Наклон вперёд/назад */
transform: rotateY(45deg); /* Поворот влево/вправо (как дверь) */
transform: rotateZ(45deg); /* Обычное вращение (= rotate()) */
transform: rotate3d(1, 1, 0, 45deg); /* Вращение вокруг произвольной оси */
/* Перемещение по оси Z */
transform: translateZ(100px); /* Ближе к зрителю */
transform: translateZ(-100px); /* Дальше от зрителя */
transform: translate3d(x, y, z);
/* Масштабирование */
transform: scaleZ(2); /* Масштаб по оси Z */
transform: scale3d(1, 1, 2);Классический паттерн: карточка с лицевой и обратной сторонами:
.card-scene {
perspective: 1000px;
width: 200px;
height: 280px;
}
.card {
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.6s ease;
position: relative;
}
.card.flipped {
transform: rotateY(180deg);
}
/* Лицевая и обратная стороны */
.card__front,
.card__back {
position: absolute;
inset: 0;
backface-visibility: hidden; /* Прячем сторону, повёрнутую от зрителя */
border-radius: 12px;
}
.card__back {
transform: rotateY(180deg); /* Обратная сторона изначально повёрнута */
background: #7b2ff7;
color: white;
}backface-visibility: hidden; /* Прячет элемент, когда он повёрнут к нам спиной */
backface-visibility: visible; /* Показывает (зеркально отражённый) */.carousel {
transform-style: preserve-3d;
/* Каждая панель повёрнута на свой угол и отодвинута по Z */
}
/* 4 панели, каждая 90° друг от друга */
.panel:nth-child(1) { transform: rotateY(0deg) translateZ(300px); }
.panel:nth-child(2) { transform: rotateY(90deg) translateZ(300px); }
.panel:nth-child(3) { transform: rotateY(180deg) translateZ(300px); }
.panel:nth-child(4) { transform: rotateY(270deg) translateZ(300px); }.card {
will-change: transform; /* Браузер заранее создаёт GPU-слой */
}Используй с умом: избыток will-change увеличивает потребление памяти GPU.
Интерактивная 3D-карточка с переворотом и вычислением матриц трансформации
// 3D Card Flip через CSS transform-style: preserve-3d
const style = document.createElement('style')
style.textContent = `
.scene {
perspective: 800px;
width: 180px;
height: 240px;
margin: 20px;
cursor: pointer;
}
.card-3d {
width: 100%; height: 100%;
transform-style: preserve-3d;
transition: transform 0.7s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
}
.card-3d.flipped { transform: rotateY(180deg); }
.face {
position: absolute; inset: 0;
backface-visibility: hidden;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-family: sans-serif;
font-weight: 700;
font-size: 18px;
box-shadow: 0 8px 32px rgba(0,0,0,0.15);
}
.front { background: linear-gradient(135deg, #7b2ff7, #06b6d4); color: white; }
.back { background: linear-gradient(135deg, #f59e0b, #ef4444); color: white;
transform: rotateY(180deg); }
`
document.head.appendChild(style)
const scene = document.createElement('div')
scene.className = 'scene'
document.body.appendChild(scene)
const card = document.createElement('div')
card.className = 'card-3d'
scene.appendChild(card)
const front = document.createElement('div')
front.className = 'face front'
front.textContent = 'Лицо'
card.appendChild(front)
const back = document.createElement('div')
back.className = 'face back'
back.textContent = 'Обратная'
card.appendChild(back)
// Переворот по клику
let isFlipped = false
scene.addEventListener('click', () => {
isFlipped = !isFlipped
card.classList.toggle('flipped', isFlipped)
console.log('Перевёрнута:', isFlipped)
console.log('transform:', getComputedStyle(card).transform)
})
// Симуляция 3D-матрицы вращения по Y
function rotateYMatrix(angleDeg) {
const a = angleDeg * Math.PI / 180
return {
m11: Math.cos(a), m13: Math.sin(a),
m31: -Math.sin(a), m33: Math.cos(a),
m22: 1, m44: 1,
}
}
console.log('Матрица rotateY(0deg):', rotateYMatrix(0))
console.log('Матрица rotateY(90deg):', rotateYMatrix(90))
console.log('Матрица rotateY(180deg):', rotateYMatrix(180))
console.log('Кликни на карточку чтобы перевернуть её')
// backface-visibility: когда |cos(angle)| < 0 — лицо от нас
function isFaceVisible(angleDeg) {
return Math.cos(angleDeg * Math.PI / 180) >= 0
}
console.log('Front visible at 0°:', isFaceVisible(0)) // true
console.log('Front visible at 90°:', isFaceVisible(90)) // false (граница)
console.log('Front visible at 180°:', isFaceVisible(180)) // falseСоздай интерактивную карточку с 3D-переворотом при клике. Карточка должна иметь лицевую (синяя) и обратную (фиолетовая) стороны. Используй `transform-style: preserve-3d`, `backface-visibility: hidden` и `transition: transform 0.6s`. При клике добавляй/убирай класс `.flipped` с `rotateY(180deg)`.
`perspective: 800px` на `.scene` создаёт глубину. `transform-style: preserve-3d` — дети живут в 3D. `backface-visibility: hidden` — прячет обратную сторону. `.back` изначально повёрнута на `rotateY(180deg)`. `.flipped` — `rotateY(180deg)` на карточке.