Рубрики
FrontEnd

CSS анимация HTML без картинок

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

Для данного урока я решил сделать анимированный секундомер. При этом я все сделаю с помощью HTML и CSS, без использования картинок. CSS анимация будет сделана для секундной стрелки.

Описание блоков и их предназначение

Так как я делаю какой-то целостный объект необходимо создать для него главный блок. Блок будет иметь класс .clock. Внутри этого блока будет еще один — .border, он будет отвечать за рамку, отбрасываемую тень и фон циферблата. Внутри блока с классом .border будут блоки со следующими классами:

  • .lines — черточки между цифрами
  • .numbers — цифры 12, 3, 6, 9
  • .arrow — секундная стрелка
  • .gradient — градиент на циферблате
  • .glass — блик на «стекле»

Описание главного блока:

<div class="clock"></div>

Так это блок, относительно которого будут позиционироваться дочерние элементы, у него должно быть свойство position. Ширина и высота будут равными. Чтобы часы располагались по центру внешний отступ(margin) справа и слева равен auto.

.clock {
	position: relative;
	width: 200px;
	height: 200px;
	margin-left: auto;
	margin-right: auto;
	font-size: 24px;
	font-family: "Times New Roman", serif;
}

Затем делаем общее описание для всех вложенных блоков и их псевдо-элементов:

Указываем, что позиционирование должно быть абсолютным, отрисовка должна быть от относительного начала координат, ширина и высота 100%. Указываем свойство content, чтобы «проявить» псевдо-элементы.

.clock div, .clock div:before, .clock div:after {
	box-sizing: border-box;
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 100%;
	content: '';
	display: block;
}

Внутри основного блока делаем блок с классом .border. Это просто декоративный блок -рамка с тенью и цветом циферблата:

<div class="clock">
	<div class="border">

	</div>
</div>
.clock .border {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 100%;
	border: 8px solid #666;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 0 2px rgba(0,0,0,.3), 0 2px 8px rgba(0,0,0,.3);
}

Внутри блока с рамкой создадим блок с классом .lines с несколькими вложенными друг в друга блоками:

<div class="clock">
	<div class="border">
		<div class="lines">
			<div>
				<div>
					<div>
						<div>
							<div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</div>

Сам блок с классом .lines должен быть чуть меньше циферблата, так как внутри него будут располагаться черточки, которые должны отстоять от рамки на какое-то расстояние.

.clock .border .lines {
	width: 90%;
	height: 90%;
	left: 5%;
	top: 5%;
}

Так как черточки должны располагаться с равным отступом друг от друга, удобно будет сделать блоки вложенные друг в друга и каждый из них повернуть на 15 градусов, тогда поворот будет происходить относительно родительского блока. Это означает, что первый блок, родителем которого является блок с классом .lines, будет повернут на 15 градусов относительно вертикали, вложенный в него будет повернут уже на 30, так как он вращается относительно того, который уже повернут на 15 градусов. И так далее.

.clock .border .lines div {
	-moz-transform: rotate(15deg); /* Для Firefox */
	-ms-transform: rotate(15deg); /* Для IE */
	-webkit-transform: rotate(15deg); /* Для Safari, Chrome, iOS */
	-o-transform: rotate(15deg); /* Для Opera */
	transform: rotate(15deg);	
}

Черточки будем рисовать с помощью псевдо-элементов befor и after. Для этого будем создавать псевдо-элементы толщиной 2 пикселя, и длинной 100%, за тем расположим их четко по центру блока и после этого повернем after на 90 градусов. В итоге получится перекрестие. Так как блоков несколько и у каждого будет свое перекрестие, мы получим «звездочку» с лучами через каждые 15 градусов с пробелами в тех местах, где будут цифры 12, 3, 6 и 9.

/* Позиционирование :before и :after ровно по центру */
.clock .border .lines div:before, .clock .border .lines div:after {
	height: 2px;
	background: #444;
	top: 50%;
	margin-top: -1px;
}
/* Поворот каждого :after на 90 градусов */
.clock .border .lines div:after {
	-moz-transform: rotate(90deg); /* Для Firefox */
	-ms-transform: rotate(90deg); /* Для IE */
	-webkit-transform: rotate(90deg); /* Для Safari, Chrome, iOS */
	-o-transform: rotate(90deg); /* Для Opera */
	transform: rotate(90deg);
}

Добавляем блок с цифрами. Сам по себе он выглядит так:

<div class="numbers">
	<div>
	</div>
</div>

Цифры будем выводить в псевдо-элементах блока с классом .numbers и вложенного в него div’а. Для этого поместим 12 в befor блока с классом .number, а 6 в after этого же блока. Затем сделаем ширину блоков 1em, расположим текст по центру, before будет расположен наверху, а after надо прижать к низу.

.clock .border .numbers:before, .clock .border .numbers:after, .clock .border .numbers div:before, .clock .border .numbers div:after {
	line-height: 1;
	width: 1em;
	height: 1em;
	left: 50%;
	z-index: 99;
	margin-left: -.5em;
	text-align: center;
}
.clock .border .numbers:after, .clock .border .numbers div:after {
	top: auto;
	bottom: 0;
}
.clock .border .numbers:before {content: '12';}
.clock .border .numbers:after {content: '6';}

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

.clock .border .numbers div {
	-moz-transform: rotate(90deg); /* Для Firefox */
	-ms-transform: rotate(90deg); /* Для IE */
	-webkit-transform: rotate(90deg); /* Для Safari, Chrome, iOS */
	-o-transform: rotate(90deg); /* Для Opera */
	transform: rotate(90deg);
}

.clock .border .numbers div:before, .clock .border .numbers div:after {
	-moz-transform: rotate(-90deg); /* Для Firefox */
	-ms-transform: rotate(-90deg); /* Для IE */
	-webkit-transform: rotate(-90deg); /* Для Safari, Chrome, iOS */
	-o-transform: rotate(-90deg); /* Для Opera */
	transform: rotate(-90deg);
}
.clock .border .numbers div:before {content: '3';}
.clock .border .numbers div:after {content: '9';}

Рисуем стрелку

Она рисуется так же как и черточки, только нам надо ее рисовать не на 100% высоты, а на 50. Еще добавим декоративный элемент к стрелке — кружок у ее основания — в середине циферблата, для этого соответствующими стилями будет наделен псевдо-блок after.

.clock .border .arrow {
	width: 98%;
	height: 98%;
	left: 1%;
	top: 1%;
	z-index: 99;
	/*
	*/
	-webkit-animation: seconds  60s infinite steps(60);
	animation: seconds  60s infinite steps(60);
}
.clock .border .arrow:before {
	width: 2px;
	height: 50%;
	left: 50%;
	margin-left: -1px;
	background: black;
}
.clock .border .arrow:after {
	width: 12px;
	height: 12px;
	left: 50%;
	top: 50%;
	margin-left: -6px;
	margin-top: -6px;
	background: #fff;
	border: 2px solid #000;
	border-radius: 50%;
}

После всего этого добавим декоративных элементов — градиент от белого к черному с высокой степенью прозрачности и закругленный блик на «стекле», так же с прозрачностью.

CSS анимация

После всего этого осталось все, что осталось сделать — CSS анимация. Анимировать будем стрелку. Начальное положение стрелки — она указывает на 12. Конечное положение — она так же указывает на 12, после того, как опишет круг — повернется 360 градусов.

Для анимации нам понадобится сделать всего два кадра:

  1. Положение при 0-е градусов;
  2. Положение при 360-и градусах.

При настройке анимации мы указываем ее длительность — 60 секунд и указываем, что css анимация должна быть пошаговая и количество шагов равно 60-ти — steps(60).

.clock .border .arrow {
	width: 98%;
	height: 98%;
	left: 1%;
	top: 1%;
	z-index: 99;
	-webkit-animation: seconds  60s infinite steps(60);
	animation: seconds  60s infinite steps(60);
}
.clock .border .arrow:before {
	width: 2px;
	height: 50%;
	left: 50%;
	margin-left: -1px;
	background: black;
}
.clock .border .arrow:after {
	width: 12px;
	height: 12px;
	left: 50%;
	top: 50%;
	margin-left: -6px;
	margin-top: -6px;
	background: #fff;
	border: 2px solid #000;
	border-radius: 50%;
}
@keyframes seconds {
	0% {
		-moz-transform: rotate(0deg); /* Для Firefox */
		-ms-transform: rotate(0deg); /* Для IE */
		-webkit-transform: rotate(0deg); /* Для Safari, Chrome, iOS */
		-o-transform: rotate(0deg); /* Для Opera */
		transform: rotate(0deg);
	}
	100% {
		-moz-transform: rotate(360deg); /* Для Firefox */
		-ms-transform: rotate(360deg); /* Для IE */
		-webkit-transform: rotate(360deg); /* Для Safari, Chrome, iOS */
		-o-transform: rotate(360deg); /* Для Opera */
		transform: rotate(360deg);
	}
}

Если вы хотите, чтобы стрелка двигалась плавно, а не прерывно, то вместо steps(60) необходимо написать linear.

Результат: