Draw an animated scene using css

  • Tutorial
Let's take a break from the layout of any user interfaces and just draw on CSS. We will draw such a scene:



Look at jsfiddle.

In the article I will try to describe the step-by-step creation of this scene.

The described code works on webkit browsers (Chrome, Safari, Opera latest versions). To work in other browsers, instead of the -webkit prefixes, you need to use the corresponding prefixes (-moz, -ms, -o).

Create a scene and sky

		.scene {
			position: relative;
			width: 800px;
			height: 600px;
			margin: 50px auto;
			overflow: hidden;
			background-image: -webkit-linear-gradient(top, #011428, #032a54);
		}
	

using linear-gradient (top, # 011428, # 032a54) we filled the scene with a gradient from a darker (# 011428) to a lighter (# 032a54) shade of blue starting from the top (top)



We draw snowdrifts. We take as the basis the ellipses that can be created from divs by setting them border-radius: 50%

		.ground {
			position: absolute;
			width: 770px;
			height: 200px;
			border-radius: 50%;
			background-color: #99a;
		}
	




Position 4 ellipses at the bottom of the scene

.ground {
	width: 400px;
	background-color: #f5f5f5;
	border-radius: 50%;
	width: 770px;
	height: 200px;
	position: absolute;
	bottom: 0;
	margin-bottom: -80px;
	right: 140px;
	background-color: #99a;
}
.ground.back-1 {left: 180px;}
.ground.front {margin-bottom: -124px;left: -27px;}
.ground.front-2 {margin-bottom: -109px;right: -508px;}
	




Making snowdrifts voluminous by adding an inner shadow to the .ground class
	box-shadow: 0 0 100px #457eb2 inset;




Draw the moon and stars

.moon {
	position: absolute;
	width: 60px;
	height: 60px;
	top: 100px;
	left: 100px;
	background-color: #ffffaa;
	border-radius: 50%;
}
.stars {
	position: absolute;
	width: 100%;
	height: 100%;
}
.star {
	position: absolute;
	border-radius: 50%;
	width: 1px;
	height: 1px;
	background-color: #ffffff;
}
.star:nth-child(1) {top: 100px;left: 685px;}
.star:nth-child(2) {top: 37px;left: 537px;}
.star:nth-child(3) {top: 150px;left: 350px;}
.star:nth-child(4) {top: 50px;left: 320px;}
.star:nth-child(5) {top: 30px;left: 755px;}
.star:nth-child(6) {top: 70px;left: 483px;}
.star:nth-child(7) {top: 18px;left: 80px;}




Add a glow effect to the moon
	box-shadow: 0 0 40px #ffffaa;
        

And the stars too:
box-shadow: 0 0 10px 2px white;





Now we proceed to the house. The house will consist of a roof, wall, window and chimney. We describe all this with layout:

		.house {
			position: absolute;
			width: 300px;
			height: 365px;
			bottom: 50px;
			right: 110px;
		}


We draw a wall. The effect of a log house can be obtained using a repeating gradient:
		.house .wall {
			width: 100%;
			height: 200px;
			position: absolute;
			bottom: 0;
			background-color: #180c00;
			background: repeating-linear-gradient(to bottom, #573808 0%,#3a1e12 15%);
		}
	




We make a window. It will be a div with a yellow background and a brown border

		.house .window {
			position: absolute;
			height: 70px;
			width: 65px;
			background-color: #cccc00;
			border: 5px solid #3a1e12;
			bottom: 53px;
			left: 110px;
			box-shadow: 0 0 5px black;
		}
	




Add a frame and a glow effect to it using box-shadow


		.house .window .frame:nth-child(1) {
			position: absolute;
			height: 100%;
			left: 50%;
			margin-left: -3px;
			width: 7px;
			background-color: #3a1e12;
		}
		.house .window .frame:nth-child(2) {
			position: absolute;
			width: 100%;
			top: 30%;
			height: 7px;
			background-color: #3a1e12;
		}
		.house .window .light {
			width: 100%;
			height: 100%;
			background-color: #ffff00;
			opacity: 0.5;
			box-shadow: 0 0 100px yellow;
		}
	




Create a roof. This will be a div border which will serve as a roof.
	.house .roof .roof-wall {
		position: absolute;
		width: 280px;
		height: 280px;
		background-color: #573808;
		left: 25px;
		top:60px;
		border: 5px solid #3a1e12;
		box-shadow: 0 0 30px black inset;
	}
	




To create the effect of the lining, we again use the repeating gradient, which we rotate by 45 degrees
		background: repeating-linear-gradient(45deg, #573808 0%,#573808 5%,#3a1e12 5%,#3a1e12 5%,#3a1e12 5%,#573808 5%,#3a1e12 6%)
	




The roof is ready, we put it on the house by turning it 45 degrees using transform: rotate (45deg) and cutting off half using overflow: hidden at the container
		.house .roof {
			width: 340px;
			height: 170px;
			right: -20px;
			position: absolute;
			overflow: hidden;
		}
		.house .roof .roof-wall {
			position: absolute;
			width: 280px;
			height: 280px;
			background-color: #573808;
			-webkit-transform: rotate(45deg);
			left: 25px;
			top:60px;
			border: 5px solid #3a1e12;
			box-shadow: 0 0 30px black inset;
			background: repeating-linear-gradient(45deg, #573808 0%,#573808 5%,#3a1e12 5%,#3a1e12 5%,#3a1e12 5%,#573808 5%,#3a1e12 6%);
		}
	




We attach a pipe drawn with a gradient
		.house .chimney {
			position: absolute;
			height: 80px;
			width: 30px;
			top: 58px;
			left: 20px;
			background: linear-gradient(to right, rgba(42,41,45,1) 0%,rgba(80,84,91,1) 36%,rgba(22,27,33,1) 100%);
		}
	


And we add roughness to the logs, laying on them a couple of repeating brown gradients turning into transparency


		.house .wall .crack {
			position: absolute;
			width: 100%;
			height: 100%;
			opacity: 0.5;
			background: repeating-linear-gradient(3deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 2%, rgba(0,0,0,0) 2%,#3a1e12 2%,#3a1e12 2%,#573808 2%,#3a1e12 3%);
		}
		.house .wall .crack:nth-child(2) {
			opacity: 0.3;
			background: repeating-linear-gradient(-4deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 2%, rgba(0,0,0,0) 2%,#3a1e12 2%,#3a1e12 2%,#573808 2%,#3a1e12 3%);
		}
	


Well, we've got a pretty nice picture.



It's time to revive our static picture with animations. For starters, make smoke from the chimney.
For now, let's draw one cloud of smoke. It will be a translucent oval with a light box-shadow around and a radial gradient.

		.smoke-area .smoke {
			position: absolute;
			width: 30px;
			height: 30px;
			border-radius: 50%;
			box-shadow: 0 0 20px lightgray;
			background: radial-gradient(ellipse at center, rgba(206,220,231,1) 33%,rgba(89,106,114,0) 100%);
			top: 120px;
			left: 20px;
		}
	




Using key frames, we describe the trajectory of the movement and the transformation of this cloud. It will gradually increase and become transparent.

		@-webkit-keyframes smoke-move {
			0% {top: 120px; left: 20px}
			20% {top: 107px; left: 25px}
			30% {top: 95px; left: 35px; opacity: 0.9}
			40% {top: 80px; left: 40px; }
			50% {top: 65px; left: 50px; }
			60% {top: 50px; left: 62px; }
			70% {top: 35px; left: 75px; }
			80% {top: 25px; left: 90px; }
			90% {top: 15px; left: 117px; }
			100% {top: 7px; left: 127px; opacity: 0; width: 90px; height: 60px}
		}
	


Now we will assign the animation just described to our cloud by adding the property .smoke to the class
	-webkit-animation: smoke-move 2.3s linear infinite
	




Well, we already have a working chimney, but in its full form it should continuously let out a lot of puffs of smoke, so we’ll add a few more to the layout.


Now there are several clouds of smoke, but so far there is little use for it, since they all move simultaneously along one trajectory and all this looks like one cloud. Describing a new animation for each cloud is too clumsy and tedious. Here I want some kind of randomness in their movement, for example, apply something like Math.random () using javascript, but since the goal is to make a scene using only css, you will have to get out of girlfriend. In our case, you can simply reuse the smoke-move animation already described for each element , but with different playback times:
		.smoke-area .smoke:nth-child(2) {
			-webkit-animation: smoke-move 2.5s linear infinite
		}
		.smoke-area .smoke:nth-child(3) {
			-webkit-animation: smoke-move 2.7s linear infinite
		}
		.smoke-area .smoke:nth-child(4) {
			-webkit-animation: smoke-move 2.2s linear infinite
		}
		.smoke-area .smoke:nth-child(5) {
			-webkit-animation: smoke-move 2.1s linear infinite
		}
		.smoke-area .smoke:nth-child(6) {
			-webkit-animation: smoke-move 2s linear infinite
		}
		.smoke-area .smoke:nth-child(7) {
			-webkit-animation: smoke-move 2.9s linear infinite
		}
	

Теперь клубы дыма движутся по той-же траектории но за различное время что дает видимость их случайного движения:



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


И в качестве изюминки добавим несколько падающих звездочек. Как и раньше начнем с одной, добавим ее как .meteor в div.meteors

	.meteors {
		position: absolute;
		width: 100%;
		height: 100%;
	}
	


Описание css начнем с хвоста нашего метеора. Это будет белая линия переходящая в прозрачность.
	.meteor {
		position: absolute;
		top: 50px;
		left: 280px;
		width: 300px;
		height: 1px;
		-webkit-transform: rotate(-45deg);
		background-image: -webkit-linear-gradient(left, white, rgba(255,255,255,0));
	}
	



Теперь нарисуем звездочку на конце этого хвоста:
		.meteor:before {
			content: ' ';
			position: absolute;
			width: 4px;
			height: 5px;
			background-color: white;
			border-radius: 50%;
			box-shadow: 0 0 14px 4px white;
			margin-top: -2px;
		}
	


We will describe the animation for the meteor, we will move it by changing the indentation creating the effect of flying at an angle of 45 degrees. The meteor will fall and gradually disappear.
	@-webkit-keyframes meteor {
		0% {margin-top: -300px; margin-right: -300px; opacity: 1}
		8% {opacity: 0}
		10% {margin-top: 300px; margin-left: -600px; opacity: 0}
		100% {opacity: 0}
	}
	

We launch a meteor in flight:
		.meteor {top: 100px;left: 480px;-webkit-animation: meteor 10s linear infinite;}
	


Need more meteors!

	.meteor:nth-child(1) {top: 100px;left: 480px;-webkit-animation: meteor 10s linear infinite;}
	.meteor:nth-child(2) {top: 200px;left: 280px;-webkit-animation: meteor 10s linear infinite;}
	.meteor:nth-child(3) {top: 250px;left: 790px;-webkit-animation: meteor 9s linear infinite;}



Well, the scene is ready!

Also popular now: