В уроках посвящённых трансформации двухмерных объектов мы научились использовать несколько видов трансформации:
- Перемещение. За это отвечает функция translate()
- Вращение. Для этого использовалась функция rotate()
- Масштабирование с использованием функции scale()
Трансформации трехмерных объектов не отличаются по своему функционалу. Мы так же можем использовать только эти типы, но для них существует специальный синтаксис. Чтобы браузеру было легче, при трансформации трехмерных объектов к названию функции дописывается 3d. Таким образом мы получаем 3 функции для трехмерных элементов:
- translate3d() — перемещение
- rotate3d() — вращение
- scale3d() — масштабирование
Единственная трансформация, которая отсутствует для оси z — skew()
transform-style
Для корректной демонстрации всех этих трансформаций необходимо иметь настоящий трехмерный объект, а не только ось z. В качестве каноничного примера используют куб. Для его создания понадобится воспользоваться новым свойством, а именно transform-style, которое принимает одно из двух значений:
- flat. Значение по умолчанию. Оно говорит о том, что элемент находится в той же плоскости, что и его родитель. Именно так мы видим элементы в большинстве случаев и в предыдущих уроках в частности
- preserve-3d — элемент как бы находится в своём трехмерном пространстве, а не в пространстве своего родителя. Это означает, что элементы будут независимы друг друга. Например, они могут проходить сквозь друг друга
Вначале это может немного запутать, но проще всего взглянуть на оба значения в контексте примера:
https://codepen.io/hexlet/pen/abwPYMr
В левом примере зелёный блок находится выше красного, это объясняется тем, что элементы находятся в одном двухмерном пространстве и зависят друг от друга. Как бы вы не трансформировали зелёный блок он никак не сможет взаимодействовать с красным блоком, так как находится перед ним.
В правом примере значение preserve-3d для красного блока создает собственный контекст объёмного пространства. Все дочерние элементы не просто существуют рядом друг с другом, а находятся в едином трехмерном пространстве, что позволяет элементам проходить друг через друга и перемещаться относительно общих осей.
Проще всего думать об этом так, что flat создает единое двухмерное пространство, а preserve-3d трехмерное. Это добавляет новые возможности по расположению элементов друг с другом.
Важно: свойство transform-style устанавливается единожды для родительского элемента. Так как свойство отвечает за создание пространства, то нет смысла в установке свойства дочерним элементам. В примере выше таким блоком стал красный элемент. Так же важно помнить, что речь идёт о прямых потомках. Если добавить новый элемент внутрь зелёного блока, то для него пространство будет определяться значением flat
Теперь настало время узнать, как работают уже знакомые трансформации, но в трехмерном пространстве. В качестве примера возьмём самый примитивный трехмерный объект — куб. Все его грани сделаны полупрозрачными, чтобы легче было ориентироваться как он выглядит в пространстве. Сейчас же мы смотрим ровно в его центральную точку передней грани. Это будет начальной позицией при любой трансформации, которую мы сделаем ниже. Вы же можете менять начальную точку используя свойство perspective-origin — это будет давать чуть другой эффект, так как взгляд будет немного под другим углом, в прямом смысле этого слова.
https://codepen.io/hexlet/pen/mdwYxEL
Перемещение
Для перемещения трехмерных объектов используются функции:
- translateX()
- translateY()
- translateZ()
и их «старший брат» — translate3d(x, y, z). Оно просто объединяет все три функции для удобства написания. Следующие две записи равнозначны:
Перемещение по координатам x и y достаточно очевидны. А как происходит перемещение по оси z? Браузер, при изменении положения по оси z перемещает элемент ближе или дальше от начального месторасположения. При этом, если элемент перемещается дальше, то он уменьшается, а если перемещается ближе, то увеличивается. Такой эффект можно рассмотреть на самом кубе. Передняя и задняя стенка куба располагаются с использованием функции translateZ(). В примере ниже были убраны все грани кроме фронтальной и задней, а также куб был немного развернут.
https://codepen.io/hexlet/pen/QWgRZKQ
Грани имеют следующие свойства:
Для достижения эффекта куба фронтальная грань была перемещена по оси z на 150 пикселей ближе к пользователю. Это привело к побочному эффекту: грань теперь имеет размер не 300x300 пикселей, как указано, а 382x382 пикселя. Как можно понять, такие трансформации преобразуют именно размеры элементов, что важно учитывать при встраивании трансформированных объектов в уже готовые шаблоны страниц.
Задняя грань претерпела похожие трансформации: она была отдалена на 150 пикселей назад относительно своего начального месторасположения. Это изменило и изначальный размер самого квадрата. Теперь он имеет размер 250x250 пикселей.
Важно: обратите внимание, что трансформация по одной оси и на одинаковое количество пикселей не привело к тому, что элементы увеличились и уменьшились на одинаковое количество пикселей. Здесь прямая связь от свойства, изначальных размеров, положительности или отрицательности значения, а также значения перспективы. Более полно, со всеми формулами и матрицами описание приведено в официальной спецификации.
Если вы не собираетесь делать свои мультфильмы на CSS, то полностью разбираться в этом не нужно. Главное уловить суть того, как свойства влияют на элементы.
Вращение
Функции, предоставляемые спецификацией CSS повторяют аналогичные функции для перемещения. Вращение элемента осуществляется с помощью следующих функций:
- rotateX() — вращение по оси x
- rotateY() — вращение по оси y
- rotateZ() — вращение по оси z
- rotate3d(x, y, z) — вращение по осям x, y и z
Проще всего увидеть вращение элементов на примере анимации куба. Для каждой оси вынесен отдельный пример
https://codepen.io/hexlet/pen/MWodPdM
Важно: обратите внимание на то, как элементы выстроены изначально. В примере используется три куба друг под другом и мы их видим так, как это было бы в жизни: у верхнего куба видна нижняя грань, так как он находится выше нашего взгляда, а у нижнего куба мы видим его верхнюю грань. Это происходит из-за того, что перспектива в примере выставлена у общего для всех этих кубов блока. В данном случае перспектива установлена у тега <body>, поэтому объекты располагаются в единой области относительно друг друга, но на разной высоте
Масштабирование
Нет ничего удивительного, что для масштабирования элемента в трехмерном пространстве используются такие же по замыслу функции, как и в прошлых примерах:
- scaleX() — масштабирование по оси x
- scaleY() — масштабирование по оси y
- scaleZ() — масштабирование по оси z
- scale3d(x, y, z) — масштабирование по осям x, y и z
Диапазон значений не отличается от двухмерного пространства — значения от 0 до 1 уменьшают элемент, значения выше 1 увеличивают элемент по одной из оси. Отрицательные значения обеспечат эффект «отзеркаливания» элемента.
https://codepen.io/hexlet/pen/abwrQqW
<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 20:12:37 UTC","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="YEn2J-BJj7MEl_cpfJLxTbBm5C5Lr_An-CqUOJF8LuOPmD0QEjci07LU07FwnQE6cG_JhEOYDoVFyg5sw3vJjQ";gon.locale="ru";gon.language="ru";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLSeibfGq-KvWQ2Fyru-zkFFRVTLBuzXAHAoEyN1p49FtDmNoNA";
//]]>
</script>
<meta charset="utf-8">
<title>3D трансформации. Функции | CSS: Transform (трансформация объектов)</title>
<meta name="description" content="3D трансформации. Функции / CSS: Transform (трансформация объектов): Учимся использовать изученные ранее трансформации в трехмерном пространстве">
<link rel="canonical" href="https://ru.hexlet.io/courses/css-transform/lessons/3d-transforming/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="3D трансформации. Функции">
<meta property="og:title" content="CSS: Transform (трансформация объектов)">
<meta property="og:description" content="3D трансформации. Функции / CSS: Transform (трансформация объектов): Учимся использовать изученные ранее трансформации в трехмерном пространстве">
<meta property="og:url" content="https://ru.hexlet.io/courses/css-transform/lessons/3d-transforming/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="r_Cpy7ui8sfq3Ym8yUPSvgNe0t20n9yxpr_kQHfzUIJAIWL8Sdxfp1yerSTFTCLJw1f_d7yoIhMbX34UJfS37A" />
<script src="/vite/assets/inertia-DfXos102.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-BrRXra1y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-cb8xch9l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAzNCwicHVyIjoiYmxvYl9pZCJ9fQ==--ba516ea9573bdfcd1d21e2aa0fff8818561828f2/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Typing-bro.png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAyNSwicHVyIjoiYmxvYl9pZCJ9fQ==--3b94875bb52777724a7b11b075b8891f331d8cdf/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programming-amico.png"/><link rel="preload" as="image" href="/vite/assets/development-BVihs_d5.png"/><div id="app" data-page="{"component":"web/courses/lessons/theory_unit","props":{"errors":{},"locale":"ru","language":"ru","httpsHost":"https://ru.hexlet.io","host":"ru.hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26T20:12:37.263Z","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":"88d071f1d3384eb4bd1deb37910235c7","formAuthToken":"PZ0oNyd-VMJ1KruNIwf8CwO4GuLS6tj6tiWdvNhKlLfSTOMA1QD5osNpnxUvCAx8w7E3SNrdJlgLxQfoik1z2Q","topics":[{"id":58375,"title":"Никита, огромное спасибо Вам за программу \"Верстальщик\"!!!\n\nСегодня закончил последний урок. Все 16 курсов пройдены. \n\nК огромному сожалению, финансово не потянул, чтобы заниматься с персональным наставником, поэтому времени на прохождение ушло больше и, возможно, недополучил какую-то дополнительную нужную информацию. Но результатом остался очень доволен!!!\n\nВ принципе, уже второй проект мне показал, что без проблем вижу структуру будущего проекта и понимаю с чего начинать и как делать. Раньше целостности картины не видел бы. Ушла боязнь и начал получать удовольствие от работы с проектом.\n\nКонечно же, практики катастрофически не хватает. Но дело сдвинулось с мертвой точки.)) \n\nНачал достаточно свободно ориентироваться в документации и перестал пытаться все запоминать, а вместо этого научился понимать логику действий. Ну а дальнейшая практика закрепит в сознании то, чего пока не запомнил, но знаю где подсмотреть в случае необходимости.\n \nЯ искренне признателен Вам за Ваш труд, благодаря которому, обучение по программе прошло очень быстро и увлекательно.\n\nСегодня пойду покорять последний бастион - третий заключительный учебный проект по Программе \"Мессенджер «Hexlet Chat»\".\n\nСпасибо!!! \n \nК сожалению, на Хекслет нет специального места, где можно было бы размещать подобные топики, поэтому разместил здесь, в обсуждениях к последнему уроку курса.\n","plain_title":"Никита, огромное спасибо Вам за программу \"Верстальщик\"!!! Сегодня закончил последний урок. Все 16 курсов пройдены. К огромному сожалению, финансово не потянул, чтобы заниматься с персональным наставником, поэтому времени на прохождение ушло больше и, возможно, недополучил какую-то дополнительную нужную информацию. Но результатом остался очень доволен!!! В принципе, уже второй проект мне показал, что без проблем вижу структуру будущего проекта и понимаю с чего начинать и как делать. Раньше целостности картины не видел бы. Ушла боязнь и начал получать удовольствие от работы с проектом. Конечно же, практики катастрофически не хватает. Но дело сдвинулось с мертвой точки.)) Начал достаточно свободно ориентироваться в документации и перестал пытаться все запоминать, а вместо этого научился понимать логику действий. Ну а дальнейшая практика закрепит в сознании то, чего пока не запомнил, но знаю где подсмотреть в случае необходимости. Я искренне признателен Вам за Ваш труд, благодаря которому, обучение по программе прошло очень быстро и увлекательно. Сегодня пойду покорять последний бастион - третий заключительный учебный проект по Программе \"Мессенджер «Hexlet Chat»\". Спасибо!!! ","creator":{"public_name":"Вячеслав Михайлов","id":235128,"is_tutor":false},"comments":[{"creator":{"public_name":"Nikita Mikhaylov","id":186965,"is_tutor":true},"id":123637,"body":"Спасибо за такой отзыв. Очень приятно услышать","topic_id":58375}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"3D трансформации. Функции","entity_url":null,"active":true}},{"id":100074,"title":"Добрый день. Большое спасибо за этот курс. Изложение ёмкое, грамотное и объясняется всё доходчиво даже для моего среднего мозга.\n\nОбратил внимание, что в последнем уроке про функции 3D трансформации описан неверный синтаксис функции: `rotate3d(x, y, z)`. Или я не нашёл такой вариант её определения в [спецификации](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d#syntax).\n\nСудя по всему, синтаксис у неё другой: `rotate3d(x, y, z, angle)`, где `x`, `y`, `z` определяют координаты вектора оси вращения, а `angle` - угол вращения. Но я не понял, как с этим работать. Было бы классно увидеть в этом уроке небольшое объяснение и пару примеров её использования. Ещё раз большое спасибо!","plain_title":"Добрый день. Большое спасибо за этот курс. Изложение ёмкое, грамотное и объясняется всё доходчиво даже для моего среднего мозга. Обратил внимание, что в последнем уроке про функции 3D трансформации описан неверный синтаксис функции: rotate3d(x, y, z). Или я не нашёл такой вариант её определения в спецификации (https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d#syntax). Судя по всему, синтаксис у неё другой: rotate3d(x, y, z, angle), где x, y, z определяют координаты вектора оси вращения, а angle - угол вращения. Но я не понял, как с этим работать. Было бы классно увидеть в этом уроке небольшое объяснение и пару примеров её использования. Ещё раз большое спасибо! ","creator":{"public_name":"Артур Буравлев","id":402155,"is_tutor":false},"comments":[{"creator":{"public_name":"Olga Pejenkova","id":364375,"is_tutor":true},"id":191770,"body":"**Артур Буравлев**, \n\nспасибо, передала вашу обратную связь нашим методистам.","topic_id":100074}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"3D трансформации. Функции","entity_url":null,"active":true}}],"lesson":{"exercise":null,"units":[{"id":4808,"name":"theory","url":"/courses/css-transform/lessons/3d-transforming/theory_unit"},{"id":4820,"name":"quiz","url":"/courses/css-transform/lessons/3d-transforming/quiz_unit"}],"links":[{"id":423834,"name":"Спецификация CSS Transforms Module Level 2","url":"https://www.w3.org/TR/css-transforms-2/"}],"ordered_units":[{"id":4808,"name":"theory","url":"/courses/css-transform/lessons/3d-transforming/theory_unit"},{"id":4820,"name":"quiz","url":"/courses/css-transform/lessons/3d-transforming/quiz_unit"}],"id":2162,"slug":"3d-transforming","state":"approved","name":"3D трансформации. Функции","course_order":700,"goal":"Учимся использовать изученные ранее трансформации в трехмерном пространстве","self_study":"Для всех примеров из урока воспользуйтесь различными значениями свойств:\n\n* `perspective`\n* `perspective-origin`\n\nПосмотрите, как реагируют трехмерные объекты на изменения этих свойств вместе с трансформациями. Попробуйте несколько трансформаций. Например, поворот и перемещение. Вы можете использовать эти свойства не только для всего куба, но и для каждой грани в отдельности\n","theory_video_provider":null,"theory_video_uid":null,"theory":"В уроках посвящённых трансформации двухмерных объектов мы научились использовать несколько видов трансформации:\n\n* Перемещение. За это отвечает функция `translate()`\n* Вращение. Для этого использовалась функция `rotate()`\n* Масштабирование с использованием функции `scale()`\n\nТрансформации трехмерных объектов не отличаются по своему функционалу. Мы так же можем использовать только эти типы, но для них существует специальный синтаксис. Чтобы браузеру было легче, при трансформации трехмерных объектов к названию функции дописывается `3d`. Таким образом мы получаем 3 функции для трехмерных элементов:\n\n* `translate3d()` — перемещение\n* `rotate3d()` — вращение\n* `scale3d()` — масштабирование\n\nЕдинственная трансформация, которая отсутствует для оси _z_ — `skew()`\n\n## transform-style\n\nДля корректной демонстрации всех этих трансформаций необходимо иметь настоящий трехмерный объект, а не только ось _z_. В качестве каноничного примера используют куб. Для его создания понадобится воспользоваться новым свойством, а именно `transform-style`, которое принимает одно из двух значений:\n\n* `flat`. Значение по умолчанию. Оно говорит о том, что элемент находится в той же плоскости, что и его родитель. Именно так мы видим элементы в большинстве случаев и в предыдущих уроках в частности\n* `preserve-3d` — элемент как бы находится в своём трехмерном пространстве, а не в пространстве своего родителя. Это означает, что элементы будут независимы друг друга. Например, они могут проходить сквозь друг друга\n\nВначале это может немного запутать, но проще всего взглянуть на оба значения в контексте примера:\n\n<https://codepen.io/hexlet/pen/abwPYMr>\n\nВ левом примере зелёный блок находится выше красного, это объясняется тем, что элементы находятся в одном двухмерном пространстве и зависят друг от друга. Как бы вы не трансформировали зелёный блок он никак не сможет взаимодействовать с красным блоком, так как находится перед ним.\n\nВ правом примере значение `preserve-3d` для красного блока создает собственный контекст объёмного пространства. Все дочерние элементы не просто существуют рядом друг с другом, а находятся в едином трехмерном пространстве, что позволяет элементам проходить друг через друга и перемещаться относительно общих осей.\n\nПроще всего думать об этом так, что `flat` создает единое двухмерное пространство, а `preserve-3d` трехмерное. Это добавляет новые возможности по расположению элементов друг с другом.\n\n---\n\n**Важно:** свойство `transform-style` устанавливается единожды для _родительского_ элемента. Так как свойство отвечает за создание пространства, то нет смысла в установке свойства дочерним элементам. В примере выше таким блоком стал красный элемент. Так же важно помнить, что речь идёт о прямых потомках. Если добавить новый элемент внутрь зелёного блока, то для него пространство будет определяться значением `flat`\n\n---\n\nТеперь настало время узнать, как работают уже знакомые трансформации, но в трехмерном пространстве. В качестве примера возьмём самый примитивный трехмерный объект — куб. Все его грани сделаны полупрозрачными, чтобы легче было ориентироваться как он выглядит в пространстве. Сейчас же мы смотрим ровно в его центральную точку передней грани. Это будет начальной позицией при любой трансформации, которую мы сделаем ниже. Вы же можете менять начальную точку используя свойство `perspective-origin` — это будет давать чуть другой эффект, так как взгляд будет немного под другим углом, в прямом смысле этого слова.\n\n<https://codepen.io/hexlet/pen/mdwYxEL>\n\n## Перемещение\n\nДля перемещения трехмерных объектов используются функции:\n\n* `translateX()`\n* `translateY()`\n* `translateZ()`\n\nи их «старший брат» — `translate3d(x, y, z)`. Оно просто объединяет все три функции для удобства написания. Следующие две записи равнозначны:\n\n```css\n.block {\n transform: translateX(10px) translateY(10px) translateZ(10px);\n transform: translate3d(10px, 10px, 10px);\n}\n```\n\nПеремещение по координатам _x_ и _y_ достаточно очевидны. А как происходит перемещение по оси _z_? Браузер, при изменении положения по оси _z_ перемещает элемент ближе или дальше от начального месторасположения. При этом, если элемент перемещается дальше, то он уменьшается, а если перемещается ближе, то увеличивается. Такой эффект можно рассмотреть на самом кубе. Передняя и задняя стенка куба располагаются с использованием функции `translateZ()`. В примере ниже были убраны все грани кроме фронтальной и задней, а также куб был немного развернут.\n\n<https://codepen.io/hexlet/pen/QWgRZKQ>\n\nГрани имеют следующие свойства:\n\n```css\n.front {\n transform: translateZ(150px);\n}\n\n.back {\n transform: translateZ(-150px);\n}\n```\n\nДля достижения эффекта куба фронтальная грань была перемещена по оси _z_ на 150 пикселей ближе к пользователю. Это привело к побочному эффекту: грань теперь имеет размер не 300x300 пикселей, как указано, а 382x382 пикселя. Как можно понять, такие трансформации преобразуют именно размеры элементов, что важно учитывать при встраивании трансформированных объектов в уже готовые шаблоны страниц.\n\nЗадняя грань претерпела похожие трансформации: она была отдалена на 150 пикселей назад относительно своего начального месторасположения. Это изменило и изначальный размер самого квадрата. Теперь он имеет размер 250x250 пикселей.\n\n---\n\n**Важно:** обратите внимание, что трансформация по одной оси и на одинаковое количество пикселей не привело к тому, что элементы увеличились и уменьшились на одинаковое количество пикселей. Здесь прямая связь от свойства, изначальных размеров, положительности или отрицательности значения, а также значения перспективы. Более полно, со всеми формулами и матрицами описание приведено в официальной спецификации.\n\nЕсли вы не собираетесь делать свои мультфильмы на CSS, то полностью разбираться в этом не нужно. Главное уловить суть того, как свойства влияют на элементы.\n\n---\n\n## Вращение\n\nФункции, предоставляемые спецификацией CSS повторяют аналогичные функции для перемещения. Вращение элемента осуществляется с помощью следующих функций:\n\n* `rotateX()` — вращение по оси _x_\n* `rotateY()` — вращение по оси _y_\n* `rotateZ()` — вращение по оси _z_\n* `rotate3d(x, y, z)` — вращение по осям _x_, _y_ и _z_\n\nПроще всего увидеть вращение элементов на примере анимации куба. Для каждой оси вынесен отдельный пример\n\n<https://codepen.io/hexlet/pen/MWodPdM>\n\n---\n\n**Важно:** обратите внимание на то, как элементы выстроены изначально. В примере используется три куба друг под другом и мы их видим так, как это было бы в жизни: у верхнего куба видна нижняя грань, так как он находится выше нашего взгляда, а у нижнего куба мы видим его верхнюю грань. Это происходит из-за того, что перспектива в примере выставлена у общего для всех этих кубов блока. В данном случае перспектива установлена у тега `<body>`, поэтому объекты располагаются в единой области относительно друг друга, но на разной высоте\n\n---\n\n## Масштабирование\n\nНет ничего удивительного, что для масштабирования элемента в трехмерном пространстве используются такие же по замыслу функции, как и в прошлых примерах:\n\n* `scaleX()` — масштабирование по оси _x_\n* `scaleY()` — масштабирование по оси _y_\n* `scaleZ()` — масштабирование по оси _z_\n* `scale3d(x, y, z)` — масштабирование по осям _x_, _y_ и _z_\n\nДиапазон значений не отличается от двухмерного пространства — значения от 0 до 1 уменьшают элемент, значения выше 1 увеличивают элемент по одной из оси. Отрицательные значения обеспечат эффект «отзеркаливания» элемента.\n\n<https://codepen.io/hexlet/pen/abwrQqW>\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":4431,"name":"theory","url":"/courses/css-transform/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":4431,"name":"theory","url":"/courses/css-transform/lessons/intro/theory_unit"}],"id":1958,"slug":"intro","state":"approved","name":"Введение","course_order":100,"goal":"Знакомимся с целями и задачами курса CSS: Трансформации","self_study":null,"theory_video_provider":null,"theory_video_uid":null,"theory":"Трансформации с использованием CSS — возможность, пришедшая с появлением стандарта CSS3. Их использование добавило возможность перемещать, вращать, искажать элемент. Причем как в двумерной плоскости, так и в трехмерной. Это совершенно новая грань визуальной работы с объектами на странице.\n\nТрансформации — база для создания анимаций любых типов, от небольших анимаций интерфейса, до сложных многоступенчатых анимаций.\n\nВ процессе прохождения курса вы познакомитесь со следующими темами:\n\n* Двумерные и трехмерные системы координат и их особенности при работе в браузере\n* Перемещение, вращение и искажение объектов в двумерной системе координат\n* Создание трехмерных объектов\n* Понятие перспективы и точки зрения на объект\n* Создание псевдотрехмерного эффекта\n* Создание обратной стороны трехмерного объекта\n* Использование матриц при трансформации\n\n## Практика\n\nМногие из уроков в данном курсе будут иметь практики с возможностью перехода в веб-доступ. Старайтесь не просто выполнять задание, а после успешного прохождения также экспериментируйте с кодом и возможностями, которые вы узнали.\n\nПрактики в этом курсе построены по системе тестирования скриншотов. В отличие от других курсов, здесь идет проверка не по значениям, которые вы указываете, а делается скриншот страницы с вашими стилями и сравнивается со скриншотами решения учителя. Вы можете легко увидеть, как должна выглядеть страница при разных разрешениях _viewport_.\n\nПосмотреть скриншоты со стилями из решения учителя вы можете в директории \\_\\_tests__/__image_snapshots\\_\\_.\n\n## Проверка практики\n\nПрактики проверяются методом _сравнения скриншотов_. Каждое упражнение содержит эталонное решение, с которого снимается скриншот. После нажатия кнопки «Проверить» тесты автоматически снимают скриншот с вашего решения и накладывают его на эталонное изображение. В случае расхождения изображений более, чем на 7%, тесты выдают ошибку. Они могут быть двух видов:\n\n* `Expected image to be the same size as the snapshot (1280x863), but was different (другие значения)`. Система говорит вам о том, что размеры изображений не совпадают. Скорее всего есть проблемы в отступах/высоте или межстрочном интервале.\n* `Expected image to match or be a close match to snapshot but was different from snapshot`. По своему размеру скриншоты полностью совпадают, но обнаружились несовпадения между изображениями. Допустимый порог равен 7%.\n\nЕсли у вас одна из этих ошибок, то внутри системы автоматически сгенерируется скриншот, который можно найти в директории `/__tests__/__image_snapshots__/__diff_output__/`. Перейти в эту директорию можно с помощью левой панели внутри упражнения.\n\nСкриншот состоит из трех частей:\n\n1. Слева находится эталонное изображение.\n2. Справа находится изображение, полученное с вашим решением.\n3. По центру результат наложения. Красным цветом выделяются области, которые не совпадают. Обращайте на них внимание. Поначалу это может быть сложно, но со временем вы научитесь быстрее читать результат теста.\n\n\n\nПосмотрите на место, выделенное красным цветом. В левом изображении оно меньше, чем в правом. Поэтому при наложении появились отличия. Это отличие за собой потянет и расположение остальных элементов. Поэтому всегда двигайтесь сверху вниз по изображению. Возможно, что исправление одной ошибки исправит и все остальные.\n\n### CodePen\n\nДругая возможность применить навыки, полученные при работе с курсом — использование сервиса [CodePen](https://codepen.io). Вы можете создать свой **pen**, внутри которого экспериментировать со свойствами.\n\nТакже в каждом уроке курса будут представлены примеры, которые подгружаются с **CodePen**. Они доступны для изучения, а также вы имеете возможность в режиме реального времени вносить правки и следить за результатом. Не упускайте такую возможность.\n\nНе забывайте постоянно практиковаться, и тогда ваши навыки работы с контентом позволят быстро и грамотно оформлять весь контент страницы или приложения.\n"},"id":227,"slug":"css-transform","challenges_count":1,"name":"CSS: Transform (трансформация объектов)","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"paid","description":"На этом курсе вы изучите трансформацию в CSS. Вы узнаете больше о перемещении, вращении и деформации блоков. В итоге вы научитесь создавать креативные блоки, использовать эффект псевдотрехмерности, добавлять движение блоков. Трансформации пригодятся, если вы решите заниматься анимациями и созданием дизайнерских макетов. Знания из этого курса помогают программистам реализовывать сложные дизайнирские проекты, которые используют в рекламных целях. Этот курс подойдет фронтенд-программистам, которые хотят разобраться в красивых анимациях.","kind":"advanced","updated_at":"2026-01-20T11:44:24.240Z","language":"html","duration_cache":22080,"skills":["Вращать, перемещать и искажать двумерные объекты на странице","Создавать эффект псевдотрехмерности с помощью трансформаций","Переводить плоские объекты в объёмные, добавляя для них новую ось","Использовать трансформации для трехмерных объектов","Создавать перспективу и управлять точкой зрения на объект","Определять точку трансформации на объекте"],"keywords":["CSS3","HTML5","CSS Transforms","CSS перспектива","Трёхмерные объекты","Анимации"],"lessons_count":7,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NzA5MywicHVyIjoiYmxvYl9pZCJ9fQ==--279965a23904173cf8cc5bbc553aadbe88c59eed/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJwbmciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--6067466c2912ca31a17eddee04b8cf2a38c6ad17/image.png"},"recommendedLandings":[{"stack":{"id":19,"slug":"layout-designer","title":"Профессиональная верстка","audience":"for_beginners","start_type":"anytime","pricing_model":"purchase","priority":"medium","kind":"track","state":"published","stack_state":"finished","order":1700,"duration_in_months":5},"id":26,"slug":"professional-layout","title":"Профессиональная верстка","subtitle":"Навык адаптивной вёрстки с современными подходами для корректного отображения сайтов на любых устройствах и разрешениях","subtitle_for_lists":"Адаптивная вёрстка для отображения на любых устройствах ","locale":"ru","current":true,"duration_in_months_text":"5 месяцев","stack_slug":"layout-designer","price_text":"от 3 900 ₽","duration_text":"5 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAzNCwicHVyIjoiYmxvYl9pZCJ9fQ==--ba516ea9573bdfcd1d21e2aa0fff8818561828f2/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Typing-bro.png"},{"stack":{"id":114,"slug":"css-animation","title":"Анимация CSS","audience":"for_programmers","start_type":"anytime","pricing_model":"subscription","priority":"medium","kind":"track","state":"published","stack_state":"finished","order":2900,"duration_in_months":1},"id":185,"slug":"css-animation","title":"Анимация CSS","subtitle":"Анимации в вебе: как использовать CSS и JavaScript для создания плавных эффектов","subtitle_for_lists":"Освоите CSS-анимации для улучшения UX","locale":"ru","current":true,"duration_in_months_text":"1 месяц","stack_slug":"css-animation","price_text":"от 3 900 ₽","duration_text":"1 месяц","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAyNSwicHVyIjoiYmxvYl9pZCJ9fQ==--3b94875bb52777724a7b11b075b8891f331d8cdf/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programming-amico.png"}],"lessonMemberUnit":null,"accessToLearnUnitExists":false,"accessToCourseExists":false},"url":"/courses/css-transform/lessons/3d-transforming/theory_unit","version":"8f286f6358a90a7bef2263b3a6edf5a90a94fa42","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">CSS: Transform (трансформация объектов)</p></div><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size);margin-bottom:var(--mantine-spacing-xl)" class="m_8a5d1357 mantine-Title-root" data-order="1">Теория: 3D трансформации. Функции</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"3D трансформации. Функции","inLanguage":"ru","isPartOf":{"@type":"LearningResource","name":"CSS: Transform (трансформация объектов)"},"isAccessibleForFree":"False","hasPart":{"@type":"WebPageElement","isAccessibleForFree":"False","cssSelector":".paywalled"}}</script><div class=""><div style="--alert-color:var(--mantine-color-indigo-light-color);margin-bottom:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-lg)" class="m_66836ed3 mantine-Alert-root" id="mantine-_R_remqrdub_" role="alert" aria-describedby="mantine-_R_remqrdub_-body" aria-labelledby="mantine-_R_remqrdub_-title"><div class="m_a5d60502 mantine-Alert-wrapper"><div class="m_667f2a6a mantine-Alert-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-rocket "><path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3"></path><path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3"></path><path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg></div><div class="m_667c2793 mantine-Alert-body"><div class="m_6a03f287 mantine-Alert-title"><span id="mantine-_R_remqrdub_-title" class="m_698f4f23 mantine-Alert-label">Полный доступ к материалам</span></div><div id="mantine-_R_remqrdub_-body" class="m_7fa78076 mantine-Alert-message"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Зарегистрируйтесь и получите доступ к этому и десяткам других курсов</p><a style="--button-height:var(--button-height-xs);--button-padding-x:var(--button-padding-x-xs);--button-fz:var(--mantine-font-size-xs);--button-bg:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-hover:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-color:var(--mantine-color-white);--button-bd:none" class="mantine-focus-auto mantine-active m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root" data-variant="gradient" data-size="xs" href="/u/new"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">Зарегистрироваться</span></span></a></div></div></div></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><p>В уроках посвящённых трансформации двухмерных объектов мы научились использовать несколько видов трансформации:</p>
<ul>
<li>Перемещение. За это отвечает функция <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">translate()</code></li>
<li>Вращение. Для этого использовалась функция <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">rotate()</code></li>
<li>Масштабирование с использованием функции <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">scale()</code></li>
</ul>
<p>Трансформации трехмерных объектов не отличаются по своему функционалу. Мы так же можем использовать только эти типы, но для них существует специальный синтаксис. Чтобы браузеру было легче, при трансформации трехмерных объектов к названию функции дописывается <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">3d</code>. Таким образом мы получаем 3 функции для трехмерных элементов:</p>
<ul>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">translate3d()</code> — перемещение</li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">rotate3d()</code> — вращение</li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">scale3d()</code> — масштабирование</li>
</ul>
<p>Единственная трансформация, которая отсутствует для оси <em>z</em> — <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">skew()</code></p>
<h2 id="heading-2-1">transform-style</h2>
<p>Для корректной демонстрации всех этих трансформаций необходимо иметь настоящий трехмерный объект, а не только ось <em>z</em>. В качестве каноничного примера используют куб. Для его создания понадобится воспользоваться новым свойством, а именно <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">transform-style</code>, которое принимает одно из двух значений:</p>
<ul>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">flat</code>. Значение по умолчанию. Оно говорит о том, что элемент находится в той же плоскости, что и его родитель. Именно так мы видим элементы в большинстве случаев и в предыдущих уроках в частности</li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">preserve-3d</code> — элемент как бы находится в своём трехмерном пространстве, а не в пространстве своего родителя. Это означает, что элементы будут независимы друг друга. Например, они могут проходить сквозь друг друга</li>
</ul>
<p>Вначале это может немного запутать, но проще всего взглянуть на оба значения в контексте примера:</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://codepen.io/hexlet/pen/abwPYMr" rel="noopener noreferrer" target="_blank">https://codepen.io/hexlet/pen/abwPYMr</a></p>
<p>В левом примере зелёный блок находится выше красного, это объясняется тем, что элементы находятся в одном двухмерном пространстве и зависят друг от друга. Как бы вы не трансформировали зелёный блок он никак не сможет взаимодействовать с красным блоком, так как находится перед ним.</p>
<p>В правом примере значение <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">preserve-3d</code> для красного блока создает собственный контекст объёмного пространства. Все дочерние элементы не просто существуют рядом друг с другом, а находятся в едином трехмерном пространстве, что позволяет элементам проходить друг через друга и перемещаться относительно общих осей.</p>
<p>Проще всего думать об этом так, что <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">flat</code> создает единое двухмерное пространство, а <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">preserve-3d</code> трехмерное. Это добавляет новые возможности по расположению элементов друг с другом.</p>
<hr/>
<p><strong>Важно:</strong> свойство <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">transform-style</code> устанавливается единожды для <em>родительского</em> элемента. Так как свойство отвечает за создание пространства, то нет смысла в установке свойства дочерним элементам. В примере выше таким блоком стал красный элемент. Так же важно помнить, что речь идёт о прямых потомках. Если добавить новый элемент внутрь зелёного блока, то для него пространство будет определяться значением <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">flat</code></p>
<hr/>
<p>Теперь настало время узнать, как работают уже знакомые трансформации, но в трехмерном пространстве. В качестве примера возьмём самый примитивный трехмерный объект — куб. Все его грани сделаны полупрозрачными, чтобы легче было ориентироваться как он выглядит в пространстве. Сейчас же мы смотрим ровно в его центральную точку передней грани. Это будет начальной позицией при любой трансформации, которую мы сделаем ниже. Вы же можете менять начальную точку используя свойство <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">perspective-origin</code> — это будет давать чуть другой эффект, так как взгляд будет немного под другим углом, в прямом смысле этого слова.</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://codepen.io/hexlet/pen/mdwYxEL" rel="noopener noreferrer" target="_blank">https://codepen.io/hexlet/pen/mdwYxEL</a></p>
<h2 id="heading-2-2">Перемещение</h2>
<p>Для перемещения трехмерных объектов используются функции:</p>
<ul>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">translateX()</code></li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">translateY()</code></li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">translateZ()</code></li>
</ul>
<p>и их «старший брат» — <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">translate3d(x, y, z)</code>. Оно просто объединяет все три функции для удобства написания. Следующие две записи равнозначны:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">.block {
transform: translateX(10px) translateY(10px) translateZ(10px);
transform: translate3d(10px, 10px, 10px);
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Перемещение по координатам <em>x</em> и <em>y</em> достаточно очевидны. А как происходит перемещение по оси <em>z</em>? Браузер, при изменении положения по оси <em>z</em> перемещает элемент ближе или дальше от начального месторасположения. При этом, если элемент перемещается дальше, то он уменьшается, а если перемещается ближе, то увеличивается. Такой эффект можно рассмотреть на самом кубе. Передняя и задняя стенка куба располагаются с использованием функции <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">translateZ()</code>. В примере ниже были убраны все грани кроме фронтальной и задней, а также куб был немного развернут.</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://codepen.io/hexlet/pen/QWgRZKQ" rel="noopener noreferrer" target="_blank">https://codepen.io/hexlet/pen/QWgRZKQ</a></p>
<p>Грани имеют следующие свойства:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">.front {
transform: translateZ(150px);
}
.back {
transform: translateZ(-150px);
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Для достижения эффекта куба фронтальная грань была перемещена по оси <em>z</em> на 150 пикселей ближе к пользователю. Это привело к побочному эффекту: грань теперь имеет размер не 300x300 пикселей, как указано, а 382x382 пикселя. Как можно понять, такие трансформации преобразуют именно размеры элементов, что важно учитывать при встраивании трансформированных объектов в уже готовые шаблоны страниц.</p>
<p>Задняя грань претерпела похожие трансформации: она была отдалена на 150 пикселей назад относительно своего начального месторасположения. Это изменило и изначальный размер самого квадрата. Теперь он имеет размер 250x250 пикселей.</p>
<hr/>
<p><strong>Важно:</strong> обратите внимание, что трансформация по одной оси и на одинаковое количество пикселей не привело к тому, что элементы увеличились и уменьшились на одинаковое количество пикселей. Здесь прямая связь от свойства, изначальных размеров, положительности или отрицательности значения, а также значения перспективы. Более полно, со всеми формулами и матрицами описание приведено в официальной спецификации.</p>
<p>Если вы не собираетесь делать свои мультфильмы на CSS, то полностью разбираться в этом не нужно. Главное уловить суть того, как свойства влияют на элементы.</p>
<hr/>
<h2 id="heading-2-3">Вращение</h2>
<p>Функции, предоставляемые спецификацией CSS повторяют аналогичные функции для перемещения. Вращение элемента осуществляется с помощью следующих функций:</p>
<ul>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">rotateX()</code> — вращение по оси <em>x</em></li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">rotateY()</code> — вращение по оси <em>y</em></li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">rotateZ()</code> — вращение по оси <em>z</em></li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">rotate3d(x, y, z)</code> — вращение по осям <em>x</em>, <em>y</em> и <em>z</em></li>
</ul>
<p>Проще всего увидеть вращение элементов на примере анимации куба. Для каждой оси вынесен отдельный пример</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://codepen.io/hexlet/pen/MWodPdM" rel="noopener noreferrer" target="_blank">https://codepen.io/hexlet/pen/MWodPdM</a></p>
<hr/>
<p><strong>Важно:</strong> обратите внимание на то, как элементы выстроены изначально. В примере используется три куба друг под другом и мы их видим так, как это было бы в жизни: у верхнего куба видна нижняя грань, так как он находится выше нашего взгляда, а у нижнего куба мы видим его верхнюю грань. Это происходит из-за того, что перспектива в примере выставлена у общего для всех этих кубов блока. В данном случае перспектива установлена у тега <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight"><body></code>, поэтому объекты располагаются в единой области относительно друг друга, но на разной высоте</p>
<hr/>
<h2 id="heading-2-4">Масштабирование</h2>
<p>Нет ничего удивительного, что для масштабирования элемента в трехмерном пространстве используются такие же по замыслу функции, как и в прошлых примерах:</p>
<ul>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">scaleX()</code> — масштабирование по оси <em>x</em></li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">scaleY()</code> — масштабирование по оси <em>y</em></li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">scaleZ()</code> — масштабирование по оси <em>z</em></li>
<li><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">scale3d(x, y, z)</code> — масштабирование по осям <em>x</em>, <em>y</em> и <em>z</em></li>
</ul>
<p>Диапазон значений не отличается от двухмерного пространства — значения от 0 до 1 уменьшают элемент, значения выше 1 увеличивают элемент по одной из оси. Отрицательные значения обеспечат эффект «отзеркаливания» элемента.</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://codepen.io/hexlet/pen/abwrQqW" rel="noopener noreferrer" target="_blank">https://codepen.io/hexlet/pen/abwrQqW</a></p></div><div style="margin-block:var(--mantine-spacing-xl)" class=""><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md)" class="m_8a5d1357 mantine-Title-root" data-order="2">Рекомендуемые программы</h2><style data-mantine-styles="inline">.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xs);--carousel-slide-size:70%;}@media(min-width: 36em){.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xl);--carousel-slide-size:50%;}}</style><div style="--carousel-control-size:calc(2.5rem * var(--mantine-scale));--carousel-controls-offset:var(--mantine-spacing-sm);margin-bottom:var(--mantine-spacing-lg);padding-block:var(--mantine-spacing-sm);background:var(--app-color-surface)" class="m_17884d0f mantine-Carousel-root responsiveClassName" data-orientation="horizontal" data-include-gap-in-size="true"><div class="m_39bc3463 mantine-Carousel-controls" data-orientation="horizontal"><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="previous" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="next" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div><div class="m_a2dae653 mantine-Carousel-viewport" data-type="media"><div class="m_fcd81474 mantine-Carousel-container __m__-_R_2mremqrdub_" data-orientation="horizontal"><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/professional-layout?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">5 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Профессиональная верстка</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Адаптивная вёрстка для отображения на любых устройствах </p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAzNCwicHVyIjoiYmxvYl9pZCJ9fQ==--ba516ea9573bdfcd1d21e2aa0fff8818561828f2/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Typing-bro.png" alt="Профессиональная верстка" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 3 900 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/css-animation?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">1 месяц</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Для продвинутых</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Анимация CSS</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Освоите CSS-анимации для улучшения UX</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAyNSwicHVyIjoiYmxvYl9pZCJ9fQ==--3b94875bb52777724a7b11b075b8891f331d8cdf/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programming-amico.png" alt="Анимация CSS" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 3 900 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md);font-size:var(--mantine-font-size-h3)" class="m_8a5d1357 mantine-Title-root" data-order="2" data-responsive="true">Каталог</h2><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Полный список доступных курсов по разным направлениям</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="/vite/assets/development-BVihs_d5.png" alt="Orientation"/></div></div></div></a></div></div></div></div></div></div></div></div></div><style data-mantine-styles="inline">.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:8.333333333333334%;--col-max-width:8.333333333333334%;}@media(min-width: 48em){.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem" class="m_96bdd299 mantine-Grid-col __m__-_R_1bdub_"><div style="margin-inline:var(--mantine-spacing-xs)" class="mantine-visible-from-sm"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-lg);text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/css-transform/lessons/3d-transforming/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label"><span style="margin-inline-end:var(--mantine-spacing-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Дальше</span>→</span></span></a><a style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Навигация по теме</span><span class="m_57492dcc mantine-NavLink-description">Теория</span></div><span class="m_690090b5 mantine-NavLink-section" data-position="right"></span></a><div style="margin-block:var(--mantine-spacing-lg)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div><div style="margin-block:var(--mantine-spacing-lg)" class=""><div style="justify-content:space-between;margin-bottom:calc(0.1875rem * var(--mantine-scale));color:var(--mantine-color-dimmed);font-size:var(--mantine-font-size-xs)" class="m_8bffd616 mantine-Flex-root __m__-_R_qimrbdub_"><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Завершено</p><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">0 / 7</p></div><div style="--progress-size:var(--progress-size-sm)" class="m_db6d6462 mantine-Progress-root" data-size="sm"><div style="--progress-section-size:0%;--progress-section-color:var(--mantine-color-gray-filled)" class="m_2242eb65 mantine-Progress-section" role="progressbar" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-valuetext="0%"></div></div></div><button style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root" type="button"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Обсуждения (архив)</span><span class="m_57492dcc mantine-NavLink-description"></span></div></button><div style="--toc-bg:var(--mantine-color-blue-light);--toc-color:var(--mantine-color-blue-light-color);--toc-size:var(--mantine-font-size-sm);--toc-radius:var(--mantine-radius-sm);margin-top:var(--mantine-spacing-xl)" class="m_bcaa9990 mantine-TableOfContents-root" data-variant="light" data-size="sm"></div></div><div class="mantine-hidden-from-sm"><div style="--stack-gap:0rem;--stack-align:stretch;--stack-justify:flex-start" class="m_6d731127 mantine-Stack-root"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-xs);padding:0rem;text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/css-transform/lessons/3d-transforming/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></a><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-Bukl1lYy.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-BrRXra1y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>