Liveweave: Generative AI Web Editor & HTML/CSS/JS Playground
Initializing
Liveweave
Web
expand_more
home
Home
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
frame_source
Python Playground
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Fork
account_circle
Login
settings
Settings
expand_more
Editor font
14
px
A
A
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
left_panel_close
AI Assistant
dashboard
All
HTML
CSS
JS
visibility
Preview
bolt
Live Preview
terminal
JS Console
<!DOCTYPE html> <html> <head> <title>Diwali lamp demo</title> </head> <body> <!-- Start your code here --> <div class="diwali-scene" id="diwali"> <canvas id="diyaCanvas"></canvas> <div class="diwali-header"> <div class="ornament">✦ ❋ ✦ ❋ ✦</div> <h2>HAPPY DIWALI</h2> <p>May the light always find its way.</p> </div> <div class="diwali-footer"> <span>THE FESTIVAL OF LIGHTS</span> <button id="lightDiya">LIGHT THE DIYA ✨</button> <span>JOY · PROSPERITY · HOPE</span> </div> </div> <!-- End your code here --> </body> </html>
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@300;400;600&family=Noto+Serif+Devanagari:wght@400;600&display=swap'); * { box-sizing: border-box; } body { margin: 0; background: #100507; } .diwali-scene { position: relative; width: 100%; height: min(760px, 100vh); min-height: 520px; overflow: hidden; background: radial-gradient(ellipse at 50% 65%, #651b12 0%, #2c0a0b 45%, #100507 100%); isolation: isolate; } #diyaCanvas { position: absolute; inset: 0; width: 100%; height: 100%; } .diwali-header { position: absolute; top: 35px; width: 100%; text-align: center; color: #f8df9c; pointer-events: none; z-index: 2; } .ornament { color: #e7a94b; font-size: 18px; letter-spacing: 8px; opacity: .8; } .diwali-header h1 { font-family: 'Noto Serif Devanagari', serif; font-size: clamp(30px, 5vw, 55px); font-weight: 400; margin: 15px 0 5px; text-shadow: 0 0 30px #ff9d2e66; } .diwali-header h2 { font-family: 'Cormorant Garamond', serif; font-size: clamp(22px, 4vw, 40px); letter-spacing: 9px; font-weight: 300; margin: 8px 0; } .diwali-header p { font-family: 'Cormorant Garamond', serif; font-size: 18px; font-style: italic; color: #d5b98a; letter-spacing: 1px; } .diwali-footer { position: absolute; bottom: 24px; left: 0; width: 100%; display: flex; justify-content: space-around; align-items: center; gap: 10px; color: #cda76a; font: 9px Arial, sans-serif; letter-spacing: 3px; z-index: 3; } .diwali-footer button { border: 1px solid #d6a44f; color: #ffe5a6; background: #54190eaa; padding: 13px 22px; letter-spacing: 2px; font: 11px Arial, sans-serif; cursor: pointer; transition: .3s; } .diwali-footer button:hover { background: #d38a2e; color: #2c1007; box-shadow: 0 0 30px #ffb33d66; } .diwali-scene.lit { background: radial-gradient(ellipse at 50% 65%, #a13c12 0%, #45100c 48%, #100507 100%); } @media(max-width: 600px) { .diwali-header { top: 25px; } .diwali-header h2 { letter-spacing: 5px; } .diwali-footer span { display: none; } .diwali-footer { justify-content: center; } } @media(prefers-reduced-motion: reduce) { .diwali-scene *, .diwali-scene *::before, .diwali-scene *::after { animation: none !important; transition: none !important; } }
const canvas = document.getElementById("diyaCanvas"); const ctx = canvas.getContext("2d"); const scene = document.getElementById("diwali"); const lightButton = document.getElementById("lightDiya"); let W, H, dpr; let time = 0; let lastTime = 0; let lit = true; const sparks = []; function resize() { const r = canvas.getBoundingClientRect(); W = r.width; H = r.height; dpr = Math.min(window.devicePixelRatio || 1, 2); canvas.width = W * dpr; canvas.height = H * dpr; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); } window.addEventListener("resize", resize); resize(); function ellipse(x, y, rx, ry, color) { ctx.beginPath(); ctx.ellipse(x, y, rx, ry, 0, 0, Math.PI * 2); ctx.fillStyle = color; ctx.fill(); } function polygon(points, color) { ctx.beginPath(); points.forEach(function(p, i) { if (i === 0) ctx.moveTo(p[0], p[1]); else ctx.lineTo(p[0], p[1]); }); ctx.closePath(); ctx.fillStyle = color; ctx.fill(); } function glow(x, y, radius, color) { const g = ctx.createRadialGradient( x, y, 0, x, y, radius ); g.addColorStop(0, color); g.addColorStop(1, "transparent"); ellipse(x, y, radius, radius, g); } function background() { // Ambient diya light if (lit) { glow(W / 2, H * .65, H * .55, "rgba(255,120,20,.12)"); } // Decorative rangoli-inspired radial geometry const cx = W / 2; const cy = H * .72; const radius = Math.min(W, H) * .37; ctx.save(); ctx.translate(cx, cy); for (let i = 0; i < 24; i++) { const angle = i * Math.PI / 12; ctx.save(); ctx.rotate(angle); ctx.strokeStyle = "rgba(232,170,76,.15)"; ctx.lineWidth = 1; ctx.beginPath(); ctx.ellipse(0, -radius * .65, radius * .18, radius * .38, 0, 0, Math.PI * 2); ctx.stroke(); ctx.restore(); } ctx.beginPath(); ctx.arc(0, 0, radius * .75, 0, Math.PI * 2); ctx.strokeStyle = "rgba(255,193,91,.15)"; ctx.stroke(); ctx.restore(); // Decorative hanging lights for (let i = 0; i < 30; i++) { const x = i * W / 29; const y = 10 + Math.sin(i * .5) * 12; ellipse(x, y, 2, 2, "#f2c36e"); if (i % 3 === 0) { glow(x, y, 18, "rgba(255,175,60,.12)"); } } } function drawDiya() { const cx = W / 2; const cy = H * .70; const width = Math.min(W * .52, 390); const height = width * .27; // Surface reflection if (lit) { glow(cx, cy + height * .3, width * .8, "rgba(255,135,25,.18)"); } // Shadow ellipse(cx, cy + height * .45, width * .65, height * .18, "rgba(0,0,0,.45)"); // Lamp bowl ctx.save(); const brass = ctx.createLinearGradient( cx - width / 2, cy, cx + width / 2, cy ); brass.addColorStop(0, "#6a290a"); brass.addColorStop(.18, "#d98b2c"); brass.addColorStop(.35, "#ffd777"); brass.addColorStop(.55, "#a54c12"); brass.addColorStop(.78, "#f4bd51"); brass.addColorStop(1, "#57200b"); ctx.beginPath(); ctx.moveTo(cx - width * .55, cy); ctx.quadraticCurveTo( cx - width * .48, cy + height * .65, cx, cy + height ); ctx.quadraticCurveTo( cx + width * .48, cy + height * .65, cx + width * .55, cy ); ctx.quadraticCurveTo( cx, cy + height * .25, cx - width * .55, cy ); ctx.fillStyle = brass; ctx.fill(); // Decorative rim ctx.beginPath(); ctx.ellipse(cx, cy, width * .55, height * .15, 0, 0, Math.PI * 2); ctx.fillStyle = "#f4c75f"; ctx.fill(); ctx.strokeStyle = "#ffdf8a"; ctx.lineWidth = 2; ctx.stroke(); // Engraved details for (let i = -4; i <= 4; i++) { const x = cx + i * width * .105; ellipse(x, cy + height * .38, 3, 3, "#7a350f"); ellipse(x, cy + height * .38 - 2, 2, 2, "#ffdb83"); } // Oil ellipse(cx, cy - 1, width * .35, height * .09, "#5b290e"); // Wick ctx.strokeStyle = "#21130b"; ctx.lineWidth = 7; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(cx, cy - height * .32); ctx.stroke(); ctx.restore(); if (lit) { drawFlame(cx, cy - height * .38); } } function drawFlame(x, y) { const flicker = Math.sin(time * 12) * 4; const sway = Math.sin(time * 8) * 7; // Outer flame glow glow(x, y - 25, 100, "rgba(255,115,10,.28)"); ctx.save(); ctx.translate(x, y); ctx.rotate(sway * .025); // Outer flame ctx.beginPath(); ctx.moveTo(0, 0); ctx.bezierCurveTo( -40, -25, -30, -65 - flicker, 0, -105 - flicker ); ctx.bezierCurveTo( 25, -70 + flicker, 40, -30, 0, 0 ); const outer = ctx.createLinearGradient( 0, 0, 0, -110 ); outer.addColorStop(0, "#ff5a00"); outer.addColorStop(.4, "#ff9b17"); outer.addColorStop(.75, "#ffd449"); outer.addColorStop(1, "#fff2b0"); ctx.fillStyle = outer; ctx.fill(); // Inner flame ctx.beginPath(); ctx.moveTo(0, -5); ctx.bezierCurveTo( -17, -25, -12, -55, 0, -75 - flicker * .5 ); ctx.bezierCurveTo( 15, -45, 20, -20, 0, -5 ); ctx.fillStyle = "#fff8c9"; ctx.fill(); ctx.restore(); } function createSpark() { const cx = W / 2; const cy = H * .58; sparks.push({ x: cx + (Math.random() - .5) * 100, y: cy, vx: (Math.random() - .5) * 30, vy: -30 - Math.random() * 80, life: 1, size: 1 + Math.random() * 3 }); } function drawSparks(dt) { if (lit && Math.random() < .35) { createSpark(); } sparks.forEach(function(s) { s.x += s.vx * dt; s.y += s.vy * dt; s.vy -= 5 * dt; s.life -= dt * .35; ctx.globalAlpha = Math.max(0, s.life); glow(s.x, s.y, s.size * 5, "rgba(255,190,70,.5)"); ellipse(s.x, s.y, s.size, s.size, "#ffd98a"); }); ctx.globalAlpha = 1; for (let i = sparks.length - 1; i >= 0; i--) { if (sparks[i].life <= 0) { sparks.splice(i, 1); } } } function draw() { const now = performance.now(); const dt = lastTime ? Math.min((now - lastTime) / 1000, .05) : 0; lastTime = now; time += dt; ctx.clearRect(0, 0, W, H); background(); drawDiya(); drawSparks(dt); requestAnimationFrame(draw); } lightButton.addEventListener("click", function() { lit = !lit; scene.classList.toggle("lit", lit); lightButton.textContent = lit ? "LIGHT THE DIYA ✨" : "LIGHT THE DIYA 🪔"; }); requestAnimationFrame(draw);
terminal
JavaScript Console
Preview
Clear
close
›
Run