Learn with us how to create an amazing Lava Lamp in HTML and CSS!
If you found us on TikTok on the following post, check out this article and copy-paste the full code!
Happy coding! 😻
Contents:
1. HTML Code
2. CSS Code
3. Javascript Code
Get your code ⬇️
1. HTML Code
.scene
- const height = 400
- const width = 150
- const inRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min
mixin lava(amount)
.lava-lamp__lava
svg
ellipse.blob.blob--top(cx='35', cy='0', rx='35', ry='10')
ellipse.blob.blob--bottom(cx='75', cy='270', rx='75', ry='10')
- for (let i = 0; i < amount; i++)
- const speed = inRange(8, 50)
- const delay = inRange(0, 10) - 10
- const height = inRange(30, 100)
- const width = inRange(30, 100)
- const skewX = inRange(0, 10) - 5
- const skewY = inRange(0, 10) - 5
- const rotation = inRange(0, 360)
- const x = inRange(0, 150)
- const direction = Math.random() > 0.5 ? 'alternate' : 'alternate-reverse'
circle.blob(r=(height / 2), cx=x, cy='400', style=`--skewX: ${skewX}; --skewY: ${skewY}; --height: ${height}; --speed: ${speed}; --delay: ${delay}; --direction: ${direction};`)
.lava-lamp(style=`--height: ${height}; --width: ${width}`)
.lava-lamp__main
.lava-lamp__glass
+lava(3)
+lava(4)
+lava(2)
+lava(1)
.lava-lamp__base
svg(style='position: absolute; left: 100%')
defs
filter(id=`goo`)
feGaussianBlur(in='SourceGraphic', stdDeviation='10', result='BLUR')
feColorMatrix(in='BLUR', mode='matrix', values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7', result='GOO')
feBlend(in='SourceGraphic', in2=`goo`)
2. CSS Code
*
box-sizing border-box
body
background darken(#8c14fc, 80%)
min-height 100vh
.scene
align-items center
display flex
justify-content center
width 100vw
position relative
height 100vh
overflow-x hidden
$lamp = #000
// $shadow = #bf55ec
// $core = #663399
// $lava = lighten(#9f5afd, 30%)
// $lava-bg = radial-gradient(circle at 50% 50%, $core 25%, $shadow)
$shadow = #19b5fe
$core = #3a539b
$lava = #29f1c3
$lava-bg = radial-gradient(circle at 50% 50%, $core 25%, $shadow)
img
position absolute
top 50%
left 50%
transform translate(-69.5%, -26%)
opacity .2
height 1300px
.lava-lamp
height calc(var(--height) * 1px)
width calc(var(--width) * 1px)
position relative
&:after
content ''
height 500px
width 500px
position absolute
background radial-gradient(circle at 50% 50%, $shadow, transparent 60%)
top 45%
left 50%
z-index 4
transform translate(-50%, -50%)
filter blur(10px)
opacity .5
&:before
content ''
height 25%
width 300%
border-radius 100%
background radial-gradient(ellipse at 50% 50%, $shadow, transparent 60%)
position absolute
top 85%
left 50%
transform translate(-50%, 0)
opacity .5
filter blur(10px)
&__main
border-radius 50% 50% 50% 50% / 60% 60% 40% 40%
width 100%
height 100%
position relative
overflow hidden
z-index 2
&:after
&:before
background $lamp
content ''
height 12%
left 0
position absolute
width 100%
&:after
top 0
&:before
bottom 0
height 26%
&__glass
background $lava-bg
border-radius 50% / 10%
overflow hidden
height 70%
left 0
position absolute
top 10%
width 100%
z-index 2
&__base
height 20%
width 100%
position absolute
bottom 0
overflow hidden
border-radius 0 0 50% 50% / 0 0 35% 35%
&:before
content ''
background $lamp
border-radius 50% 50% 50% 50% / 60% 60% 40% 40%
position absolute
top -60%
height calc(var(--height) * 1px)
width calc(var(--width) * 1px)
&__lava
border-radius 50% / 10%
height 100%
overflow hidden
position absolute
width 100%
filter url('#goo')
svg
height 280px
width 150px
.blob
animation-delay calc(var(--delay) * 1s)
animation-direction var(--direction)
animation-duration calc(var(--speed) * 1s)
animation-iteration-count infinite
animation-name blob
animation-timing-function linear
fill $lava
transform-box fill-box
&--bottom
&--top
animation none
&--top
animation sway 20s infinite linear
@keyframes sway
50%
transform translate(50%, 0)
@keyframes blob
from
transform skew(calc(var(--skewX) * 1deg), calc(var(--skewY) * 1deg)) translate(0, 0)
to
transform skew(calc(var(--skewX) * 1deg), calc(var(--skewY) * 1deg)) translate(0, calc((400 + (var(--height) * 2)) * -1px))
3. Javascript Code
// NOPE
/**
* Possible by randomly generating CSS variables
* within our markup code.
* Those variables define the characteristics of
* each blob.
*/
I hope you did find this tutorial useful!
For more web development or UI/UX design tutorials, follow us on:
Other useful resources: