<html>
<head>
<title>I Love You!</title>
<meta charset="utf-8" />
<style>
* {
margin: 0;
padding: 0;
}
#castle {
position: relative;
width: 100vw;
height: 100vh;
background: radial-gradient(#293c4d, #001920);
overflow: hidden;
}
#table {
position: absolute;
left: calc(50% - 200px);
top: calc(50% - 50px);
width: 400px;
height: 400px;
background: radial-gradient(#a3727e, #af7279, #a16674);
border-radius: 100%;
border-bottom: 80px solid #623c53;
transform: scaleY(0.225);
}
.shade-wrap {
position: absolute;
left: calc(50% - 100px);
top: calc(52% - 250px);
width: 200px;
height: 400px;
}
#flower-wrap {
position: relative;
top: -50px;
}
#shade-main {
position: absolute;
left: 20px;
top: 100px;
width: 160px;
height: 300px;
border-top: 1px solid rgba(255, 255, 255, 0.5);
border-left: 1px solid rgba(255, 255, 255, 0.5);
border-right: 1px solid rgba(255, 255, 255, 0.6);
border-top-left-radius: 50% 30%;
border-top-right-radius: 50% 30%;
border-bottom: none;
transform: perspective(200px) rotateX(8deg) scale(1.075, 1);
}
#shade-main:after {
content: "";
position: absolute;
bottom: -20px;
width: 100%;
height: 40px;
transform: scaleY(0.5);
border-radius: 100%;
background: radial-gradient(#d287a5, #da9db6, #985e74);
}
#shade-main-reflections {
position: relative;
left: 20px;
top: 100px;
width: 160px;
height: 300px;
border-top-left-radius: 50% 30%;
border-top-right-radius: 50% 30%;
border-bottom: none;
background-color: #6d6179;
transform: perspective(200px) rotateX(8deg) scale(1.075, 1);
opacity: 0.25;
}
#shade-main-reflections:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
border-top-right-radius: 50% 30%;
border-right: 20px solid rgba(255, 255, 255, 0.5);
transform: scale(0.7, 0.85);
filter: blur(5px);
}
#shade-main-reflections:before {
content: "";
position: absolute;
width: 100%;
height: 100%;
border-top-left-radius: 50% 30%;
border-left: 8px solid rgba(255, 255, 255, 0.6);
transform: scale(0.85, 0.85);
filter: blur(5px);
}
#inner-glow {
position: absolute;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
border-radius: 100%;
background-color: #a16674;
animation: innerGlow 3s ease-in-out infinite;
}
#shade-handle-big {
position: absolute;
left: 55px;
top: -14px;
width: 50px;
height: 30px;
border-radius: 100%;
border-top: 1px solid rgba(255, 255, 255, 0.7);
transform: scaleY(0.9);
}
#shade-handle-small {
position: absolute;
left: 70px;
top: -33px;
width: 20px;
height: 20px;
border-radius: 100%;
border: 1px solid rgba(255, 255, 255, 0.5);
border-bottom: none;
}
#stem {
position: absolute;
left: 82px;
top: 187px;
width: 100px;
height: 150px;
background-color: transparent;
border: solid 4px #a1b965;
border-color: transparent transparent transparent #a1b965;
border-radius: 50%/120px 100px 0 0;
transform: rotate(-3deg) scale(1.1, 0.9);
}
#petal1 {
position: absolute;
left: 97px;
top: 188px;
width: 25px;
height: 25px;
border-top-left-radius: 50% 10%;
border-top-right-radius: 50% 10%;
border-bottom-left-radius: 50% 40%;
border-bottom-right-radius: 50% 40%;
background-color: #c82b60;
box-shadow: 1px -1px 1px 0 #6f1232;
transform: rotate(32deg) scale(1.6, 1.6);
}
#petal1:before {
content: "";
position: absolute;
height: 100%;
width: 100%;
border-top-left-radius: 50% 10%;
border-top-right-radius: 50% 10%;
border-bottom-left-radius: 50% 40%;
border-bottom-right-radius: 50% 40%;
background-color: transparent;
box-shadow: 0 0 10px 0 #e8b2ca;
opacity: 0.9;
}
#petal1:after {
content: "";
position: absolute;
height: 100%;
width: 100%;
border-top-left-radius: 50% 10%;
border-top-right-radius: 50% 10%;
border-bottom-left-radius: 50% 40%;
border-bottom-right-radius: 50% 40%;
background-color: transparent;
box-shadow: 0 0 35px 0 #e8b2ca;
animation: glow 3s ease-in-out infinite;
}
#petal2 {
position: absolute;
left: 85px;
top: 185px;
width: 25px;
height: 30px;
border-top-left-radius: 50% 10%;
border-top-right-radius: 50% 50%;
border-bottom-left-radius: 50% 50%;
border-bottom-right-radius: 50% 10%;
background-color: #d05478;
transform: rotate(35deg) scale(1.2, 1);
box-shadow: 1px -1px 1px 0 #6f1232;
opacity: 0.9;
}
#petal3 {
position: absolute;
left: 105px;
top: 197px;
width: 25px;
height: 28px;
border-top-left-radius: 50% 50%;
border-top-right-radius: 10% 10%;
border-bottom-left-radius: 10% 10%;
border-bottom-right-radius: 50% 50%;
background-color: #cb5275;
transform: rotate(25deg) scale(1, 1.05) skew(-8deg);
box-shadow: 1px -1px 1px 0 #6f1232;
opacity: 0.9;
}
#petal4 {
position: absolute;
left: 80px;
top: 191px;
width: 25px;
height: 25px;
border-top-left-radius: 50% 10%;
border-top-right-radius: 50% 50%;
border-bottom-left-radius: 50% 50%;
border-bottom-right-radius: 50% 10%;
background-color: #d26484;
transform: rotate(30deg) scale(1.1, 0.9) skew(10deg);
box-shadow: 1px -1px 1px 0 #a53d60;
opacity: 0.9;
}
#petal5 {
position: absolute;
left: 105px;
top: 207px;
width: 25px;
height: 20px;
border-top-left-radius: 50% 50%;
border-top-right-radius: 10% 10%;
border-bottom-left-radius: 10% 10%;
border-bottom-right-radius: 50% 50%;
background-color: #d26484;
transform: rotate(28deg) scale(1, 1.05) skew(-18deg);
box-shadow: 1px -1px 1px 0 #a53d60;
opacity: 0.9;
}
#falling-petal {
position: absolute;
left: 105px;
top: 209px;
width: 22px;
height: 18px;
border-top-left-radius: 50% 50%;
border-top-right-radius: 10% 10%;
border-bottom-left-radius: 10% 10%;
border-bottom-right-radius: 50% 50%;
background-color: #da7290;
transform: rotate(32deg) scale(0.9, 0.95) skew(-18deg);
box-shadow: 1px -1px 1px 0 #a53d60;
opacity: 0.9;
animation: fall 5s ease-in-out forwards;
}
#leaf1 {
position: absolute;
left: 75px;
top: 225px;
width: 13px;
height: 20px;
border-top-left-radius: 50% 10%;
border-top-right-radius: 50% 50%;
border-bottom-left-radius: 50% 50%;
border-bottom-right-radius: 50% 10%;
background-color: #a1b965;
transform: rotate(5deg);
}
#leaf2 {
position: absolute;
left: 82px;
top: 265px;
width: 12px;
height: 16px;
border-top-left-radius: 50% 10%;
border-top-right-radius: 50% 50%;
border-bottom-left-radius: 50% 50%;
border-bottom-right-radius: 50% 10%;
background-color: #a1b965;
transform: rotate(-97deg);
}
#rose-glow {
position: absolute;
left: 91px;
top: 180px;
width: 40px;
height: 40px;
border-radius: 100%;
background-color: white;
}
.dustDef {
position: absolute;
background-color: white;
border-radius: 100%;
box-shadow: 0 0 1px 1px white;
opacity: 0;
}
.hov {
animation: hover 2.5s ease-in-out infinite;
}
@keyframes hover {
0% {
margin-top: 60px;
}
50% {
margin-top: 50px;
}
100% {
margin-top: 60px;
}
}
@keyframes glow {
0% {
box-shadow: 0 0 25px 0 #e8b2ca;
}
50% {
box-shadow: 0 0 45px 0 #e8b2ca;
}
100% {
box-shadow: 0 0 25px 0 #e8b2ca;
}
}
@keyframes fall {
0% {
top: 209px;
transform: rotate(32deg) scale(0.9, 0.95) skew(-18deg);
opacity: 0.9;
}
100% {
top: 300px;
transform: rotate(60deg) scale(0.9, 0.95) skew(-18deg);
opacity: 0;
}
}
@keyframes innerGlow {
0% {
filter: blur(10px);
}
50% {
filter: blur(15px);
}
100% {
filter: blur(10px);
}
}
</style>
</head>
<body>
<div id="castle">
<div id="table"></div>
<div class="shade-wrap hov" id="main">
<div id="flower-wrap">
<div id="stem"></div>
<div id="petal1"></div>
<div id="petal2"></div>
<div id="petal3"></div>
<div id="petal4"></div>
<div id="petal5"></div>
<div id="falling-petal"></div>
<div id="leaf1"></div>
<div id="leaf2"></div>
</div>
</div>
<div class="shade-wrap" id="sub">
<div id="shade-main-reflections"></div>
<div id="shade-main">
<div id="shade-handle-big"></div>
<div id="shade-handle-small"></div>
<div id="top-reflection"></div>
</div>
</div>
</div>
<script>
(() => {
const head = document.getElementsByTagName('head')[0];
let animationId = 1;
function CreateMagicDust(x1, x2, y1, y2, sizeRatio, fallingTime, animationDelay, node = 'main') {
let dust = document.createElement('span');
let animation = document.createElement('style');
animation.innerHTML = '\
@keyframes blink' + animationId + '{\
0% {\
top: ' + y1 + 'px;\
left: ' + x1 + 'px;\
width: ' + 2*sizeRatio + 'px;\
height: ' + 2*sizeRatio + 'px;\
opacity: .4\
}\
20% {\
width: ' + 4*sizeRatio + 'px;\
height: ' + 4*sizeRatio + 'px;\
opacity: .8\
}\
35% {\
width: ' + 2*sizeRatio + 'px;\
height: ' + 2*sizeRatio + 'px;\
opacity: .5\
}\
55% {\
width: ' + 3*sizeRatio + 'px;\
height: ' + 3*sizeRatio + 'px;\
opacity: .7\
}\
80% {\
width: ' + sizeRatio + 'px;\
height: ' + sizeRatio + 'px;\
opacity: .3\
}\
100% {\
top: ' + y2 + 'px;\
left: ' + x2 + 'px;\
width: ' + 0 + 'px;\
height: ' + 0 + 'px;\
opacity: .1\
}}';
head.appendChild(animation);
dust.classList.add('dustDef');
dust.setAttribute('style', `animation: blink${animationId++} ${fallingTime}s cubic-bezier(.71, .11, .68, .83) infinite ${animationDelay}s`);
document.getElementById(node).appendChild(dust);
}
// yes, I'm doing it manually to get the effect I want.. can be easily changed to render randomly
[[130, 132, 150, 152, .15, 2.5,.1, 'sub'],
[65, 63, 300, 299, .5, 2, .2, 'sub' ],
[70, 70, 150, 150, .45, 2, .5],
[75, 78, 160, 170, .6, 2, 1],
[80, 82, 160, 180, .6, 1, .4],
[85, 100, 160, 170, .5, 2, .5],
[125, 110, 170, 180, .25, 3, 1.5],
[90, 90, 115, 115, .4, 2, 2],
[93, 95, 200, 200, .4, 3, 1.5],
[100, 100, 145, 155, .45, 1, .5],
[100, 90, 170, 230, .35, 2, .75],
[100, 102, 115, 112, .35, 3, .25],
[100, 95, 170, 200, .55, 1.5, .75],
[100, 97, 150, 190, .7, 2, 1.5],
[105, 100, 160, 180, .5, 1.5, .725],
[125, 125, 180, 190, .25, 1, .725],
[130, 130, 135, 135, .45, 3, 1.5],
[135, 132, 170, 190, .25, 2.5, .75],
[135, 132, 320, 315, .2, 5, .3, 'sub']
].forEach((o) => CreateMagicDust(...o));
})();
</script>
</body>
</html>