← Назад к вопросам

Что такое repaint?

2.0 Middle🔥 141 комментариев
#Браузер и сетевые технологии#Оптимизация и производительность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое repaint?

Repaint (перерисовка) — это процесс, при котором браузер переносит пиксели на экран после изменения внешних свойств элемента (цвет, тень, видимость), не меняя его размеры и положение. Это критическое понимание для оптимизации производительности веб-приложений.

Различие: reflow vs repaint

Это два различных процесса, которые часто путают:

Reflow (перекомпоновка):

  • Пересчёт макета (layout) документа
  • Определение размеров и положения элементов
  • Затрагивает DOM модель
  • Более дорогой процесс
  • Влечёт за собой repaint
// Операции, вызывающие reflow:
element.width = 100;           // изменение размера
element.style.marginLeft = 10; // изменение позиции
element.offsetWidth;           // чтение размера
window.innerWidth;             // получение высоты окна

Repaint (перерисовка):

  • Перерисовка внешнего вида элемента
  • Не меняет макет (layout)
  • Менее дорогой процесс
  • Может происходить без reflow
// Операции, вызывающие repaint (без reflow):
element.style.color = 'red';           // цвет текста
element.style.backgroundColor = 'blue'; // цвет фона
element.style.opacity = 0.5;           // прозрачность
element.style.boxShadow = '0 0 5px';   // тень
element.style.borderColor = 'red';     // цвет границы

Как браузер обновляет экран

1. JavaScript выполнение
2. Parsing (парсинг CSS, HTML)
3. Render Tree (дерево рендеринга)
4. Layout (reflow) — вычисление размеров/позиций
5. Paint (repaint) — отрисовка пикселей
6. Composite (композиция слоёв)
7. Отображение на экране

Практические примеры repaint

Пример 1: Простое изменение цвета (только repaint)

// ✅ Этот код вызывает только repaint (быстро)
const element = document.getElementById('box');
element.style.color = 'blue';        // repaint
element.style.backgroundColor = 'yellow'; // repaint
element.style.opacity = 0.8;        // repaint

// ❌ Этот код вызывает reflow + repaint (медленнее)
element.style.width = '100px';       // reflow
element.style.height = '50px';       // reflow
element.style.color = 'red';         // repaint

Пример 2: Изменение видимости

// ✅ Только repaint (используется display в DOM)
element.style.display = 'none';      // reflow (переносит элемент)
element.style.visibility = 'hidden'; // repaint (скрывает, место занято)
element.style.opacity = '0';         // repaint (прозрачность)

Пример 3: Анимация (repaint vs reflow)

// ❌ Плохо — вызывает reflow при каждом шаге
function animateBadly() {
  for (let i = 0; i < 100; i++) {
    element.style.left = i + 'px';   // reflow + repaint
  }
}

// ✅ Хорошо — только repaint
function animateWell() {
  for (let i = 0; i < 100; i++) {
    element.style.backgroundColor = `rgb(${i}, 0, 0)`; // repaint
  }
}

// ✅ Лучше всего — используй CSS анимацию
// CSS анимация оптимизирована браузером
element.style.animation = 'moveRight 1s ease';

Операции, вызывающие repaint (но НЕ reflow)

const element = document.getElementById('box');

// Цвет и эффекты
element.style.color = 'blue';
element.style.backgroundColor = 'red';
element.style.borderColor = 'green';

// Прозрачность
element.style.opacity = 0.5;

// Тени (не меняют макет)
element.style.boxShadow = '0 10px 30px rgba(0,0,0,0.3)';
element.style.textShadow = '2px 2px 4px rgba(0,0,0,0.5)';

// Трансформации (используют GPU)
element.style.transform = 'scale(1.2)';
element.style.transform = 'rotate(45deg)';

// Фильтры
element.style.filter = 'blur(5px)';

Операции, вызывающие reflow (и, следовательно, repaint)

const element = document.getElementById('box');

// Размеры
element.style.width = '200px';    // reflow
element.style.height = '100px';   // reflow
element.style.padding = '10px';   // reflow

// Позиция
element.style.left = '50px';      // reflow
element.style.top = '100px';      // reflow

// Границы
element.style.borderWidth = '2px'; // reflow

// Чтение свойств (триггер reflow)
const width = element.offsetWidth;   // reflow
const height = element.clientHeight; // reflow
const top = element.offsetTop;      // reflow

Лучшие практики для оптимизации

1. Батчинг (группировка изменений)

// ❌ Плохо: множественные reflow
element.style.width = '100px';   // reflow
element.style.height = '50px';   // reflow
element.style.padding = '10px';  // reflow

// ✅ Хорошо: один reflow
element.style.cssText = 'width: 100px; height: 50px; padding: 10px;';

// ✅ Или используй класс
element.classList.add('my-style'); // один reflow

2. Избегай чтения и записи в перемешку

// ❌ Плохо: чередование чтения и записи
element.style.left = '50px';        // reflow
const left = element.offsetLeft;    // reflow
element.style.top = '100px';       // reflow
const top = element.offsetTop;      // reflow

// ✅ Хорошо: сначала читай, потом пиши
const left = element.offsetLeft;    // reflow (один раз)
const top = element.offsetTop;      // reflow (один раз)
element.style.left = left + 50 + 'px';
element.style.top = top + 100 + 'px';

3. Используй transform вместо top/left

// ❌ Вызывает reflow при каждом кадре
function animatePosition() {
  let x = 0;
  setInterval(() => {
    x += 5;
    element.style.left = x + 'px'; // reflow
  }, 16);
}

// ✅ Только repaint (или даже GPU acceleration)
function animatePositionOptimized() {
  let x = 0;
  setInterval(() => {
    x += 5;
    element.style.transform = `translateX(${x}px)`; // repaint (быстрее)
  }, 16);
}

4. Используй requestAnimationFrame

// ✅ Синхронизируется с refresh rate браузера
function animate() {
  requestAnimationFrame(() => {
    element.style.backgroundColor = 'blue'; // repaint
    // или
    element.style.transform = 'scale(1.1)'; // repaint
  });
}

5. Дублируй элемент для сложных операций

// ❌ Множественные изменения = множественные reflow
for (let i = 0; i < 1000; i++) {
  const item = document.createElement('div');
  item.textContent = i;
  parent.appendChild(item); // reflow для каждого элемента
}

// ✅ Один reflow для всех элементов
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const item = document.createElement('div');
  item.textContent = i;
  fragment.appendChild(item); // в памяти, без reflow
}
parent.appendChild(fragment); // один reflow

Профилирование repaint

// Chrome DevTools Performance:
// 1. Откройте DevTools (F12)
// 2. Перейдите на вкладку Performance
// 3. Нажмите Record
// 4. Выполните операции
// 5. Нажмите Stop
// 6. Посмотрите на временную шкалу (Paint события)

// Или используй Performance API:
performance.mark('start');
element.style.color = 'red';
performance.mark('end');
performance.measure('paint', 'start', 'end');

Когда repaint неизбежен

// Некоторые изменения всегда требуют repaint:
// 1. Изменение фонового цвета
// 2. Изменение цвета текста
// 3. Изменение границ
// 4. Изменение теней
// 5. Изменение фильтров
// 6. Изменение видимости (display: none это reflow)

// Но это всё равно быстрее, чем reflow!

Вывод: понимание разницы между repaint и reflow критически важно для написания высокопроизводительного кода. Используй инструменты профилирования браузера для анализа и оптимизации своих приложений.

Что такое repaint? | PrepBro