Flowing ideas across a page
07:48 12 Jul 2026

I want to make a board and inside the board will be different texts flowing across a page with a floating animation, but the "texts" keep overlapping each other. My original idea was that each idea is wrapped in a bubble with a boundary so that the don't bleed into one another and that they spawn randomly without leaving a significant empty gap between each idea.

How it looks right now:

.opinions-section {
        margin-top: 18px;
        padding-top: 8px;
      }

      .opinions-section h3 {
        margin: 0 0 14px;
        font-size: 0.9rem;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        color: var(--muted);
        font-weight: 600;
      }

      .opinion-clouds {
        position: relative;
        min-height: 260px;
        border: 1px solid rgba(255, 255, 255, 0.1);
        border-radius: 28px;
        padding: 18px;
        overflow: hidden;
        background: rgba(255, 255, 255, 0.025);
        box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
      }

      .opinion-cloud {
        position: absolute;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 11px 16px;
        border-radius: 999px;
        border: 1px solid rgba(255, 255, 255, 0.16);
        background: rgba(255, 255, 255, 0.06);
        color: #eef2f7;
        font-size: 0.95rem;
        line-height: 1.2;
        box-shadow: 0 8px 20px rgba(0, 0, 0, 0.16);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        white-space: nowrap;
        will-change: left, top;
        max-width: calc(100% - 36px);
        overflow: hidden;
        text-overflow: ellipsis;
      }

      .opinion-cloud::before {
        content: '';
        position: absolute;
        inset: 2px;
        border-radius: inherit;
        border: 1px solid rgba(255, 255, 255, 0.05);
        pointer-events: none;
      }
 

Opinions

emotionally intelligent deeply thoughtful makes you feel seen comforting to be around genuinely kind-hearted appreciative compassionate one of the kindest people I know effortlessly warm has a beautiful way with people so easy to talk to makes kindness feel natural makes you feel safe unbelievably sincere
function initOpinionFlow() { if (animationFrameId) { cancelAnimationFrame(animationFrameId); } const areaWidth = opinionArea.clientWidth; const areaHeight = opinionArea.clientHeight; const laneGap = 56; const laneCount = Math.max( 3, Math.min(5, Math.floor((areaHeight - 24) / laneGap) + 1), ); const lanes = Array.from( { length: laneCount }, (_, index) => 20 + index * laneGap, ); const bubbles = opinionClouds.map((cloud, index) => ({ el: cloud, lane: index % lanes.length, x: 0, y: lanes[index % lanes.length], speed: 0.45 + (index % 4) * 0.07, drift: 3 + (index % 3) * 2, phase: index * 0.95, width: 0, height: 0, reentryOffset: 36 + index * 48, })); function resetBubble(bubble) { bubble.width = bubble.el.offsetWidth; bubble.height = bubble.el.offsetHeight; bubble.x = areaWidth + bubble.reentryOffset; bubble.y = lanes[bubble.lane]; } function animate(now) { const height = opinionArea.clientHeight; bubbles.forEach((bubble) => { if (!bubble.width || !bubble.height) { bubble.width = bubble.el.offsetWidth; bubble.height = bubble.el.offsetHeight; } if (bubble.x < -bubble.width - 24) { resetBubble(bubble); } bubble.x -= bubble.speed; bubble.y = lanes[bubble.lane] + Math.sin(now * 0.0012 + bubble.phase) * bubble.drift; bubble.y = Math.max( 10, Math.min(height - bubble.height - 10, bubble.y), ); bubble.el.style.left = `${bubble.x}px`; bubble.el.style.top = `${bubble.y}px`; }); animationFrameId = requestAnimationFrame(animate); } bubbles.forEach(resetBubble); animationFrameId = requestAnimationFrame(animate); } window.addEventListener('load', () => { setMuted(true); initOpinionFlow(); }); window.addEventListener('resize', () => { initOpinionFlow(); });
javascript html css animation