Hey everyone! Today, let’s whip up a cute “I Love You” animation using HTML, CSS, and JavaScript. Valentine’s I love you Animation. This project is great for all skill levels, whether you’re just starting out or a seasoned developer looking for a quick and fun project.
We’ll keep things easy and breezy, using basic HTML for the structure, simple CSS for styling, and a touch of JavaScript for some playful animation. No need for anything too complicated – just some good ol’ coding fun!
So, let’s jump in and create this adorable “I Love You” animation together. Whether you’re a coding newbie or just looking for a light-hearted project, let’s have a blast making something sweet. Let’s get started and spread some love through code!
HTML :
The provided code is an HTML document that includes a title, a stylesheet link, and a JavaScript script. It also contains a container with an SVG element and a div element. Additionally, there are two audio elements with source tags for audio files.
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <title> I love you Animation | Coding Stella </title> <link rel="stylesheet" href="./style.css"> </head> <body> <!-- partial:index.partial.html --> <div class="container"> <svg class="svg-container" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 200"> <line class="line line--left" x1="10" y1="17" x2="10" y2="183"> </line> <line class="line line--rght" x1="490" y1="17" x2="490" y2="183"> </line> <g> <path class="lttr lttr--I" d="M42.2,73.9h11.4v52.1H42.2V73.9z"></path> <path class="lttr lttr--L" d="M85.1,73.9h11.4v42.1h22.8v10H85.1V73.9z"></path> <path class="lttr lttr--O" d="M123.9,100c0-15.2,11.7-26.9,27.2-26.9s27.2,11.7,27.2,26.9s-11.7,26.9-27.2,26.9S123.9,115.2,123.9,100zM166.9,100c0-9.2-6.8-16.5-15.8-16.5c-9,0-15.8,7.3-15.8,16.5s6.8,16.5,15.8,16.5C160.1,116.5,166.9,109.2,166.9,100z"> </path> <path class="lttr lttr--V" d="M180.7,73.9H193l8.4,22.9c1.7,4.7,3.5,9.5,5,14.2h0.1c1.7-4.8,3.4-9.4,5.2-14.3l8.6-22.8h11.7l-19.9,52.1h-11.5L180.7,73.9z"></path> <path class="lttr lttr--E" d="M239.1,73.9h32.2v10h-20.7v10.2h17.9v9.5h-17.9v12.4H272v10h-33V73.9z"></path> <path class="lttr lttr--Y" d="M315.8,102.5l-20.1-28.6H309l6.3,9.4c2,3,4.2,6.4,6.3,9.6h0.1c2-3.2,4.1-6.4,6.3-9.6l6.3-9.4h12.9l-19.9,28.5v23.6h-11.4V102.5z"></path> <path class="lttr lttr--O2" d="M348.8,100c0-15.2,11.7-26.9,27.2-26.9c15.5,0,27.2,11.7,27.2,26.9s-11.7,26.9-27.2,26.9C360.5,126.9,348.8,115.2,348.8,100z M391.8,100c0-9.2-6.8-16.5-15.8-16.5c-9,0-15.8,7.3-15.8,16.5s6.8,16.5,15.8,16.5C385,116.5,391.8,109.2,391.8,100z"></path> <path class="lttr lttr--U" d="M412.4,101.1V73.9h11.4v26.7c0,10.9,2.4,15.9,11.5,15.9c8.4,0,11.4-4.6,11.4-15.8V73.9h11v26.9c0,7.8-1.1,13.5-4,17.7c-3.7,5.3-10.4,8.4-18.7,8.4c-8.4,0-15.1-3.1-18.8-8.5C413.4,114.2,412.4,108.5,412.4,101.1z"></path> </g> </svg> <div class="mo-container"> </div> </div> <audio class="blup" style="display: none"> <source src="https://www.freesound.org/data/previews/265/265115_4373976-lq.mp3" type="audio/ogg"> </audio> <audio class="blop" style="display: none"> <source src="https://www.freesound.org/data/previews/265/265115_4373976-lq.mp3" type="audio/ogg"> </audio> <div class="sound">sound</div> <!-- partial --> <script src='https://cdn.jsdelivr.net/mojs/latest/mo.min.js'></script><script src="./script.js"></script> </body> </html>
CSS :
This concise CSS snippet defines styles for HTML elements. It ensures consistent box models, centers content both horizontally and vertically, sets a dark background color (#282a36), specifies font size and family, and includes a media query for smaller screens. The .container
class establishes a relative-positioned container, while the .line
class defines stroke properties for lines. The .lttr
class fills letters with a light blue color (#a5b9c7), and the .sound
class fixes its position, color, and font size. The .sound--off
class applies a line-through style. Overall, it creates a visually appealing layout! 🎨✨
*, *:before, *:after { box-sizing: border-box; margin: 0; padding: 0; } html, body { min-height: 100vh; display: flex; justify-content: center; align-items: center; background-color: #282a36; font-size: 62.5%; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } @media screen and (max-width: 520px) { html, body { /* don't know how to set default units to rem in mojs :(( */ } } .container { width: 50rem; height: 20rem; position: relative; } .svg-container { z-index: 2; position: absolute; } .mo-container { width: 100%; height: 100%; } .line { fill: none; stroke: #ffffff; stroke-width: 8; stroke-linecap: round; stroke-miterlimit: 10; } .lttr { fill: #a5b9c7; } .sound { position: fixed; color: #a5b9c7; font-size: 1.6rem; bottom: 1rem; right: 1rem; text-decoration: underline; cursor: default; } .sound--off { text-decoration: line-through; }
JavaScript:
This JavaScript code creates the required Animation for I LOVE YOU.
const qs = document.querySelector.bind(document); const easingHeart = mojs.easing.path( "M0,100C2.9,86.7,33.6-7.3,46-7.3s15.2,22.7,26,22.7S89,0,100,0"); const el = { container: qs(".mo-container"), i: qs(".lttr--I"), l: qs(".lttr--L"), o: qs(".lttr--O"), v: qs(".lttr--V"), e: qs(".lttr--E"), y: qs(".lttr--Y"), o2: qs(".lttr--O2"), u: qs(".lttr--U"), lineLeft: qs(".line--left"), lineRight: qs(".line--rght"), colTxt: "#763c8c", colHeart: "#fa4843", blup: qs(".blup"), blop: qs(".blop"), sound: qs(".sound") }; class Heart extends mojs.CustomShape { getShape() { return '<path d="M50,88.9C25.5,78.2,0.5,54.4,3.8,31.1S41.3,1.8,50,29.9c8.7-28.2,42.8-22.2,46.2,1.2S74.5,78.2,50,88.9z"/>'; } getLength() { return 200; }} mojs.addShape("heart", Heart); const crtBoom = (delay = 0, x = 0, rd = 46) => { parent = el.container; const crcl = new mojs.Shape({ shape: "circle", fill: "none", stroke: el.colTxt, strokeWidth: { 5: 0 }, radius: { [rd]: [rd + 20] }, easing: "quint.out", duration: 500 / 3, parent, delay, x }); const brst = new mojs.Burst({ radius: { [rd + 15]: 110 }, angle: "rand(60, 180)", count: 3, timeline: { delay }, parent, x, children: { radius: [5, 3, 7], fill: el.colTxt, scale: { 1: 0, easing: "quad.in" }, pathScale: [0.8, null], degreeShift: ["rand(13, 60)", null], duration: 1000 / 3, easing: "quint.out" } }); return [crcl, brst]; }; const crtLoveTl = () => { const move = 1000; const boom = 200; const easing = "sin.inOut"; const easingBoom = "sin.in"; const easingOut = "sin.out"; const opts = { duration: move, easing, opacity: 1 }; const delta = 150; return new mojs.Timeline().add([ new mojs.Tween({ duration: move, onStart: () => { [el.i, el.l, el.o, el.v, el.e, el.y, el.o2, el.u].forEach(el => { el.style.opacity = 1; el.style = "transform: translate(0px, 0px) rotate(0deg) skew(0deg, 0deg) scale(1, 1); opacity: 1;"; }); }, onComplete: () => { [el.l, el.o, el.v, el.e].forEach(el => el.style.opacity = 0); el.blop.play(); } }), new mojs.Tween({ duration: move * 2 + boom, onComplete: () => { [el.y, el.o2].forEach(el => el.style.opacity = 0); el.blop.play(); } }), new mojs.Tween({ duration: move * 3 + boom * 2 - delta, onComplete: () => { el.i.style.opacity = 0; el.blop.play(); } }), new mojs.Tween({ duration: move * 3 + boom * 2, onComplete: () => { el.u.style.opacity = 0; el.blup.play(); } }), new mojs.Tween({ duration: 50, delay: 4050, onUpdate: progress => { [el.i, el.l, el.o, el.v, el.e, el.y, el.o2, el.u].forEach(el => { el.style = `transform: translate(0px, 0px) rotate(0deg) skew(0deg, 0deg) scale(1, 1); opacity: ${ 1 * progress };`; }); }, onComplete: () => { [el.i, el.l, el.o, el.v, el.e, el.y, el.o2, el.u].forEach(el => { el.style.opacity = 1; el.style = "transform: translate(0px, 0px) rotate(0deg) skew(0deg, 0deg) scale(1, 1); opacity: 1;"; }); } }), new mojs.Html({ ...opts, el: el.lineLeft, x: { 0: 52 } }). then({ duration: boom + move, easing, x: { to: 52 + 54 } }). then({ duration: boom + move, easing, x: { to: 52 + 54 + 60 } }). then({ duration: 150, // 3550 easing, x: { to: 52 + 54 + 60 + 10 } }). then({ duration: 300 }). then({ duration: 350, x: { to: 0 }, easing: easingOut }), new mojs.Html({ ...opts, el: el.lineRight, x: { 0: -52 } }). then({ duration: boom + move, easing, x: { to: -52 - 54 } }). then({ duration: boom + move, easing, x: { to: -52 - 54 - 60 } }). then({ duration: 150, easing, x: { to: -52 - 54 - 60 - 10 } }). then({ duration: 300 }). then({ duration: 350, x: { to: 0 }, easing: easingOut }), new mojs.Html({ // [I] LOVE YOU ...opts, el: el.i, x: { 0: 34 } }). then({ duration: boom, easing: easingBoom, x: { to: 34 + 19 } }). then({ duration: move, easing, x: { to: 34 + 19 + 40 } }). then({ duration: boom, easing: easingBoom, x: { to: 34 + 19 + 40 + 30 } }). then({ duration: move, easing, x: { to: 34 + 19 + 40 + 30 + 30 } }), new mojs.Html({ // I [L]OVE YOU ...opts, el: el.l, x: { 0: 15 } }), new mojs.Html({ // I L[O]VE YOU ...opts, el: el.o, x: { 0: 11 } }), new mojs.Html({ // I LO[V]E YOU ...opts, el: el.v, x: { 0: 3 } }), new mojs.Html({ // I LOV[E] YOU ...opts, el: el.e, x: { 0: -3 } }), new mojs.Html({ // I LOVE [Y]OU ...opts, el: el.y, x: { 0: -20 } }). then({ duration: boom, easing: easingBoom, x: { to: -20 - 33 } }). then({ duration: move, easing, x: { to: -20 - 33 - 24 } }), new mojs.Html({ // I LOVE Y[O]U ...opts, el: el.o2, x: { 0: -27 } }). then({ duration: boom, easing: easingBoom, x: { to: -27 - 27 } }). then({ duration: move, easing, x: { to: -27 - 27 - 30 } }), new mojs.Html({ // I LOVE YO[U] ...opts, el: el.u, x: { 0: -32 } }). then({ duration: boom, easing: easingBoom, x: { to: -32 - 21 } }). then({ duration: move, easing, x: { to: -32 - 21 - 36 } }). then({ duration: boom, easing: easingBoom, x: { to: -32 - 21 - 36 - 31 } }). then({ duration: move, easing, x: { to: -32 - 21 - 36 - 31 - 27 } }), new mojs.Shape({ parent: el.container, shape: "heart", delay: move, fill: el.colHeart, x: -64, scale: { 0: 0.95, easing: easingHeart }, duration: 500 }). then({ x: { to: -62, easing }, scale: { to: 0.65, easing }, duration: boom + move - 500 }). then({ duration: boom - 50, x: { to: -62 + 48 }, scale: { to: 0.9 }, easing: easingBoom }). then({ duration: 125, scale: { to: 0.8 }, easing: easingOut }). then({ duration: 125, scale: { to: 0.85 }, easing: easingOut }). then({ duration: move - 200, scale: { to: 0.45 }, easing }). then({ delay: -75, duration: 150, x: { to: 0 }, scale: { to: 0.9 }, easing: easingBoom }). then({ duration: 125, scale: { to: 0.8 }, easing: easingOut }). then({ duration: 125, // 3725 scale: { to: 0.85 }, easing: easingOut }). then({ duration: 125 // 3850 }). then({ duration: 350, scale: { to: 0 }, easing: easingOut }), ...crtBoom(move, -64, 46), ...crtBoom(move * 2 + boom, 18, 34), ...crtBoom(move * 3 + boom * 2 - delta, -64, 34), ...crtBoom(move * 3 + boom * 2, 45, 34)]); }; const loveTl = crtLoveTl().play(); setInterval(() => { loveTl.replay(); }, 4300); const volume = 0.2; el.blup.volume = volume; el.blop.volume = volume; const toggleSound = () => { let on = true; return () => { if (on) { el.blup.volume = 0.0; el.blop.volume = 0.0; el.sound.classList.add("sound--off"); } else { el.blup.volume = volume; el.blop.volume = volume; el.sound.classList.remove("sound--off"); } on = !on; }; }; el.sound.addEventListener("click", toggleSound());
In summary, creating this “I Love You” animation has been a fun and rewarding experience. Using HTML, CSS, and JavaScript, we’ve added a touch of sweetness to our projects. Whether you’re new to coding or a seasoned developer, I hope you’ve enjoyed this journey as much as I have.
If you run into any problems with your project, worry not. The remedy is just a click away—Download the source code and confront your coding challenges with enthusiasm. Enjoy your coding adventure!