skewX(), skewY() и skew() скашивают элемент, превращая прямоугольник в параллелограмм: одна сторона смещается тем сильнее, чем дальше она от центра по другой оси. Это не поворот - углы фигуры перестают быть прямыми, а линии остаются ровными. Как и другие функции transform, наклон не меняет поток документа и не занимает лишнего места.
В этом уроке
Попробуй прямо сейчас: бейдж выглядит параллелограммом, а надпись "СКИДКА" внутри осталась ровной - потому что у .badge-text свой встречный наклон skewX(12deg), который компенсирует наклон родителя skewX(-12deg). Попробуй убрать transform у .badge-text (поставь transform: none) - текст перекосится вместе с фоном. А если заменить skewX(-12deg) у .badge на skewY(-12deg), параллелограмм превратится в фигуру с наклонными верхом и низом вместо боков.
skewX() и skewY(): наклон по одной оси
skewX() наклоняет элемент по горизонтали: чем дальше точка от центра по вертикали, тем сильнее она сдвигается влево или вправо. skewY() работает симметрично по вертикали: сдвиг зависит от расстояния до центра по горизонтали. Собственная проверка через реальные координаты углов показала точное направление: у прямоугольника 120×80px после transform: skewX(30deg) верхние углы уходят на 23px ВЛЕВО от исходного положения, а нижние - на 23px ВПРАВО (высота при этом не меняется, а ширина видимой рамки растёт со 120 до ~166px). У skewY(30deg) - симметрично: левые углы уходят вверх, правые вниз, ширина не меняется, а высота растёт с 80 до ~149px. Единица измерения угла - deg, turn, grad или rad, как и у rotate(); ненулевой угол без единицы измерения (skewX(20) вместо skewX(20deg)) недопустим, и браузер отбрасывает всё объявление transform целиком - исключение только для skewX(0).
.banner {
transform: skewX(-8deg);
} - баннер получает лёгкий наклон, похожий на классические скошенные плашки в дизайне.
Неправильное ожидание - что угол наклона можно задать в пикселях, как сдвиг:
.banner {
transform: skewX(-8px);
} - px здесь не единица угла, значение недопустимо: браузер отбрасывает transform целиком, и баннер остаётся без наклона.
skew(): два значения сразу и приём с ровным текстом внутри
skew() с двумя значениями через запятую применяет наклон сразу по обеим осям: skew(20deg, 10deg) равносилен связке skewX(20deg) и skewY(10deg) вместе - собственная проверка подтвердила, что матрица трансформации в этом случае содержит оба компонента сдвига одновременно. С одним значением skew(20deg) полностью равносилен skewX(20deg) - второй угол по умолчанию считается нулевым. Точка, от которой отсчитывается наклон, - тот же самый transform-origin по умолчанию (центр элемента), что мы уже видели у rotate() в прошлом уроке. На практике наклон родителя утягивает за собой и содержимое внутри - надпись в скошенном бейдже тоже перекашивается. Стандартный приём (его действительно так решают на форумах): наклонить контейнер, а к содержимому внутри применить наклон на ТОТ ЖЕ угол, но с обратным знаком - искажения взаимно гасятся, и текст остаётся читаемым, как в блокноте выше.
.badge {
transform: skewX(-12deg);
}
.badge-text {
display: inline-block;
transform: skewX(12deg);
} - параллелограмм-бейдж, текст внутри читается без искажений.
Неправильное ожидание - что наклона родителя достаточно, а текст сам останется ровным:
.badge {
transform: skewX(-12deg);
} - без встречного наклона у .badge-text надпись "СКИДКА" перекосится вместе с фоном, и читать её станет неудобно.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Забыть указать deg у ненулевого угла: skewX(20) вместо skewX(20deg) | Число без единицы измерения (кроме нуля) недопустимо для угла - браузер отбрасывает всё объявление transform | Всегда писать единицу измерения для ненулевого угла (skewX(0) без единицы - единственное исключение) |
| Наклонить контейнер и ожидать, что текст внутри останется ровным сам по себе | Наклон - это трансформация всего элемента целиком, включая содержимое; текст перекашивается вместе с фоном | Применить к содержимому внутри такой же наклон, но с противоположным знаком угла |
| Путать skew с rotate | skew превращает прямоугольник в параллелограмм (углы фигуры перестают быть прямыми); rotate поворачивает фигуру целиком, её собственные углы не меняются | Для поворота использовать rotate(), для наклона/перекоса - skew() |
| Искать отдельное CSS-свойство skew (по аналогии с translate, rotate, scale) | Такого свойства не существует - в 2020 году браузеры получили отдельные свойства только для translate, rotate и scale, skew в их число не попал | Наклон пишется только внутри transform: transform: skewX(-10deg) |
Шпаргалка
| Запись | Что означает |
|---|---|
| transform: skewX(20deg); | Наклон по горизонтали, сдвиг зависит от Y |
| transform: skewY(20deg); | Наклон по вертикали, сдвиг зависит от X |
| transform: skew(20deg, 10deg); | Оба наклона сразу через запятую |
| transform: skew(20deg); | То же самое, что skewX(20deg) - второй угол по умолчанию 0 |
| Компенсирующий наклон | Наклонить контейнер и применить противоположный угол к содержимому внутри |
| transform: skewX(0); | Единственный угол, который можно писать без единицы измерения |
Коротко: отвечаем на вопросы
Как сделать параллелограмм на CSS, чтобы текст внутри остался ровным?
Наклонить сам контейнер через transform: skew() (или skewX()/skewY()), а тексту или другому содержимому внутри задать точно такой же наклон, но с противоположным знаком угла. Два наклона взаимно гасят друг друга визуально, и содержимое читается без искажений, хотя сам блок выглядит скошенным.
Можно ли сделать скошенный блок со скруглёнными углами через skew()?
Технически да, но результат обычно разочаровывает: skew() наклоняет уже готовую фигуру целиком, включая border-radius, из-за чего круглые уголки превращаются в неровные, вытянутые в разные стороны дуги вместо аккуратных скруглений. Для скошенного блока с ровными скруглёнными углами разработчики чаще используют clip-path или готовую SVG-форму вместо transform: skew().