Трансформация элементов. Часть 2.

В этой статье мы продолжим изучать трансформации элементов, рассмотрим функции преобразования элементов, которые позволяют сдвигать элементы как в двухмерном, так и трехмерном пространстве, детально познакомимся с перспективой обзора элемента, поговорим о матрицах преобразований и научимся изменять точку преобразования элемента.

Рис. 180а Пример трансформации.

Сдвиг элементов

Следующая функция преобразования translate(), определяет двухмерное преобразование путем сдвига элемента влево, вправо, вверх или вниз, используя координаты по оси X и Y (отрицательные значения отвечают за сдвиг влево и вверх, положительные за сдвиг вправо и вниз).


Обращаю Ваше внимание, что элемент, к которому применяется сдвиг не влияет на поток документа (элемент перекрывает другие элементы), это правило верно и для других трансформаций.


Давайте перейдем к примеру:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<title>Сдвиг элементов</title>
<style>
.static {
display: inline-block; /* блочно-строчные элементы (выстраиваем элементы в линейку) */
margin: 10px; /* внешние отступы со всех сторон */
background: gray; /* цвет заднего фона */
}
div {
width: 180px; /* ширина элемента */
height: 100px; /* высота элемента */
line-height: 100px; /* высота строки (выраывниваем по вертикали) */
text-align: center; /* горизонтальное выравнивание текста по центру */
transition: 0.2s; /* переходный эффект составляет 200 миллисекунд (0,2 секунды) */
}
.test2, .test4, .test6 {background: orange;} /* цвет заднего фона */
.test, .test3, .test5 {background: plum;} /* цвет заднего фона */
.test:hover {
transform: translate(20px, 20px); /* сдвиг элемента при наведении */
}
.test2:hover {
transform: translate(-20px, -20px); /* сдвиг элемента при наведении */
}
.test3:hover {
transform: translate(20px, 0); /* сдвиг элемента при наведении */
}
.test4:hover {
transform: translate(-20px, 0); /* сдвиг элемента при наведении */
}
.test5:hover {
transform: translate(0, 20px); /* сдвиг элемента при наведении */
}
.test6:hover {
transform: translate(0, -20px); /* сдвиг элемента при наведении */
}
</style>
</head>
	<body>
		<div class = "static"><div class = "test">translate(20px, 20px)</div></div>
		<div class = "static"><div class = "test2">translate(-20px, -20px)</div></div>
		<div class = "static"><div class = "test3">translate(20px, 0)</div></div><br>
		<div class = "static"><div class = "test4">translate(-20px, 0)</div></div>
		<div class = "static"><div class = "test5">translate(0, 20px)</div></div>
		<div class = "static"><div class = "test6">translate(0, -20px)</div></div>
	</body>
</html>

В этом примере мы использовали различные значения для функции translate(). Первое значение функции определяет горизонтальный сдвиг элемента (положительное значение сдвигает элемент вправо по оси X, а отрицательное влево по оси X). Второе значение функции определяет вертикальный сдвиг элемента (положительное значение сдвигает элемент вниз по оси Y, а отрицательное вверх по оси Y). Если указать значение 0 для любой оси, то элемент не будет по ней сдвигаться, по аналогии с другими функциями.

Результат нашего примера:

Рис. 181 Пример сдвига элементов (функция преобразования элемента translate).
Рис. 181 Пример сдвига элементов (функция преобразования элемента translate).

Вы можете проводить преобразование путем сдвига элемента и для конкретной оси, для этого в CSS существуют функции преобразования translateX(), translateY() и translateZ(). Рассмотрим их в следующем примере:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<title>Сдвиг элементов по конкретным осям</title>
<style>
.static {
display: inline-block; /* блочно-строчные элементы (выстраиваем элементы в линейку) */
margin: 10px; /* внешние отступы со всех сторон */
background: gray; /* цвет заднего фона */
}
div {
width: 180px; /* ширина элемента */
height: 100px; /* высота элемента */
line-height: 100px; /* высота строки (выраывниваем по вертикали) */
text-align: center; /* горизонтальное выравнивание текста по центру */
transition: 0.2s; /* переходный эффект составляет 200 миллисекунд (0,2 секунды) */
}
.test2, .test4, .test6 {background: orange;} /* цвет заднего фона */
.test, .test3, .test5 {background: plum;} /* цвет заднего фона */
.test:hover {
transform: translateX(20px); /* сдвиг элемента по оси X при наведении */
}
.test2:hover {
transform: translateX(-20px); /* сдвиг элемента по оси X при наведении */
}
.test3:hover {
transform: translateY(20px); /* сдвиг элемента по оси Y при наведении */
}
.test4:hover {
transform: translateY(-20px); /* сдвиг элемента по оси Y при наведении */
}
.test5:hover {
transform: perspective(500px) rotateX(45deg) translateZ(30px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X, сдвиг элемента по оси Z ) */
}
.test6:hover {
transform: perspective(500px) rotateX(45deg) translateZ(-30px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X, сдвиг элемента по оси Z ) */
}
</style>
</head>
	<body>
		<div class = "static"><div class = "test">translateX(20px)</div></div>
		<div class = "static"><div class = "test2">translateX(-20px)</div></div>
		<div class = "static"><div class = "test3">translateY(20px)</div></div><br>
		<div class = "static"><div class = "test4">translateY(-20px)</div></div>
		<div class = "static"><div class = "test5">translateZ(30px)</div></div>
		<div class = "static"><div class = "test6">translateZ(-30px)</div></div>
	</body>
</html>

В этом примере были использованы различные значения функций translateX(), translateY() и translateZ(), благодаря которым, мы сдвигаем элементы по необходимой оси.

Для демонстрации работы трехмерного сдвига элемента функцией translateZ(), мы добавили функцию rotateX(), которая поворачивает наш элемент по оси X и функцию преобразования perspective(), которая определяет перспективу обзора элемента, создавая для пользователя иллюзию глубины.

Результат нашего примера:

Рис. 182 Сдвиг элементов по конкретным осям (функции преобразования элементов translateX, translateY и translateZ).
Рис. 182 Сдвиг элементов по конкретным осям (функции преобразования элементов translateX, translateY и translateZ).

Трехмерный сдвиг элементов

Следующая функция - translate3d() позволяет нам задать трехмерное преобразование путем сдвига элемента, используя координаты трёх осей (X,Y и Z). Перейдем к примеру:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<title>Трехмерный сдвиг элементов</title>
<style>
.static {
display: inline-block; /* блочно-строчные элементы (выстраиваем элементы в линейку) */
margin: 10px; /* внешние отступы со всех сторон */
background: gray; /* цвет заднего фона */
}
div {
width: 180px; /* ширина элемента */
height: 100px; /* высота элемента */
line-height: 100px; /* высота строки (выраывниваем по вертикали) */
text-align: center; /* горизонтальное выравнивание текста по центру */
transition: 0.2s; /* переходный эффект составляет 200 миллисекунд (0,2 секунды) */
}
.test2, .test4, .test6 {background: orange;} /* цвет заднего фона */
.test, .test3, .test5 {background: plum;} /* цвет заднего фона */
.test:hover {
transform: perspective(500px) rotateX(45deg) translate3d(20px,20px,20px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X, трехмерный сдвиг элемента) */
}
.test2:hover {
transform: perspective(500px) rotateX(45deg) translate3d(-20px,-20px,-20px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X, трехмерный сдвиг элемента) */
}
.test3:hover {
transform: perspective(500px) rotateX(45deg) translate3d(-20px,-20px,-80px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X, трехмерный сдвиг элемента) */
}
.test4:hover {
transform: perspective(500px) rotateX(45deg) translate3d(0,0,-80px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X, трехмерный сдвиг элемента) */
}
.test5:hover {
transform: perspective(500px) rotateX(45deg) translate3d(20px,0, 40px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X, трехмерный сдвиг элемента) */
}
.test6:hover {
transform: perspective(500px) rotateX(45deg) translate3d(0,20px, 40px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X, трехмерный сдвиг элемента) */
}
</style>
</head>
	<body>
		<div class = "static"><div class = "test">translate3d(20px,20px,20px)*</div></div>
		<div class = "static"><div class = "test2">translate3d(-20px,-20px,-20px)*</div></div>
		<div class = "static"><div class = "test3">translate3d(-20px,-20px,-80px)*</div></div><br>
		<div class = "static"><div class = "test4">translate3d(0,0,-80px)*</div></div>
		<div class = "static"><div class = "test5">translate3d(20px,0, 40px)*</div></div>
		<div class = "static"><div class = "test6">translate3d(0,20px, 40px)*</div></div>
	</body>
</html>

По аналогии с ранее рассмотренными функциями сдвига элементов, функция translate3d() задаёт сдвиг одновременно по осям X,Y и Z. Первое значение функции определяет горизонтальный сдвиг элемента (положительное значение сдвигает элемент вправо по оси X, а отрицательное влево по оси X). Второе значение функции определяет вертикальный сдвиг элемента (положительное значение сдвигает элемент вниз по оси Y, а отрицательное вверх по оси Y). Третее значение функции определяет сдвиг по оси Z (отрицательное значение отдаляет элемент). Если указать значение 0 для любой оси, то элемент не будет по ней сдвигаться, по аналогии с другими функциями.

Результат нашего примера:

Рис. 183 Пример трехмерного сдвига элементов (функция преобразования элемента translate3d).
Рис. 183 Пример трехмерного сдвига элементов (функция преобразования элемента translate3d).

Перспектива обзора элемента

Давайте более детально рассмотрим функцию perspective(), она как мы выяснили ранее, определяет перспективу обзора элемента, создавая для пользователя иллюзию глубины. Чем больше значение, указанное для функции перспективы, тем дальше от пользователя расположен элемент. Значение должно быть больше нуля.

Рассмотрим пример:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<title>Указание перспективы обзора элемента</title>
<style>
.static {
display: inline-block; /* блочно-строчные элементы (выстраиваем элементы в линейку) */
margin: 10px; /* внешние отступы со всех сторон */
background: gray; /* цвет заднего фона */
}
div {
width: 180px; /* ширина элемента */
height: 100px; /* высота элемента */
line-height: 100px; /* высота строки (выраывниваем по вертикали) */
text-align: center; /* горизонтальное выравнивание текста по центру */
transition: 0.2s; /* переходный эффект составляет 200 миллисекунд (0,2 секунды) */
}
.test2, .test4, .test6 {background: orange;} /* цвет заднего фона */
.test, .test3, .test5 {background: plum;} /* цвет заднего фона */
.test:hover {
transform: perspective(50px) rotateX(45deg); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X) */
}
.test2:hover {
transform: perspective(100px) rotateX(45deg); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X) */
}
.test3:hover {
transform: perspective(200px) rotateX(45deg); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X) */
}
.test4:hover {
transform: perspective(300px) rotateX(45deg); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X) */
}
.test5:hover {
transform: perspective(400px) rotateX(45deg); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X) */
}
.test6:hover {
transform: perspective(500px) rotateX(45deg); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот по оси X) */
}
</style>
</head>
	<body>
		<div class = "static"><div class = "test">perspective(50px)*</div></div>
		<div class = "static"><div class = "test2">perspective(100px)*</div></div>
		<div class = "static"><div class = "test3">perspective(200px)*</div></div><br>
		<div class = "static"><div class = "test4">perspective(300px)*</div></div>
		<div class = "static"><div class = "test5">perspective(400px)*</div></div>
		<div class = "static"><div class = "test6">perspective(500px)*</div></div>
	</body>
</html>

Для демонстрации функции perspective() мы дополнительно на элемент воздействуем функцией rotateX(), благодаря, которой поворачиваем элемент по оси X на 45 градусов.

Результат нашего примера:

Рис. 184 Пример указания перспективы обзора элемента (функция преобразования элемента perspective).
Рис. 184 Пример указания перспективы обзора элемента (функция преобразования элемента perspective).

Матрицы преобразований

В CSS все трансформации (функции, которые контролируют преобразования элементов) основаны на следующих двух функциях:

Давайте рассмотрим из чего состоит матрица для двухмерных преобразований:

Рис. 185  Матрица двумерной трансформации. Рис. 185 Матрица двумерной трансформации.

Когда мы применяем двумерную трансформацию, браузер умножает матрицу на вектор [x, y, 1]. Значения X и Y — координаты конкретной точки в локальном пространстве координат.

Рис. 186 Умножение матрицы на вектор. Рис. 186 Умножение матрицы на вектор.

Матрица для элемента, без преобразования будет выглядеть следующим образом:

transform: matrix(1, 0, 0, 1, 0, 0);

Достаточно будет понять того, что у каждого типа трансформаций — своя собственная матрица, давайте рассмотрим пример их использования:

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<title>Матрицы преобразований в CSS</title>
<style>
.static {
display: inline-block; /* блочно-строчные элементы (выстраиваем элементы в линейку) */
margin: 10px; /* внешние отступы со всех сторон */
background: gray; /* цвет заднего фона */
}
div {
width: 180px; /* ширина элемента */
height: 100px; /* высота элемента */
line-height: 100px; /* высота строки (выраывниваем по вертикали) */
text-align: center; /* горизонтальное выравнивание текста по центру */
transition: 0.2s; /* переходный эффект составляет 200 миллисекунд (0,2 секунды) */
}
.test2, .test4, .test6 {background: orange;} /* цвет заднего фона */
.test, .test3, .test5 {background: plum;} /* цвет заднего фона */
.test:hover {
transform: matrix(0.5,0,0,1,0,0); /* используем двухмерную матрицу преобразования при наведении */
}
.test2:hover {
transform: matrix(1,0,0,1.5,0,0); /* используем двухмерную матрицу преобразования при наведении */
}
.test3:hover {
transform: matrix(0,-1, 1,0,0,0); /* используем двухмерную матрицу преобразования при наведении */
}
.test4:hover {
transform: matrix(1,0, -1,1,0,0); /* используем двухмерную матрицу преобразования при наведении */
}
.test5:hover {
transform: matrix(1,0, 0,1,50,0); /* используем двухмерную матрицу преобразования при наведении */
}
.test6:hover {
transform: matrix3d(0.3, -0.4, 0.8, 0, 0.2, 0.9, 0.4, 0, -0.9, 0, 0.4, 0, 0, 0, 0, 1); /* используем трехмерную матрицу преобразования при наведении */
}
</style>
</head>
	<body>
		<div class = "static"><div class = "test">matrix(0.5,0,0,1,0,0)</div></div>
		<div class = "static"><div class = "test2">matrix(1,0,0,1.5,0,0)</div></div>
		<div class = "static"><div class = "test3">matrix(0,-1, 1,0,0,0)</div></div><br>
		<div class = "static"><div class = "test4">matrix(1,0, -1,1,0,0)</div></div>
		<div class = "static"><div class = "test5">matrix(1,0, 0,1,50,0)</div></div>
		<div class = "static"><div class = "test6">matrix3d()</div></div>
	</body>
</html>

В этом примере с помощью функций matrix() и matrix3d() мы производим различные двухмерные и трехмерные трансформации элементов.

Результат нашего примера:

Рис. 187 Пример использования матриц преобразования в CSS.
Рис. 187 Пример использования матриц преобразования в CSS.

При необходимости, вы можете получить более подробное описание функции matrix3d() здесь (на русском), либо в стандарте W3C - разделы 20 и 21.

Точка преобразования элемента

При использовании любого преобразования, браузер пользователя по умолчанию использует в качестве точки начала преобразования центр элемента. В CSS свойство transform-origincss3 позволяет указать произвольное начало координат преобразования элемента. Вспомните, похожее поведение имеет свойство background-positioncss3, которое позволяет задать положение (позицию) фонового изображения, мы подробно рассматривали это свойство в статье "Работа с фоном элемента в CSS".


Обратите внимание, что свойство transform-origincss3 используется только совместно со свойством transformcss3, которое применяет двухмерные или трехмерные трансформации к элементу (функции преобразования элемента).


Для наглядности логика работы свойства transform-origincss3 отображена на изображении:

Рис. 188 Логика работы свойства transform-origin. Рис. 188 Логика работы свойства transform-origin.

  1. Первое значение указывает положение на оси X. Допускается использование числовых значений длины (допустимые единицы измерения CSS), процентное соотношение или одно из следующих трех ключевых слов: left (указывает 0% длины по оси X), center (указывает среднюю точку) или right (указывает 100%). Может быть указано вторым значением при использовании ключевых слов. Допускаются отрицательные значения.
  2. Второе значение указывает положение на оси Y. Допускается использование числовых значений длины (допустимые единицы измерения CSS), процентное соотношение или одно из следующих трех ключевых слов: top (указывает 0% длины по оси Y), center (указывает среднюю точку) или bottom (указывает 100%). Может быть указано первым значением при использовании ключевых слов. Допускаются отрицательные значения.
  3. Третье значение указывает положение на оси Z. Допускается использование только числовых значений длины (допустимые единицы измерения CSS). Допускаются отрицательные значения.

Перейдем к примеру.

<!DOCTYPE html>
<html>
<head>
	<meta charset = "UTF-8">
	<title>Пример изменения точки преобразования элемента</title>
<style>
.static {
display: inline-block; /* блочно-строчные элементы (выстраиваем элементы в линейку) */
margin: 10px; /* внешние отступы со всех сторон */
background: gray; /* цвет заднего фона */
}
div {
width: 180px; /* ширина элемента */
height: 100px; /* высота элемента */
line-height: 100px; /* высота строки (выраывниваем по вертикали) */
text-align: center; /* горизонтальное выравнивание текста по центру */
transition: 0.2s; /* переходный эффект составляет 200 миллисекунд (0,2 секунды) */
}
.test2, .test4, .test6 {background: orange;} /* цвет заднего фона */
.test, .test3, .test5 {background: plum;} /* цвет заднего фона */
.test:hover {
transform: rotate(15deg);	/* поворачиваем элемент при наведении */
transform-origin: 50% 50% 0; /* изменяем точку преобразования элемента при наведении */
}
.test2:hover {
transform: rotate(15deg);	/* поворачиваем элемент при наведении */
transform-origin: left top; /* изменяем точку преобразования элемента при наведении */
}
.test3:hover {
transform: rotate(15deg);	/* поворачиваем элемент при наведении */
transform-origin: center bottom; /* изменяем точку преобразования элемента при наведении */
}
.test4:hover {
transform: rotate(15deg);	/* поворачиваем элемент при наведении */
transform-origin: 100% 0%; /* изменяем точку преобразования элемента при наведении */
}
.test5:hover {
transform: rotate(15deg) perspective(500px);	/* используем несколько функций преобразования для элемента при наведении (перспектива, поворот) */
transform-origin: 50% 50% -250px;  /* изменяем точку преобразования элемента при наведении */
}
.test6:hover {
transform: rotate(15deg) perspective(500px); /* используем несколько функций преобразования для элемента при наведении (перспектива, поворот) */	
transform-origin: 50% top 250px; /* изменяем точку преобразования элемента при наведении */
}
</style>
</head>
	<body>
		<div class = "static"><div class = "test">50% 50% 0</div></div>
		<div class = "static"><div class = "test2">left top</div></div>
		<div class = "static"><div class = "test3">center bottom</div></div><br>
		<div class = "static"><div class = "test4">100% 0%</div></div>
		<div class = "static"><div class = "test5">50% 50% -250px</div></div>
		<div class = "static"><div class = "test6">50% top 250px</div></div>
	</body>
</html>

В этом примере мы использовали для свойства transform-origincss3 различные значения, которые определяют точку начала преобразования элемента. Для пятого и шестого блока мы дополнительно указали значение функции преобразования perspective() для возможности демонстрации изменения точки преобразования по оси Z.

Результат нашего примера:

Рис. 189 Пример изменения точки преобразования элемента.
Рис. 189 Пример изменения точки преобразования элемента.

Обращаю Ваше внимание на то, что свойство transform-origincss3 не влияет на те элементы, которые находятся только под действием функции преобразования translate().

Мы с Вами рассмотрели все функции преобразования элементов, которые в настоящее время используются в той, или иной степени. Если Вас заинтересовала эта тема, вы можете самостоятельно изучить такие современные, но мало используемые свойства CSS, как:


Вопросы и задачи по теме

Перед тем как перейти к изучению следующей темы пройдите практические задания:

  • Для выполнения задания вам понадобится скачать архив и скопировать содержимое архива (HTML файл) в любую папку на вашем жестком диске:

  1. Используя полученные знания составьте следующий документ в котором элементы имеют различную трансформацию, продвинутым заданием будет считаться трансформация родительского элемента:


    Практическое задание № 36.
    Практическое задание № 36.

    Подсказка:

    • Для начала Вам необходимо спозиционировать родительский элемент и задать его детям, абсолютное позиционирование. Эту тему мы подробно рассматривали ранее в статье "Позиционирование элементов в CSS".
    • Вам необходимо для двух вложенных элементов применить трансформацию с функцией rotate(), а для двух других translateY(). Кроме того, необходимо для двух элементов изменить точку начала преобразования.
    • Для того, чтобы запустить трансформацию родительского элемента, после того как закончится трансформация вложенных элементов, Вам необходимо указать для всех элементов свойство эффекта перехода - transitioncss3, при том для родительского элемента необходимо задать задержку начала эффекта перехода между двумя состояниями. Эту тему мы подробно рассматривали ранее в статье "Переходные эффекты в CSS".

Если у Вас возникают трудности при выполнении практического задания, Вы всегда можете открыть пример в отдельном окне и проинспектировать страницу, чтобы понять какой код CSS был использован.