Nowadays, it is hard to get the first job without impressing somebody with your portfolio. Everybody is creating weather apps, but does everybody has custom CSS-based images in it? 😎 let’s create unique images to boost your portfolio!
There are multiple shapes that we can create in CSS, so why not create custom CSS images instead of stock photos? It will cut some unnecessary requests and speed up your website; moreover, it allows us to bring some life to it.
I don’t want to create here entire app, but only images that you can use to build one. It may look like you put much more effort to tweak it, but you didn’t. 😉
let’s start with a simple cloud. This cloud is made with one rectangle and two circles. You can use three div's, but I prefer to minimalize HTML as much as I can. that’s why I use one div for rectangle and two pseudoelements to create circles.
This is really easy.
<div class="cloud_1_init"></div>
.cloud_1_init{
top: 20px;
background: #fff;
border-radius: 100px;
box-shadow: 0 8px 5px rgba(0,0,0, 0.1);
height: 80px;
position: relative;
width: 200px;
}
.cloud_1_init:after,
.cloud_1_init:before {
content: '';
position: absolute;
border-radius: 100px;
}
.cloud_1_init:after {
top: 0px;
left: 30px;
height: 60px;
width: 60px;
background: green;
}
.cloud_1_init:before {
top: 0px;
right: 30px;
width: 100px;
height: 100px;
color: orange;
}
Now, we need to change the background of our circles and move them closer to the rectangle.
<div class="cloud_1"></div>
.cloud_1 {
top: 20px;
background: #fff;
border-radius: 100px;
box-shadow: 0 8px 5px rgba(0,0,0, 0.1);
height: 80px;
position: relative;
width: 200px;
}
.cloud_1:after,
.cloud_1:before {
content: '';
position: absolute;
background: #fff;
border-radius: 100px;
}
.cloud_1:after {
top: -30px;
left: 30px;
height: 60px;
width: 60px;
}
.cloud_1:before {
top: -56px;
right: 30px;
width: 100px;
height: 100px;
}
Voilà! First cloud created!
This cloud is more unique and is taken from my book landing page Frontend Unicorn. It is created with one rectangle and 3 squares. One div, two pseudoelements and one span.
<div class="FU_cloud">
<span></span>
</div>
.FU_cloud{
top: 60px;
background: #fff;
filter: drop-shadow(0px 5px 10px rgba(0,0,0,0.2));
height: 80px;
width: 200px;
position: relative;
}
.FU_cloud:after,
.FU_cloud:before {
content: '';
position: absolute;
background: #fff;
width: 80px;
height: 80px;
transform: rotate(45deg);
top:-17px;
}
.FU_cloud:before {
background: green;
left: -110px;
}
.FU_cloud:after {
background: orange;
right: -110px;
}
.FU_cloud span {
width: 120px;
height: 120px;
transform: rotate(45deg);
background: purple;
top: -155px;
margin: 0 auto;
display: block;
z-index: 1;
position: relative;
}
The same situation as in the first cloud. We need to slide the elements together and change the background to white.
<div class="FU_cloud">
<span></span>
</div>
.FU_cloud{
top: 30px;
background: #fff;
filter: drop-shadow(0px 5px 10px rgba(0,0,0,0.2));
height: 80px;
width: 200px;
position: relative;
}
.FU_cloud:after,
.FU_cloud:before {
content: '';
position: absolute;
background: #fff;
width: 80px;
height: 80px;
transform: rotate(45deg);
top:-17px;
}
.FU_cloud:before {
left: -40px;
}
.FU_cloud:after {
right: -40px;
}
.FU_cloud span {
width: 120px;
height: 120px;
transform: rotate(45deg);
top: -64px;
margin: 0 auto;
display: block;
background: #fff;
z-index: 1;
position: relative;
}
let’s get our hands dirty. We will create two images - a basic sunny cloud and a stormy and evil one. But don’t worry, it’s simple!
All images are based on this article.
Firstly, we need to create a few components:
Our base clour component is created similar to the first one.
<div class="cloudBase">
<div></div>
</div>
.cloudBase {
top: 30px;
background: #fff;
filter: drop-shadow(0px 5px 10px rgba(175, 215, 243, 0.6));
height: 120px;
width: 230px;
position: relative;
border-radius: 100px;
}
.cloudBase div {
background: #fff;
height: 120px;
width: 120px;
position: relative;
top: -60px;
margin: 0 auto;
border-radius: 100%;
}
Cloud Shadow
To create shadow, we need to duplicate our cloud with additional blur, blue colour and scale it down.
<div class="cloudWrap">
<div class="cloudBase">
<div></div>
</div>
<div class="cloudBaseShadow">
<div></div>
</div>
</div>
.cloudWrap {
position: relative;
z-index: 1;
}
.cloudBase {
top: 30px;
background: #fff;
filter: drop-shadow(0px 5px 10px rgba(175, 215, 243, 0.6));
height: 120px;
width: 230px;
position: relative;
border-radius: 100px;
}
.cloudBase div {
background: #fff;
height: 120px;
width: 120px;
position: relative;
top: -60px;
margin: 0 auto;
border-radius: 100%;
}
.cloudBaseShadow {
position: absolute;
top: 65px;
left:0;
right:0;
background: #69C1F8;
height: 120px;
width: 230px;
border-radius: 100px;
filter: blur(15px);
transform: scale(0.8);
opacity: 0.4;
z-index: 2;
}
.cloudBaseShadow div {
background: #69C1F8;
height: 120px;
width: 120px;
position: relative;
top: -60px;
margin: 0 auto;
border-radius: 100%;
}
.cloudBaseShadow div:after,
.cloudBaseShadow div:before {
content: '';
position: absolute;
background: #fff;
height: 100px;
width: 100px;
filter: blur(16px);
border-radius: 100%;
}
.cloudBaseShadow div:after {
right: -12px;
top: -20px;
}
.cloudBaseShadow div:before {
right: -92px;
top: 33px;
}
Step by step:
- duplicated cloud with blue colour
- add blur
- scale it down - transform: scale(0.8)
- add pseudoelements - two circles to mask our shadow
This is pretty simple. Circle with background:linear-gradient()
, shadow and pseudoelement background to lighten our sun.
.sun {
width:120px;
height: 120px;
border-radius: 50%;
background: linear-gradient(30deg, #ffb347, #fbeb36);
position: relative;
box-shadow: 0px -6px 36px 0px #fbeb36, 0px 0px 6px 0px #ffb347;
}
.sun:after {
content: '';
position: absolute;
top:-3px;
bottom:-3px;
left:-3px;
right:-3px;
border-radius: 50%;
filter: blur(10px);
background: linear-gradient(30deg,rgb(251 235 54 / 30%) 20%,rgb(255 255 255 / 49%));
z-index: 1;
}
Now we have to combine sun, cloud and additional sun flashes.
<div class="cloudWrap">
<div class="cloudBase">
<div></div>
</div>
<div class="cloudBaseShadow">
<div></div>
</div>
<div class="sun"></div>
<div class="flash"></div>
</div>
.cloudWrap {
position: relative;
z-index: 1;
}
.cloudBase {
top: 30px;
background: #fff;
filter: drop-shadow(0px 5px 10px rgba(175, 215, 243, 0.6));
height: 120px;
width: 230px;
position: relative;
border-radius: 100px;
}
.cloudBase div {
background: #fff;
height: 120px;
width: 120px;
position: relative;
top: -60px;
margin: 0 auto;
border-radius: 100%;
}
.cloudBaseShadow {
position: absolute;
top: 65px;
left:0;
right:0;
background: #69C1F8;
height: 120px;
width: 230px;
border-radius: 100px;
filter: blur(15px);
transform: scale(0.8);
opacity: 0.4;
z-index: 2;
}
.cloudBaseShadow div {
background: #69C1F8;
height: 120px;
width: 120px;
position: relative;
top: -60px;
margin: 0 auto;
border-radius: 100%;
}
.cloudBaseShadow div:after,
.cloudBaseShadow div:before {
content: '';
position: absolute;
background: #fff;
height: 100px;
width: 100px;
filter: blur(16px);
border-radius: 100%;
}
.cloudBaseShadow div:after {
right: -12px;
top: -20px;
}
.cloudBaseShadow div:before {
right: -92px;
top: 33px;
}
.sun {
position: absolute;
top: -50px;
right: -20px;
z-index: -1;
width:120px;
height: 120px;
border-radius: 50%;
background: linear-gradient(30deg, #ffb347, #fbeb36);
box-shadow: 0px -6px 36px 0px #fbeb36, 0px 0px 6px 0px #ffb347;
}
.sun:after {
content: '';
position: absolute;
top:-3px;
bottom:-3px;
left:-3px;
right:-3px;
border-radius: 50%;
filter: blur(10px);
background: linear-gradient(30deg,rgb(251 235 54 / 30%) 20%,rgb(255 255 255 / 49%));
z-index: 1;
}
.flash {
position: absolute;
bottom: -40px;
left: -20px;
width: 60px;
height: 60px;
background: rgba(255,255,255,0.4);
box-shadow: 0px 0px 6px 3px rgba(255,255,255,0.4);
border-radius: 50%;
z-index: 2;
}
.flash:before {
content: '';
width: 10px;
height: 10px;
background: #fff;
box-shadow: 0px 0px 6px 3px rgba(255,255,255,0.4);
border-radius: 50%;
filter: blur(0px);
position: absolute;
top: 60px;
left: -10px;
}
And that’s it!
Here you can play with sunny cloud.
As you can see, creating this image taken us a few minutes of work. Moreover, creating another image based on this one can be even faster. So let’s do this!
First of all, let’s create a lightning bolt shape. By merging two triangles, if you read one of my latest article about creating shapes in CSS - you won’t have any problem. 😎
Now use two triangles and animate it with CSS.
<div class="lightningBolt"></div>
@keyframes flash{
0%, to { opacity: 1; }
4% { opacity: 0; }
6% { opacity: .6; }
8% { opacity: .2; }
10% { opacity: .9; }
}
@keyframes float{
0%, 100% { transform: translateY(0); }
50% { transform: translateY(5px); }
}
.lightningBolt {
position: absolute;
z-index: 3;
width: 80px;
height: 20px;
margin: 0 auto;
left: 0;
right: 0;
bottom: -40px;
animation: flash 3s infinite, float 3s ease-in-out infinite;
}
.lightningBolt:before,
.lightningBolt:after {
content: '';
position: absolute;
}
.lightningBolt:before {
width: 0;
height: 0;
left: -4px;
top: 5px;
border-style: solid;
border-width: 0px 13px 24px 70px;
border-color: transparent transparent #fbeb36 transparent;
transform: rotate(-60deg);
}
.lightningBolt:after {
width: 0;
height: 0;
left: 4px;
top: -40px;
border-style: solid;
border-width: 0px 13px 24px 70px;
border-color: transparent transparent #fbeb36 transparent;
transform: rotate(-60deg) scaleY(-1) scaleX(-1);
}
Okay! let’s finish our cloud combining our basic cloud (with grey background), lightning and some CSS for wind and water drop.
<div class="cloudWrap">
<div class="cloudBase">
<div></div>
</div>
<div class="cloudBaseShadow">
<div></div>
</div>
<div class="wind"></div>
<div class="lightningBolt"></div>
</div>
.cloudWrap {
position: relative;
z-index: 1;
}
.cloudBase {
top: 30px;
background: #fff;
filter: drop-shadow(0px 5px 10px rgba(175, 215, 243, 0.6));
height: 120px;
width: 230px;
position: relative;
border-radius: 100px;
}
.cloudBase div {
background: #fff;
height: 120px;
width: 120px;
position: relative;
top: -60px;
margin: 0 auto;
border-radius: 100%;
}
.cloudBaseShadow {
position: absolute;
top: 65px;
left:0;
right:0;
background: #5B7186;
height: 120px;
width: 230px;
border-radius: 100px;
filter: blur(15px);
transform: scale(0.8);
opacity: 0.4;
z-index: 2;
}
.cloudBaseShadow div {
background: #5B7186;
height: 120px;
width: 120px;
position: relative;
top: -60px;
margin: 0 auto;
border-radius: 100%;
}
.cloudBaseShadow div:after,
.cloudBaseShadow div:before {
content: '';
position: absolute;
background: #fff;
height: 100px;
width: 100px;
filter: blur(16px);
border-radius: 100%;
}
.cloudBaseShadow div:after {
right: -12px;
top: -20px;
}
.cloudBaseShadow div:before {
right: -92px;
top: 33px;
}
@keyframes flash{
0%, to { opacity: 1; }
4% { opacity: 0; }
6% { opacity: .6; }
8% { opacity: .2; }
10% { opacity: .9; }
}
@keyframes float{
0%, 100% { transform: translateY(0); }
50% { transform: translateY(5px); }
}
.lightningBolt {
position: absolute;
z-index: 3;
width: 80px;
height: 20px;
margin: 0 auto;
left: 0;
right: 0;
bottom: -40px;
animation: flash 3s infinite, float 3s ease-in-out infinite;
}
.lightningBolt:before,
.lightningBolt:after {
content: '';
position: absolute;
}
.lightningBolt:before {
width: 0;
height: 0;
left: -4px;
top: 5px;
border-style: solid;
border-width: 0px 13px 24px 70px;
border-color: transparent transparent #fbeb36 transparent;
transform: rotate(-60deg);
}
.lightningBolt:after {
width: 0;
height: 0;
left: 4px;
top: -40px;
border-style: solid;
border-width: 0px 13px 24px 70px;
border-color: transparent transparent #fbeb36 transparent;
transform: rotate(-60deg) scaleY(-1) scaleX(-1);
}
.wind {
position: absolute;
top: 20px;
left: -10px;
width: 90px;
height: 20px;
background: linear-gradient(-90deg,rgb(91 113 134 / 0.4),transparent);
z-index: -1;
}
.wind:before {
content: '';
width: 60px;
height: 20px;
background: linear-gradient(90deg,transparent,rgb(91 113 134 / 0.4));
position: absolute;
top: 60px;
right: -190px;
}
.wind:after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 50%;
border-radius: 100%;
width: 8px;
height: 8px;
z-index: 1;
filter: blur(2px);
z-index: 1;
box-shadow:
50px -30px 2px rgb(91 113 134 / 0.4),
-20px 90px 0px rgb(91 113 134 / 0.4),
240px 10px 2px rgb(91 113 134 / 0.4);
animation: float 3s ease-in-out infinite;
}
Here you can play with storm cloud.
Now you know how to create awesome weather images, so create your own! Snow? Blizzard? Fog maybe? Share you codepen on Twitter with #frontendunicorns hashtag!
Thanks for reading! 🦄