CSS3 Animated Flask with Bubbles

In our new tutorial we will create animated flask with bubbles. Not so long ago I was tasked to create an animation in the form of bubbles emitting from the flask. It was the original step of an advertising agency. Very often when you want to create the animation, we think about using javascript, but sometimes you can do it using the capabilities of CSS3. We can draw basic elements like rectangles, circles and even triangles using pseudo-classes CSS3. Sounds interesting? Then let’s get started!


Examine the task

The flask consists of many diverse shapes, but CSS capabilities are limited and do not allow us to create complex elements. How do we proceed? We implement them using triangles and rectangles. To do this, we’ll use the following CSS properties:

  • pseudo-elements :before and :after
  • position, top, right, bottom, left and z-index
  • border, width and height

Base of the flask

The base has a triangular shape, so we’ll do it using triangle. For this I will create the following markup:

1 <div class="flask">
2   <div class="flask_bottom">
3     <div class="big_triangle">
4
5     </div>
6   </div>
7 </div>

Main element with class flask is located in the base class flask_bottom. We have added a template for the future triangle.
Styles for the markup:

01 body {
02   background-color#292548;
03 }
04
05 .flask {
06   height405px;
07   width368px;
08   positionabsolute;
09   bottom0;
10 }
11
12 .flask_bottom {
13   bottom0;
14   positionabsolute;
15 }
16
17 .big_triangle {
18   overflowhidden;
19   positionrelative;
20   width368px;
21   height250px;
22   background-color#fff;
23 }

The base is fixed to the bottom of the flask, using position: absolute and bottom: 0. Set the width of 368 pixels and height of 250 pixels. As a result we have a rectangle.CSS3 Animated Flask with Bubbles

Now the fun begins! How do we make a triangle?! For this I will use pseudo-elements :before and :after. Using them, we will create right triangles and arrange them on top of the white rectangle from the left and the right edge respectively. Thus, hiding part of its area.

CSS3 Animated Flask with Bubbles

But first we need to make right-angled triangles. In order to make it, I will add the following CSS code:

01 .big_triangle:before, .big_triangle:after {
02   content"";
03   displayblock;
04   width0;
05   height0;
06   border-top250px solid #292548;
07   positionabsolute;
08   top0;
09   z-index100;
10 }
11
12 .big_triangle:before {
13   border-right152px solid transparent;
14   left0;
15 }
16
17 .big_triangle:after {
18   border-left152px solid transparent;
19   right0;
20 }

The basic technique for creating CSS triangles – use the border property. But first you need to set the width and height of elements is equal to 0, for correct calculation of the size of the triangles. Next to them are set the property border-top equal to 250 pixels and color #292548 (background color). Next to the left triangle indicate a border-left with a value of the 152 pixels. The same thing will do for the right triangle, only instead of border-left we set border-right. Then have them on the edges of the rectangle using the left and right properties. And we make a triangle!CSS3 Animated Flask with Bubbles

Elements of the base

Now we will start implementing the elements of the base. To do this, add the following markup:

01 <div class="flask">
02   <div class="flask_bottom">
03     <div class="big_triangle">
04       <div class="flask_bottom_one"></div>
05       <div class="flask_bottom_two"></div>
06       <div class="flask_bottom_five"></div>
07       <div class="flask_bottom_six"></div>
08       <div class="flask_bottom_seven"></div>
09       <div class="flask_bottom_eight"></div>
10     </div>
11   </div>
12 </div>

Then we use the following CSS styles:

01 .flask_bottom_one {
02   width0;
03   height0;
04   border-bottom55px solid #3a2481;
05   border-left32px solid transparent;
06   border-right42px solid transparent;
07   positionabsolute;
08   bottom0;
09   z-index4;
10 }
11
12 .flask_bottom_two {
13   border-bottom165px solid #4266c0;
14   border-left93px solid transparent;
15   border-right200px solid transparent;
16   width0;
17   height0;
18   positionabsolute;
19   left0;
20   bottom0;
21   z-index2;
22 }
23
24 .flask_bottom_five {
25   positionabsolute;
26   background-color#4248c0;
27   width100%;
28   height75px;
29   positionabsolute;
30   z-index3;
31   left50px;
32   bottom18px;
33   -webkit-transform: rotate(24deg);
34   transform: rotate(24deg);
35   -webkit-transform-origin: left top;
36   transform-origin: left top;
37 }
38
39 .flask_bottom_six {
40   positionabsolute;
41   background-color#37acdd;
42   width100%;
43   height170px;
44   positionabsolute;
45   z-index1;
46   right0;
47   bottom0;
48 }
49
50 .flask_bottom_seven {
51   positionabsolute;
52   background-color#1493c8;
53   width100%;
54   height218px;
55   positionabsolute;
56   z-index3;
57   right-95px;
58   bottom24px;
59   -webkit-transform: rotate(24deg);
60   transform: rotate(24deg);
61   -webkit-transform-origin: right top;
62   transform-origin: right top;
63 }
64
65 .flask_bottom_eight {
66   positionabsolute;
67   background-color#5c30ae;
68   width100%;
69   height50px;
70   positionabsolute;
71   z-index3;
72   right-95px;
73   bottom218px;
74   -webkit-transform: rotate(-12deg);
75   transform: rotate(-12deg);
76   -webkit-transform-origin: left top;
77   transform-origin: left top;
78 }

An important step in creating of elements is preserving the triangular form of the base. When positioning the internal elements, they will be outside the triangle. To avoid this, I added the overflow property with hidden value to the class big_triangle. When the browser reads this property, it will hide everything that goes outside of the element with class big_triangle.

Next we need to create 6 additional elements and using the transform property (with value rotate) and transform-origin, positioning them as we need. In our case, the transformation is needed to rotate the elements, and transform-origin to specify the point around which will rotate the elements. Also,using absolute positioning, we have elements in their places. As a result, we get:CSS3 Animated Flask with Bubbles

Top and its elements

To create the top (neck) we need to create a rectangle with a size of 62×152 pixels and place inside all 4 elements. Have a look at the following markup:

01 <div class="flask">
02   <div class="flask_throat">
03     <div class="flask_throat_one"></div>
04     <div class="flask_throat_two"></div>
05     <div class="flask_throat_three"></div>
06     <div class="flask_throat_four"></div>
07   </div>
08   <div class="flask_bottom">
09     <div class="big_triangle">
10       <div class="flask_bottom_one"></div>
11       <div class="flask_bottom_two"></div>
12       <div class="flask_bottom_five"></div>
13       <div class="flask_bottom_six"></div>
14       <div class="flask_bottom_seven"></div>
15       <div class="flask_bottom_eight"></div>
16     </div>
17   </div>
18 </div>

And styles for this markup:

01 .flask_throat {
02   overflowhidden;
03   height155px;
04   width64px;
05   positionabsolute;
06   left152px;
07   top0;
08 }
09
10 .flask_throat_one {
11   positionabsolute;
12   -webkit-transform: rotate(24deg);
13   transform: rotate(24deg);
14   -webkit-transform-origin: right top;
15   transform-origin: right top;
16   background-color#5c30ae;
17   width150px;
18   height50px;
19   positionabsolute;
20   z-index3;
21   right-26px;
22   top110px;
23 }
24
25 .flask_throat_two {
26   positionabsolute;
27   -webkit-transform: rotate(20deg);
28   transform: rotate(20deg);
29   -webkit-transform-origin: right top;
30   transform-origin: right top;
31   background-color#37acdd;
32   width150px;
33   height60px;
34   positionabsolute;
35   z-index3;
36   right-35px;
37   top35px;
38 }
39
40 .flask_throat_three {
41   positionabsolute;
42   background-color#5c30ae;
43   width100%;
44   height50px;
45   positionabsolute;
46   z-index3;
47   right0;
48   bottom0;
49 }
50
51 .flask_throat_four {
52   positionabsolute;
53   -webkit-transform: rotate(20deg);
54   transform: rotate(20deg);
55   -webkit-transform-origin: right top;
56   transform-origin: right top;
57   background-color#6c49ac;
58   width150px;
59   height20px;
60   positionabsolute;
61   z-index3;
62   right-45px;
63   top100px;
64 }

Arrangement of elements is exactly the same as the elements of base. In result we have finished the bulb!CSS3 Animated Flask with Bubbles

Animation of the bubbles

We will load the flask and after some time the bubbles will appear. They will be of different sizes and colors. The timing of the appearance will be different.

For the realization of the bubbles, we will use modern CSS features, in particular the border-radius property. Using this property you can round the corners of an element. Now we will create 3 multi-colored bubbles of the same size, one is slightly larger, and another one with large size. Here is the markup:

01 <div class="flask">
02   <div class="circle small_circle"></div>
03   <div class="circle middle_circle"></div>
04   <div class="circle little_circle little_circle_white"></div>
05   <div class="circle little_circle little_circle_purpure"></div>
06   <div class="circle little_circle little_circle_blue"></div>
07   <div class="flask_throat">
08     <div class="flask_throat_one"></div>
09     <div class="flask_throat_two"></div>
10     <div class="flask_throat_three"></div>
11     <div class="flask_throat_four"></div>
12   </div>
13   <div class="flask_bottom">
14     <div class="big_triangle">
15       <div class="flask_bottom_one"></div>
16       <div class="flask_bottom_two"></div>
17       <div class="flask_bottom_five"></div>
18       <div class="flask_bottom_six"></div>
19       <div class="flask_bottom_seven"></div>
20       <div class="flask_bottom_eight"></div>
21     </div>
22   </div>
23 </div>

Then we add CSS styles for the bubbles:

01 .circle {
02   border-radius: 50%;
03   border1px solid #fff;
04   positionabsolute;
05   left45%;
06   top30px;
07   -webkit-animation-name: circle;
08   animation-name: circle;
09   -webkit-animation-duration: 5s;
10   animation-duration: 5s;
11   -webkit-animation-iteration-count: infinite;
12   animation-iteration-count: infinite;
13   -webkit-animation-delay: 0s;
14   animation-delay: 0s;
15 }
16
17 .little_circle {
18   width5px;
19   height5px;
20 }
21
22 .little_circle_white {
23   background-color#fff;
24   left48%;
25   -webkit-animation-duration: 2000ms;
26   animation-duration: 2000ms;
27 }
28
29 .little_circle_purpure {
30   background-color#6c49ac;
31   border1px solid #6c49ac;
32   left52%;
33   -webkit-animation-duration: 2000ms;
34   animation-duration: 2000ms;
35   -webkit-animation-delay: 100ms;
36   animation-delay: 100ms;
37 }
38
39 .little_circle_blue {
40   background-color#117fba;
41   border1px solid #117fba;
42   left45%;
43   -webkit-animation-duration: 2000ms;
44   animation-duration: 2000ms;
45   -webkit-animation-delay: 200ms;
46   animation-delay: 200ms;
47 }
48
49 .small_circle {
50   width20px;
51   height20px;
52   -webkit-animation-duration: 4200ms;
53   animation-duration: 4200ms;
54   -webkit-animation-delay: 300ms;
55   animation-delay: 300ms;
56 }
57
58 .middle_circle {
59   width45px;
60   height45px;
61 }
62
63 @-webkit-keyframes circle {
64   0% {
65     -webkit-transform: translateZ(0px) translateY(20px) scale(1);
66     transform: translateZ(0px) translateY(20px) scale(1);
67     opacity: 1;
68   }
69   85% {
70     opacity: 0;
71   }
72   100% {
73     -webkit-transform: translateZ(0px) translateY(-200px) scale(0);
74     transform: translateZ(0px) translateY(-200px) scale(0);
75     opacity: 0;
76   }
77 }
78
79 @keyframes circle {
80   0% {
81     -webkit-transform: translateZ(0px) translateY(20px) scale(1);
82     transform: translateZ(0px) translateY(20px) scale(1);
83     opacity: 1;
84   }
85   85% {
86     opacity: 0;
87   }
88   100% {
89     -webkit-transform: translateZ(0px) translateY(-200px) scale(0);
90     transform: translateZ(0px) translateY(-200px) scale(0);
91     opacity: 0;
92   }
93 }

Next step is to create animation using @keyframes. Here is the idea: when the page is loaded the bubbles are at the initial coordinates – 20 pixels on the y axis. Then the bubbles start moving along the axis Y from the start coordinate to 200px. Besides of this motion, the bubbles will move farther from us. For this we use the transform property. Also, the motion of the bubbles gradually disappear using the opacity property.

The script is created, now we need to specify it in the circle class. For this we use the property animation-name and specify the name of the script – circle. Next, for each bubble, we set the delay by using animation-delay, and thus they will appear in different period of time. The last step is to set the animation-iteration-count to infinite repetition of the scenario of the animation.

Animation of the flask

For the animation of the flask I created different scenario for each element:

001 @-webkit-keyframes animation_bg_element1 {
002   0% {
003     border-bottom-color#3a2481;
004   }
005   25% {
006     border-bottom-color#242781;
007   }
008   50% {
009     border-bottom-color#244081;
010   }
011   75% {
012     border-bottom-color#242781;
013   }
014 }
015
016 @keyframes animation_bg_element1 {
017   0% {
018     border-bottom-color#3a2481;
019   }
020   25% {
021     border-bottom-color#242781;
022   }
023   50% {
024     border-bottom-color#244081;
025   }
026   75% {
027     border-bottom-color#242781;
028   }
029 }
030
031 @-webkit-keyframes animation_bg_element2 {
032   0% {
033     border-bottom-color#4266c0;
034   }
035   25% {
036     border-bottom-color#4287c0;
037   }
038   50% {
039     border-bottom-color#42a8c0;
040   }
041   75% {
042     border-bottom-color#4287c0;
043   }
044 }
045
046 @keyframes animation_bg_element2 {
047   0% {
048     border-bottom-color#4266c0;
049   }
050   25% {
051     border-bottom-color#4287c0;
052   }
053   50% {
054     border-bottom-color#42a8c0;
055   }
056   75% {
057     border-bottom-color#4287c0;
058   }
059 }
060
061 @-webkit-keyframes animation_bg_element3 {
062   0% {
063     background-color#4248c0;
064   }
065   25% {
066     background-color#4269c0;
067   }
068   50% {
069     background-color#428ac0;
070   }
071   75% {
072     background-color#4269c0;
073   }
074 }
075
076 @keyframes animation_bg_element3 {
077   0% {
078     background-color#4248c0;
079   }
080   25% {
081     background-color#4269c0;
082   }
083   50% {
084     background-color#428ac0;
085   }
086   75% {
087     background-color#4269c0;
088   }
089 }
090
091 @-webkit-keyframes animation_bg_element4 {
092   0% {
093     background-color#37acdd;
094   }
095   25% {
096     background-color#37d8dd;
097   }
098   50% {
099     background-color#37ddb5;
100   }
101   75% {
102     background-color#37d8dd;
103   }
104 }
105
106 @keyframes animation_bg_element4 {
107   0% {
108     background-color#37acdd;
109   }
110   25% {
111     background-color#37d8dd;
112   }
113   50% {
114     background-color#37ddb5;
115   }
116   75% {
117     background-color#37d8dd;
118   }
119 }
120
121 @-webkit-keyframes animation_bg_element5 {
122   0% {
123     background-color#1493c8;
124   }
125   25% {
126     background-color#14c2c8;
127   }
128   50% {
129     background-color#14c89d;
130   }
131   75% {
132     background-color#14c2c8;
133   }
134 }
135
136 @keyframes animation_bg_element5 {
137   0% {
138     background-color#1493c8;
139   }
140   25% {
141     background-color#14c2c8;
142   }
143   50% {
144     background-color#14c89d;
145   }
146   75% {
147     background-color#14c2c8;
148   }
149 }
150
151 @-webkit-keyframes animation_bg_element6 {
152   0% {
153     background-color#5c30ae;
154   }
155   25% {
156     background-color#3a30ae;
157   }
158   50% {
159     background-color#3048ae;
160   }
161   75% {
162     background-color#3a30ae;
163   }
164 }
165
166 @keyframes animation_bg_element6 {
167   0% {
168     background-color#5c30ae;
169   }
170   25% {
171     background-color#3a30ae;
172   }
173   50% {
174     background-color#3048ae;
175   }
176   75% {
177     background-color#3a30ae;
178   }
179 }
180
181 @-webkit-keyframes animation_bg_element7 {
182   0% {
183     background-color#6c49ac;
184   }
185   25% {
186     background-color#5249ac;
187   }
188   50% {
189     background-color#495aac;
190   }
191   75% {
192     background-color#5249ac;
193   }
194 }
195
196 @keyframes animation_bg_element7 {
197   0% {
198     background-color#6c49ac;
199   }
200   25% {
201     background-color#5249ac;
202   }
203   50% {
204     background-color#495aac;
205   }
206   75% {
207     background-color#5249ac;
208   }
209 }

Now I’ll add a call to the animation in each class:

001 .flask_throat_one {
002   positionabsolute;
003   -webkit-transform: rotate(24deg);
004   transform: rotate(24deg);
005   -webkit-transform-origin: right top;
006   transform-origin: right top;
007   background-color#5c30ae;
008   width150px;
009   height50px;
010   positionabsolute;
011   z-index3;
012   right-26px;
013   top110px;
014   -webkit-animation-name: animation_bg_element6;
015   animation-name: animation_bg_element6;
016   -webkit-animation-duration: 5s;
017   animation-duration: 5s;
018   -webkit-animation-iteration-count: infinite;
019   animation-iteration-count: infinite;
020   -webkit-animation-delay: 0s;
021   animation-delay: 0s;
022 }
023
024 .flask_throat_two {
025   positionabsolute;
026   -webkit-transform: rotate(20deg);
027   transform: rotate(20deg);
028   -webkit-transform-origin: right top;
029   transform-origin: right top;
030   background-color#37acdd;
031   width150px;
032   height60px;
033   positionabsolute;
034   z-index3;
035   right-35px;
036   top35px;
037   -webkit-animation-name: animation_bg_element5;
038   animation-name: animation_bg_element5;
039   -webkit-animation-duration: 5s;
040   animation-duration: 5s;
041   -webkit-animation-iteration-count: infinite;
042   animation-iteration-count: infinite;
043   -webkit-animation-delay: 0s;
044   animation-delay: 0s;
045 }
046
047 .flask_throat_three {
048   positionabsolute;
049   background-color#5c30ae;
050   width100%;
051   height50px;
052   positionabsolute;
053   z-index3;
054   right0;
055   bottom0;
056   -webkit-animation-name: animation_bg_element6;
057   animation-name: animation_bg_element6;
058   -webkit-animation-duration: 5s;
059   animation-duration: 5s;
060   -webkit-animation-iteration-count: infinite;
061   animation-iteration-count: infinite;
062   -webkit-animation-delay: 0s;
063   animation-delay: 0s;
064 }
065
066 .flask_throat_four {
067   positionabsolute;
068   -webkit-transform: rotate(20deg);
069   transform: rotate(20deg);
070   -webkit-transform-origin: right top;
071   transform-origin: right top;
072   background-color#6c49ac;
073   width150px;
074   height20px;
075   positionabsolute;
076   z-index3;
077   right-45px;
078   top100px;
079   -webkit-animation-name: animation_bg_element7;
080   animation-name: animation_bg_element7;
081   -webkit-animation-duration: 5s;
082   animation-duration: 5s;
083   -webkit-animation-iteration-count: infinite;
084   animation-iteration-count: infinite;
085   -webkit-animation-delay: 0s;
086   animation-delay: 0s;
087 }
088
089 .flask_bottom_one {
090   width0;
091   height0;
092   border-bottom55px solid #3a2481;
093   border-left32px solid transparent;
094   border-right42px solid transparent;
095   positionabsolute;
096   bottom0;
097   z-index4;
098   -webkit-animation-name: animation_bg_element1;
099   animation-name: animation_bg_element1;
100   -webkit-animation-duration: 5s;
101   animation-duration: 5s;
102   -webkit-animation-iteration-count: infinite;
103   animation-iteration-count: infinite;
104   -webkit-animation-delay: 0s;
105   animation-delay: 0s;
106 }
107
108 .flask_bottom_two {
109   border-bottom165px solid #4266c0;
110   border-left93px solid transparent;
111   border-right200px solid transparent;
112   width0;
113   height0;
114   positionabsolute;
115   left0;
116   bottom0;
117   z-index2;
118   -webkit-animation-name: animation_bg_element2;
119   animation-name: animation_bg_element2;
120   -webkit-animation-duration: 5s;
121   animation-duration: 5s;
122   -webkit-animation-iteration-count: infinite;
123   animation-iteration-count: infinite;
124   -webkit-animation-delay: 0s;
125   animation-delay: 0s;
126 }
127
128 .flask_bottom_five {
129   positionabsolute;
130   background-color#4248c0;
131   width100%;
132   height75px;
133   positionabsolute;
134   z-index3;
135   left50px;
136   bottom18px;
137   -webkit-transform: rotate(24deg);
138   transform: rotate(24deg);
139   -webkit-transform-origin: left top;
140   transform-origin: left top;
141   -webkit-animation-name: animation_bg_element3;
142   animation-name: animation_bg_element3;
143   -webkit-animation-duration: 5s;
144   animation-duration: 5s;
145   -webkit-animation-iteration-count: infinite;
146   animation-iteration-count: infinite;
147   -webkit-animation-delay: 0s;
148   animation-delay: 0s;
149 }
150
151 .flask_bottom_six {
152   positionabsolute;
153   background-color#37acdd;
154   width100%;
155   height170px;
156   positionabsolute;
157   z-index1;
158   right0;
159   bottom0;
160   -webkit-animation-name: animation_bg_element4;
161   animation-name: animation_bg_element4;
162   -webkit-animation-duration: 5s;
163   animation-duration: 5s;
164   -webkit-animation-iteration-count: infinite;
165   animation-iteration-count: infinite;
166   -webkit-animation-delay: 0s;
167   animation-delay: 0s;
168 }
169
170 .flask_bottom_seven {
171   positionabsolute;
172   background-color#1493c8;
173   width100%;
174   height218px;
175   positionabsolute;
176   z-index3;
177   right-95px;
178   bottom24px;
179   -webkit-transform: rotate(24deg);
180   transform: rotate(24deg);
181   -webkit-transform-origin: right top;
182   transform-origin: right top;
183   -webkit-animation-name: animation_bg_element5;
184   animation-name: animation_bg_element5;
185   -webkit-animation-duration: 5s;
186   animation-duration: 5s;
187   -webkit-animation-iteration-count: infinite;
188   animation-iteration-count: infinite;
189   -webkit-animation-delay: 0s;
190   animation-delay: 0s;
191 }
192
193 .flask_bottom_eight {
194   positionabsolute;
195   background-color#5c30ae;
196   width100%;
197   height50px;
198   positionabsolute;
199   z-index3;
200   right-95px;
201   bottom218px;
202   -webkit-transform: rotate(-12deg);
203   transform: rotate(-12deg);
204   -webkit-transform-origin: left top;
205   transform-origin: left top;
206   -webkit-animation-name: animation_bg_element6;
207   animation-name: animation_bg_element6;
208   -webkit-animation-duration: 5s;
209   animation-duration: 5s;
210   -webkit-animation-iteration-count: infinite;
211   animation-iteration-count: infinite;
212   -webkit-animation-delay: 0s;
213   animation-delay: 0s;
214 }

Conclusion

In this article we demonstrated the possibilities of modern CSS3. I hope that this is interesting for you, and you will be able to create spectacular work.