Frontend Forever App
We have a mobile app for you to download and use. And you can unlock many features in the app.
Get it now
Intall Later
Run
HTML
CSS
Javascript
Output
Document
@charset "UTF-8"; @import url(https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800); *, :after, :before { box-sizing: border-box; padding: 0; margin: 0; } body, html { margin: 0; padding: 0px; height: 100%; display: flex; justify-content: center; align-items: center; background: #000000; } #wave-grid { display: grid; width: 100%; height: 100%; } .dot-point { width: 20px; height: 10px; background: linear-gradient(to bottom, white, rgba(255, 255, 255, 0.5)); opacity: 0.5; transition: background 0.3s; cursor: crosshair; } .dot-point:hover { background: linear-gradient(to bottom, #718096, white); /* Slate-like hover effect */ } .cursor-crosshair { cursor: crosshair; } .flex { display: flex; } .justify-center { justify-content: center; } .items-center { align-items: center; }
console.log("Event Fired")] function updateGridDimensions() { if (window.innerWidth <= 768) { return { gridWidth: 11, gridHeight: 23 }; } else if (window.innerWidth <= 1024) { return { gridWidth: 25, gridHeight: 40 }; } else { return { gridWidth: 35, gridHeight: 23 }; } } function createDotGrid(gridWidth, gridHeight) { const app = document.getElementById("app"); const grid = document.createElement("div"); grid.id = "wave-grid"; grid.style.gridTemplateColumns = `repeat(${gridWidth}, 1fr)`; let index = 0; for (let i = 0; i < gridWidth; i++) { for (let j = 0; j < gridHeight; j++) { const dotWrapper = document.createElement("div"); dotWrapper.className = "cursor-crosshair"; dotWrapper.dataset.index = index; const dot = document.createElement("div"); dot.className = "dot-point"; dot.dataset.index = index; dotWrapper.appendChild(dot); grid.appendChild(dotWrapper); index++; } } app.innerHTML = ""; app.appendChild(grid); autoAnimateDots(gridWidth, gridHeight); } function autoAnimateDots(gridWidth, gridHeight) { const timeline = anime.timeline({ loop: true, easing: "easeInOutSine", }); timeline.add({ targets: ".dot-point", translateX: [ { value: 20, duration: 500 }, { value: 0, duration: 500 }, ], delay: anime.stagger(50, { grid: [gridWidth, gridHeight], from: "center" }), }); timeline.add({ targets: ".dot-point", translateY: [ { value: 20, duration: 500 }, { value: 0, duration: 500 }, ], delay: anime.stagger(50, { grid: [gridWidth, gridHeight], from: "center" }), }); } let { gridWidth, gridHeight } = updateGridDimensions(); createDotGrid(gridWidth, gridHeight); window.addEventListener("resize", () => { const dimensions = updateGridDimensions(); gridWidth = dimensions.gridWidth; gridHeight = dimensions.gridHeight; createDotGrid(gridWidth, gridHeight); });