Реалізація Glitch-ефекту на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація Glitch-ефекту на сайті
Середня
від 1 робочого дня до 3 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація ефекту Glitch на сайті

Glitch—цифровий артефакт як дизайн-прийм: горизонтальні зміщення частин зображення, хроматична аберація, мерехтіння, цифровий «зламаний екран». Застосовується на hover, при переходах сторінок, як анімація заголовків.

CSS Glitch для тексту

Чистий CSS через ::before/::after псевдоелементи з clip-path:

<h1 class="glitch" data-text="СИСТЕМА">СИСТЕМА</h1>
.glitch {
  position: relative;
  color: #fff;
  font-size: 80px;
  font-weight: 900;
  letter-spacing: 0.05em;
}

.glitch::before,
.glitch::after {
  content: attr(data-text);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.glitch::before {
  left: 2px;
  text-shadow: -2px 0 #ff0040;
  animation: glitch-1 3s infinite linear alternate-reverse;
}

.glitch::after {
  left: -2px;
  text-shadow: 2px 0 #00ffea;
  animation: glitch-2 2s infinite linear alternate-reverse;
}

@keyframes glitch-1 {
  0%   { clip-path: inset(20% 0 60% 0); }
  5%   { clip-path: inset(70% 0 1% 0); }
  10%  { clip-path: inset(40% 0 43% 0); }
  15%  { clip-path: inset(5% 0 80% 0); }
  20%  { clip-path: inset(60% 0 25% 0); }
  /* ... більшість кроків — порожні для нерегулярності */
  25%  { clip-path: inset(0 0 100% 0); }
  30%  { clip-path: inset(0 0 100% 0); }
  35%  { clip-path: inset(0 0 100% 0); }
  40%  { clip-path: inset(15% 0 55% 0); }
  45%  { clip-path: inset(0 0 100% 0); }
  50%  { clip-path: inset(0 0 100% 0); }
  55%  { clip-path: inset(85% 0 5% 0); }
  100% { clip-path: inset(0 0 100% 0); }
}

@keyframes glitch-2 {
  0%   { clip-path: inset(55% 0 30% 0); transform: translate(-2px); }
  10%  { clip-path: inset(10% 0 75% 0); transform: translate(2px); }
  20%  { clip-path: inset(0 0 100% 0); }
  30%  { clip-path: inset(90% 0 3% 0); transform: translate(-1px); }
  50%  { clip-path: inset(0 0 100% 0); }
  60%  { clip-path: inset(45% 0 40% 0); transform: translate(3px); }
  100% { clip-path: inset(0 0 100% 0); }
}

Glitch для зображень—хроматична аберація

Розділення RGB-каналів—найбільш впізнаваний ефект глітчу:

.glitch-image {
  position: relative;
  overflow: hidden;
}

.glitch-image img,
.glitch-image::before,
.glitch-image::after {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Червоний канал — зміщено вліво */
.glitch-image::before {
  content: '';
  background: inherit;
  background-image: var(--img);
  mix-blend-mode: screen;
  filter: url('#red-channel');  /* SVG фільтр: тільки червоний */
  animation: glitch-ca-r 4s steps(1) infinite;
}

/* Синій канал — зміщено вправо */
.glitch-image::after {
  content: '';
  background-image: var(--img);
  mix-blend-mode: screen;
  filter: url('#blue-channel');
  animation: glitch-ca-b 4s steps(1) infinite;
}

@keyframes glitch-ca-r {
  0%, 90%, 100% { transform: translate(0); clip-path: inset(0 0 100% 0); }
  92%  { transform: translate(-4px, 1px); clip-path: inset(30% 0 50% 0); }
  94%  { transform: translate(-6px, 0); clip-path: inset(10% 0 70% 0); }
  96%  { transform: translate(-3px, -1px); clip-path: inset(60% 0 20% 0); }
}

@keyframes glitch-ca-b {
  0%, 90%, 100% { transform: translate(0); clip-path: inset(0 0 100% 0); }
  92%  { transform: translate(4px, -1px); clip-path: inset(30% 0 50% 0); }
  94%  { transform: translate(6px, 0); clip-path: inset(10% 0 70% 0); }
  96%  { transform: translate(3px, 1px); clip-path: inset(60% 0 20% 0); }
}

SVG-фільтри для виділення каналів:

<svg style="position:absolute;width:0;height:0">
  <defs>
    <filter id="red-channel">
      <feColorMatrix type="matrix"
        values="1 0 0 0 0
                0 0 0 0 0
                0 0 0 0 0
                0 0 0 1 0"/>
    </filter>
    <filter id="blue-channel">
      <feColorMatrix type="matrix"
        values="0 0 0 0 0
                0 0 0 0 0
                0 0 1 0 0
                0 0 0 1 0"/>
    </filter>
  </defs>
</svg>

JavaScript Glitch—керований тригер

class GlitchEffect {
  private el: HTMLElement
  private isGlitching = false
  private timeouts: ReturnType<typeof setTimeout>[] = []

  constructor(el: HTMLElement) {
    this.el = el
  }

  trigger(duration = 600) {
    if (this.isGlitching) return
    this.isGlitching = true
    this.el.classList.add('is-glitching')

    // Кілька випадкових спалахів за час дії
    const flashes = Math.floor(Math.random() * 4) + 2

    for (let i = 0; i < flashes; i++) {
      const delay = Math.random() * duration * 0.7
      const flashDuration = Math.random() * 80 + 40

      this.timeouts.push(
        setTimeout(() => {
          this.el.classList.add('glitch-flash')
          this.el.style.setProperty('--glitch-x', `${(Math.random() - 0.5) * 10}px`)
          this.el.style.setProperty('--glitch-y', `${(Math.random() - 0.5) * 5}px`)

          setTimeout(() => {
            this.el.classList.remove('glitch-flash')
          }, flashDuration)
        }, delay)
      )
    }

    this.timeouts.push(
      setTimeout(() => {
        this.el.classList.remove('is-glitching')
        this.isGlitching = false
        this.timeouts = []
      }, duration)
    )
  }

  destroy() {
    this.timeouts.forEach(clearTimeout)
    this.el.classList.remove('is-glitching', 'glitch-flash')
  }
}

// Тригер на hover
document.querySelectorAll<HTMLElement>('[data-glitch]').forEach((el) => {
  const effect = new GlitchEffect(el)
  el.addEventListener('mouseenter', () => effect.trigger(800))
})

Canvas Glitch—зміщення рядків

Максимальна автентичність: випадкові рядки пікселів зміщуються горизонтально, імітуючи збій відеосигналу.

class CanvasGlitch {
  private canvas: HTMLCanvasElement
  private ctx: CanvasRenderingContext2D
  private source: HTMLImageElement | HTMLVideoElement
  private rafId: number | null = null

  constructor(source: HTMLImageElement | HTMLVideoElement) {
    this.source = source
    this.canvas = document.createElement('canvas')
    this.ctx = this.canvas.getContext('2d')!

    // Замінюємо source на canvas
    source.parentNode?.insertBefore(this.canvas, source)
    source.style.display = 'none'

    this.canvas.width = source instanceof HTMLImageElement
      ? source.naturalWidth
      : source.videoWidth
    this.canvas.height = source instanceof HTMLImageElement
      ? source.naturalHeight
      : source.videoHeight
  }

  renderFrame() {
    const { width, height } = this.canvas
    this.ctx.drawImage(this.source, 0, 0)

    // Випадкові рядки зміщуються
    const numSlices = Math.floor(Math.random() * 8) + 2

    for (let i = 0; i < numSlices; i++) {
      const y = Math.floor(Math.random() * height)
      const sliceHeight = Math.floor(Math.random() * 30) + 5
      const offset = (Math.random() - 0.5) * 40

      const imageData = this.ctx.getImageData(0, y, width, sliceHeight)
      this.ctx.putImageData(imageData, offset, y)
    }

    // Хроматична аберація — зміщення червоного каналу
    const imageData = this.ctx.getImageData(0, 0, width, height)
    const data = imageData.data

    for (let i = 0; i < data.length; i += 4) {
      const x = (i / 4) % width
      const y = Math.floor(i / 4 / width)
      const shift = 3  // пікселів

      if (x + shift < width) {
        const j = (y * width + x + shift) * 4
        data[i] = data[j]  // R канал з правої сторони
      }
    }

    this.ctx.putImageData(imageData, 0, 0)
  }

  startContinuous(fps = 8) {
    let lastTime = 0
    const interval = 1000 / fps

    const tick = (time: number) => {
      if (time - lastTime > interval) {
        this.renderFrame()
        lastTime = time
      }
      this.rafId = requestAnimationFrame(tick)
    }

    this.rafId = requestAnimationFrame(tick)
  }

  destroy() {
    if (this.rafId) cancelAnimationFrame(this.rafId)
  }
}

Терміни

CSS glitch на тексті з hover — 4–6 годин. Хроматична аберація для зображень + JS-тригер — 1–2 дні. Canvas glitch зі зміщенням рядків — 2–3 дні.