← JS

Marquee Text

Бегущая строка с плавной анимацией — текст непрерывно движется слева направо. Поддерживает паузу при наведении, настраиваемую скорость и несколько строк с разным направлением. Чистый JS без библиотек.

(function(){
    const root = document.createElement('div');
    document.body.appendChild(root);
    const container = root;

    try {
const style = document.createElement('style');
style.textContent = `
  .marquee-wrap {
    background: #050505;
    padding: 30px 0;
    font-family: monospace;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .marquee-row {
    display: flex;
    overflow: hidden;
    position: relative;
  }

  .marquee-row::before,
  .marquee-row::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    width: 60px;
    z-index: 2;
    pointer-events: none;
  }
  .marquee-row::before {
    left: 0;
    background: linear-gradient(to right, #050505, transparent);
  }
  .marquee-row::after {
    right: 0;
    background: linear-gradient(to left, #050505, transparent);
  }

  .marquee-track {
    display: flex;
    gap: 0;
    will-change: transform;
  }

  .marquee-track.paused {
    animation-play-state: paused !important;
  }

  .marquee-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 16px;
    white-space: nowrap;
    font-size: 15px;
    font-weight: bold;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  .marquee-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    flex-shrink: 0;
  }

  .marquee-row-1 .marquee-item { color: #00ff9c; }
  .marquee-row-1 .marquee-dot  { background: #00ff9c; }

  .marquee-row-2 .marquee-item { color: #a78bfa; }
  .marquee-row-2 .marquee-dot  { background: #a78bfa; }

  .marquee-row-3 .marquee-item {
    color: transparent;
    -webkit-text-stroke: 1px rgba(255,255,255,0.25);
  }
  .marquee-row-3 .marquee-dot { background: rgba(255,255,255,0.2); }

  @keyframes marquee-left {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
  }
  @keyframes marquee-right {
    from { transform: translateX(-50%); }
    to   { transform: translateX(0); }
  }
`;
document.head.appendChild(style);

const rows = [
  {
    cls: 'marquee-row-1',
    direction: 'left',
    speed: 28,
    items: ['JavaScript', 'HTML', 'CSS', 'PHP', 'React', 'Node.js', 'Canvas', 'WebGL'],
  },
  {
    cls: 'marquee-row-2',
    direction: 'right',
    speed: 22,
    items: ['Snippets', 'Components', 'Utilities', 'Animations', 'Effects', 'Micro Apps'],
  },
  {
    cls: 'marquee-row-3',
    direction: 'left',
    speed: 35,
    items: ['Copy', 'Paste', 'Build', 'Ship', 'Create', 'Deploy', 'Code', 'Design'],
  },
];

const wrap = document.createElement('div');
wrap.className = 'marquee-wrap';

rows.forEach(row => {
  const rowEl = document.createElement('div');
  rowEl.className = `marquee-row ${row.cls}`;

  const track = document.createElement('div');
  track.className = 'marquee-track';

  // Дублируем items для бесшовного повтора
  const allItems = [...row.items, ...row.items];
  allItems.forEach(text => {
    const item = document.createElement('div');
    item.className = 'marquee-item';
    item.innerHTML = `<span class="marquee-dot"></span>${text}`;
    track.appendChild(item);
  });

  // Анимация через JS для точного контроля
  let offset = row.direction === 'right' ? -50 : 0;
  const trackWidth = row.items.length * 160;
  let paused = false;
  let animId;

  function animate() {
    if (!paused) {
      if (row.direction === 'left') {
        offset -= row.speed / 60 / row.items.length;
        if (offset <= -50) offset = 0;
      } else {
        offset += row.speed / 60 / row.items.length;
        if (offset >= 0) offset = -50;
      }
      track.style.transform = `translateX(${offset}%)`;
    }
    animId = requestAnimationFrame(animate);
  }

  animate();

  // Пауза при наведении
  rowEl.addEventListener('mouseenter', () => { paused = true; });
  rowEl.addEventListener('mouseleave', () => { paused = false; });

  rowEl.appendChild(track);
  wrap.appendChild(rowEl);
});

container.appendChild(wrap);
    } catch(e){
        console.error(e);
    }
})();

👁 9