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>Fireflies in a jar</title> </head> <body> <!-- Start your code here --> <div class="firefly-app" id="fireflyApp"> <div class="firefly-scene" id="fireflyScene"> <div class="forest-backdrop"></div> <div class="forest-shade"></div> <div class="moonlight"></div> <div class="scene-heading"> <span class="eyebrow">A LITTLE MAGIC AFTER DARK</span> <h1>Fireflies <em>in a Jar.</em></h1> <p>Some of the smallest things make the night beautiful.</p> </div> <div class="jar-stage"> <div class="jar-shadow"></div> <div class="jar" id="jar"> <div class="jar-lid"> <div class="lid-top"></div> <div class="lid-body"></div> </div> <div class="jar-neck"></div> <div class="jar-body"> <div class="jar-ambient-glow"></div> <canvas id="fireflyCanvas" aria-label="Animated golden fireflies" ></canvas> <div class="glass-shine glass-shine-left"></div> <div class="glass-shine glass-shine-right"></div> <div class="glass-bottom"></div> </div> </div> </div> <div class="wooden-table"></div> <div class="scene-footer"> <span>THE MAGIC OF ORDINARY MOMENTS</span> <span>EST. AFTER SUNSET</span> </div> </div> <div class="firefly-controls"> <div class="control-brand"> <div class="brand-symbol">✦</div> <div> <strong>Firefly Garden</strong> <small>An interactive nighttime scene</small> </div> </div> <div class="control-field"> <label for="fireflyCount">Fireflies</label> <input type="range" id="fireflyCount" min="5" max="35" value="20" > <output id="countOutput">20</output> </div> <div class="control-field"> <label for="glowStrength">Glow</label> <input type="range" id="glowStrength" min="20" max="100" value="75" > <output id="glowOutput">75%</output> </div> <button class="release-button" id="releaseButton" type="button" > Release Fireflies </button> <button class="reset-button" id="resetButton" type="button" > Reset </button> </div> <p class="scene-note" id="sceneNote" aria-live="polite"> Twenty little lights are glowing quietly inside the jar. </p> </div> <!-- End your code here --> </body> </html>
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,500;1,500&display=swap'); * { box-sizing: border-box; } body { margin: 0; background: #101813; color: #fff; font-family: 'DM Sans', sans-serif; } button, input { font: inherit; } button:focus-visible, input:focus-visible { outline: 3px solid #ffe0a0; outline-offset: 4px; } .firefly-app { min-height: 100vh; padding: 20px; } /* MAIN SCENE */ .firefly-scene { position: relative; isolation: isolate; overflow: hidden; height: 650px; border-radius: 18px; background: #101f1b; } /* WOODLAND BACKGROUND */ .forest-backdrop { position: absolute; inset: 0; background: radial-gradient( ellipse at 50% 30%, #345346 0%, #192f2a 48%, #0a1715 100% ); } /* SOFT FOREST SILHOUETTES */ .forest-backdrop::before { content: ""; position: absolute; inset: 0; background: radial-gradient( ellipse at 5% 65%, #081711 0%, transparent 40% ), radial-gradient( ellipse at 94% 65%, #081711 0%, transparent 38% ), linear-gradient( 90deg, #0b1c17 0%, transparent 25%, transparent 75%, #0b1c17 100% ); } /* NIGHT ATMOSPHERE */ .forest-shade { position: absolute; inset: 0; background: linear-gradient( to bottom, rgba(3,10,9,.45), transparent 35%, rgba(4,11,9,.65) 100% ); } .moonlight { position: absolute; width: 500px; height: 500px; left: 50%; top: 18%; transform: translateX(-50%); background: radial-gradient( circle, rgba(170,205,175,.13), transparent 65% ); pointer-events: none; } /* TITLE */ .scene-heading { position: absolute; z-index: 5; top: 45px; left: 0; right: 0; text-align: center; padding: 0 20px; } .eyebrow { color: #e5c894; font-size: 10px; font-weight: 700; letter-spacing: 3px; } .scene-heading h1 { margin: 12px 0; font-family: 'Playfair Display', serif; font-size: clamp(38px, 5vw, 62px); font-weight: 500; letter-spacing: -1.5px; } .scene-heading h1 em { color: #f4cf91; font-weight: 500; } .scene-heading p { margin: 0; color: #e2e9df; font-size: 14px; } /* JAR STAGE */ .jar-stage { position: absolute; z-index: 3; width: 300px; height: 365px; left: 50%; bottom: 69px; transform: translateX(-50%); } .jar-shadow { position: absolute; width: 290px; height: 34px; left: 5px; bottom: -7px; border-radius: 50%; background: rgba(0,0,0,.65); filter: blur(10px); } /* JAR */ .jar { position: absolute; width: 220px; height: 345px; left: 40px; bottom: 0; transition: transform .5s ease; } .jar-lid { position: absolute; z-index: 6; top: 4px; left: 19px; width: 182px; height: 40px; transition: transform .65s ease, opacity .65s ease; } .lid-top { position: absolute; top: 0; left: 4px; right: 4px; height: 12px; border-radius: 50%; background: linear-gradient( #a8a38b, #5f6659 ); border: 1px solid #c6c3a7; } .lid-body { position: absolute; top: 6px; width: 100%; height: 30px; border-radius: 5px 5px 10px 10px; background: repeating-linear-gradient( 90deg, transparent 0 6px, rgba(0,0,0,.12) 7px 8px ), linear-gradient( 90deg, #454e45, #9d9f8a 25%, #777f6f 70%, #343e38 ); border: 1px solid rgba(255,255,255,.25); box-shadow: 0 4px 7px rgba(0,0,0,.3); } .jar-neck { position: absolute; top: 30px; left: 27px; width: 166px; height: 35px; border-radius: 9px; border: 3px solid rgba(190,220,205,.35); background: rgba(150,190,170,.07); } /* GLASS BODY */ .jar-body { position: absolute; top: 54px; left: 0; width: 220px; height: 290px; overflow: hidden; border-radius: 38px 38px 35px 35px / 30px 30px 42px 42px; border: 3px solid rgba(195,225,210,.38); background: linear-gradient( 90deg, rgba(210,245,225,.12), rgba(15,45,35,.08) 20%, rgba(12,35,27,.1) 80%, rgba(210,245,225,.15) ); box-shadow: inset 9px 0 12px rgba(220,255,235,.08), inset -8px 0 12px rgba(220,255,235,.08), inset 0 -12px 14px rgba(255,220,125,.07), 0 0 30px rgba(255,194,90,.08); } /* AMBIENT JAR GLOW */ .jar-ambient-glow { position: absolute; inset: 20px; border-radius: 50%; background: radial-gradient( ellipse, rgba(255,190,80,.12), transparent 72% ); pointer-events: none; } /* FIREFLY CANVAS */ #fireflyCanvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; } /* GLASS REFLECTIONS */ .glass-shine { position: absolute; pointer-events: none; } .glass-shine-left { left: 12px; top: 26px; width: 18px; height: 185px; border-radius: 50%; background: linear-gradient( to bottom, transparent, rgba(240,255,245,.3) 25%, rgba(240,255,245,.12) 75%, transparent ); transform: rotate(5deg); } .glass-shine-right { right: 13px; top: 40px; width: 8px; height: 130px; border-radius: 50%; background: rgba(230,255,240,.16); transform: rotate(-6deg); } .glass-bottom { position: absolute; bottom: 7px; left: 14px; right: 14px; height: 18px; border-bottom: 3px solid rgba(220,245,225,.28); border-radius: 50%; } /* OPEN JAR */ .jar.open .jar-lid { transform: translate(50px, -45px) rotate(24deg); opacity: .9; } /* TABLE */ .wooden-table { position: absolute; z-index: 2; bottom: 0; left: 0; right: 0; height: 83px; background: repeating-linear-gradient( 3deg, transparent 0 24px, rgba(0,0,0,.09) 25px 26px ), linear-gradient( to bottom, #5a3c2a, #33251d 65%, #251b16 ); border-top: 7px solid #76513a; box-shadow: 0 -8px 20px rgba(0,0,0,.3); } /* FOOTER */ .scene-footer { position: absolute; z-index: 5; bottom: 22px; left: 30px; right: 30px; display: flex; justify-content: space-between; gap: 15px; color: #e6d9c8; font-size: 9px; font-weight: 700; letter-spacing: 1.5px; } /* CONTROLS */ .firefly-controls { display: flex; align-items: center; flex-wrap: wrap; gap: 22px; margin-top: 16px; padding: 20px 24px; border: 1px solid #45574a; border-radius: 14px; background: #1b2922; } .control-brand { display: flex; align-items: center; gap: 12px; margin-right: auto; } .brand-symbol { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; background: #3c4831; color: #ffd38b; font-size: 25px; } .control-brand strong { display: block; font-size: 14px; } .control-brand small { display: block; margin-top: 4px; color: #cbd8cc; font-size: 11px; } .control-field { display: flex; align-items: center; gap: 10px; } .control-field label { font-size: 12px; font-weight: 700; } .control-field input { width: 110px; accent-color: #f4c579; } .control-field output { min-width: 34px; font-size: 12px; font-weight: 700; color: #ffdb9b; } .release-button, .reset-button { min-height: 44px; padding: 11px 17px; border-radius: 8px; font-size: 12px; font-weight: 700; cursor: pointer; } .release-button { border: 1px solid #f4cb8d; background: #f4cb8d; color: #2d2418; } .release-button:hover { background: #ffe0ad; } .reset-button { border: 1px solid #acbeae; background: transparent; color: white; } .reset-button:hover { background: #344539; } .scene-note { margin: 14px 5px 0; text-align: center; color: #c6d2c7; font-size: 12px; } /* RESPONSIVE */ @media (max-width: 700px) { .firefly-app { padding: 10px; } .firefly-scene { height: 620px; } .scene-heading { top: 35px; } .scene-heading h1 { font-size: 42px; } .scene-heading p { font-size: 12px; } .firefly-controls { gap: 18px; } .control-brand { width: 100%; } } @media (max-width: 420px) { .scene-heading h1 { font-size: 36px; } .eyebrow { font-size: 9px; letter-spacing: 2px; } .jar-stage { transform: translateX(-50%) scale(.9); transform-origin: center bottom; } .scene-footer { left: 15px; right: 15px; font-size: 7px; letter-spacing: .5px; } .control-field { width: 100%; } .control-field input { flex: 1; min-width: 0; } } /* REDUCED MOTION */ @media (prefers-reduced-motion: reduce) { .jar-lid { transition: none; } }
(function () { "use strict"; var root = document.getElementById("fireflyApp"); if (!root) return; var canvas = document.getElementById("fireflyCanvas"); var jar = document.getElementById("jar"); var scene = document.getElementById("fireflyScene"); var countInput = document.getElementById("fireflyCount"); var glowInput = document.getElementById("glowStrength"); var countOutput = document.getElementById("countOutput"); var glowOutput = document.getElementById("glowOutput"); var releaseButton = document.getElementById("releaseButton"); var resetButton = document.getElementById("resetButton"); var sceneNote = document.getElementById("sceneNote"); var ctx = canvas.getContext("2d"); if (!ctx) return; var width = 214; var height = 284; var particles = []; var released = false; var running = true; var lastFrame = 0; var frameInterval = 1000 / 30; var animationId = 0; var reducedMotion = window.matchMedia( "(prefers-reduced-motion: reduce)" ); function random(min, max) { return Math.random() * (max - min) + min; } function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } function setupCanvas() { var ratio = Math.min(window.devicePixelRatio || 1, 1.5); canvas.width = Math.round(width * ratio); canvas.height = Math.round(height * ratio); ctx.setTransform(ratio, 0, 0, ratio, 0, 0); } function makeParticle() { return { x: random(25, width - 25), y: random(35, height - 35), vx: random(-0.35, 0.35), vy: random(-0.3, 0.3), size: random(1.3, 2.6), phase: random(0, Math.PI * 2), speed: random(0.012, 0.035), brightness: random(0.6, 1), outside: false, escaping: false }; } function syncParticles() { var count = Number(countInput.value); count = clamp(count, 5, 35); while (particles.length < count) { particles.push(makeParticle()); } if (particles.length > count) { particles.length = count; } countOutput.textContent = String(count); } function drawFirefly(x, y, size, alpha, glow) { var halo = size * (5 + glow * 5); var gradient = ctx.createRadialGradient( x, y, 0, x, y, halo ); gradient.addColorStop( 0, "rgba(255,245,170," + (alpha * 0.9) + ")" ); gradient.addColorStop( 0.15, "rgba(255,210,85," + (alpha * 0.45) + ")" ); gradient.addColorStop( 1, "rgba(255,180,50,0)" ); ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(x, y, halo, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = "rgba(255,248,188," + alpha + ")"; ctx.beginPath(); ctx.arc(x, y, size, 0, Math.PI * 2); ctx.fill(); } function updateParticle(p, delta) { p.phase += p.speed * delta; p.x += p.vx * delta; p.y += p.vy * delta; p.vx += Math.sin(p.phase) * 0.005 * delta; p.vy += Math.cos(p.phase * 0.8) * 0.004 * delta; p.vx = clamp(p.vx, -0.5, 0.5); p.vy = clamp(p.vy, -0.5, 0.5); if (p.x < 16 || p.x > width - 16) { p.vx *= -1; p.x = clamp(p.x, 16, width - 16); } if (p.y < 20 || p.y > height - 20) { p.vy *= -1; p.y = clamp(p.y, 20, height - 20); } } function drawScene(time, delta) { ctx.clearRect(0, 0, width, height); var glow = Number(glowInput.value) / 100; for (var i = 0; i < particles.length; i++) { var p = particles[i]; if (!reducedMotion.matches) { updateParticle(p, delta); } var pulse = 0.7 + Math.sin(time * 0.0018 + p.phase) * 0.3; var alpha = clamp(p.brightness * pulse * glow, 0.1, 1); drawFirefly(p.x, p.y, p.size, alpha, glow); } } function animate(time) { if (!running) return; animationId = requestAnimationFrame(animate); var elapsed = time - lastFrame; if (elapsed < frameInterval) return; lastFrame = time - (elapsed % frameInterval); var delta = Math.min(elapsed / 33.33, 2); drawScene(time, delta); } function startAnimation() { if (!running) { running = true; } cancelAnimationFrame(animationId); lastFrame = 0; if (reducedMotion.matches) { drawScene(0, 0); } else { animationId = requestAnimationFrame(animate); } } function stopAnimation() { running = false; cancelAnimationFrame(animationId); } function releaseFireflies() { released = !released; jar.classList.toggle("open", released); if (released) { releaseButton.textContent = "Gather Fireflies"; sceneNote.textContent = "The lid is open. The fireflies are enjoying the evening."; } else { releaseButton.textContent = "Release Fireflies"; sceneNote.textContent = "The fireflies are safely back in their glowing jar."; } } function updateGlow() { glowOutput.textContent = glowInput.value + "%"; if (reducedMotion.matches) { drawScene(0, 0); } } function resetScene() { released = false; countInput.value = 20; glowInput.value = 75; jar.classList.remove("open"); releaseButton.textContent = "Release Fireflies"; sceneNote.textContent = "Twenty little lights are glowing quietly inside the jar."; particles = []; syncParticles(); updateGlow(); if (reducedMotion.matches) { drawScene(0, 0); } } countInput.addEventListener("input", function () { syncParticles(); if (reducedMotion.matches) { drawScene(0, 0); } }); glowInput.addEventListener("input", updateGlow); releaseButton.addEventListener("click", releaseFireflies); resetButton.addEventListener("click", resetScene); document.addEventListener("visibilitychange", function () { if (document.hidden) { stopAnimation(); } else { startAnimation(); } }); if (reducedMotion.addEventListener) { reducedMotion.addEventListener("change", startAnimation); } setupCanvas(); syncParticles(); updateGlow(); startAnimation(); })();
terminal
JavaScript Console
Preview
Clear
close
›
Run