\n\n\n\n\n

Content

\n \n\n```\n\n## Фаза 2: Style Calculation\n\n### Что происходит\n\nБраузер матчит селекторы CSS и вычисляет стили\n\n### Как это влияет на код\n\n```css\n/* ПЛОХО: сложные селекторы медленнее */\nbody > div > section > article > .container > p { color: red; }\n\n/* ХОРОШО: простые селекторы быстрее */\n.article-text { color: red; }\n\n/* ПЛОХО: много селекторов */\n.header, .nav, .sidebar, .main, .footer { margin: 0; }\n\n/* ХОРОШО: одно правило */\nbody { margin: 0; }\n```\n\n## Фаза 3: Layout (Reflow)\n\n### Что происходит\n\nБраузер вычисляет позицию и размер каждого элемента\n\n### Как это влияет на код\n\n```javascript\n// Свойства которые вызывают Layout (Reflow):\noffsettop, offsetLeft, offsetWidth, offsetHeight\nclientTop, clientLeft, clientWidth, clientHeight\nscrollTop, scrollLeft, scrollWidth, scrollHeight\ngetComputedStyle()\ngetBoundingClientRect()\nElement.offsetParent\nElement.scrollIntoView()\n\n// ПЛОХО: вызываем Layout каждый раз\nfor (let i = 0; i < elements.length; i++) {\n const width = elements[i].offsetWidth; // Layout!\n elements[i].style.width = (width * 0.9) + 'px';\n}\n\n// ХОРОШО: читаем один раз\nconst widths = elements.map(el => el.offsetWidth); // Layout один раз!\nelements.forEach((el, i) => {\n el.style.width = (widths[i] * 0.9) + 'px';\n});\n```\n\n## Фаза 4: Paint\n\n### Что происходит\n\nБраузер рисует пиксели (текст, изображения, фоны)\n\n### Как это влияет на код\n\n```css\n/* ПЛОХО: дорогие paint операции */\nbox-shadow: 0 0 10px rgba(0,0,0,0.5); /* Рисует тень вокруг элемента */\ntext-shadow: 0 0 5px black;\nfilter: blur(10px); /* Очень дорого! */\n\n/* ХОРОШО: дешёвые операции */\ntransform: scale(1.1); /* Только Composite! */\nopacity: 0.5; /* Только Composite! */\n\n/* ПЛОХО: много элементов с градиентами */\n.gradient { background: linear-gradient(45deg, red, blue); }\n\n/* ХОРОШО: используй один раз для контейнера */\n.gradient-container { background: linear-gradient(45deg, red, blue); }\n```\n\n## Фаза 5: Composite\n\n### Что происходит\n\nБраузер объединяет слои (layers) и отправляет на GPU\n\n### Как это влияет на код\n\n```javascript\n// Свойства которые не вызывают Layout или Paint:\n// transform, opacity, filter (в некоторых случаях)\n\n// МЕДЛЕННАЯ анимация (Layout + Paint)\nfunction slowAnimate() {\n let position = 0;\n setInterval(() => {\n position += 10;\n element.style.left = position + 'px'; // Reflow + Paint\n }, 16);\n}\n// Результат: ~60fps, но может быть jank\n\n// БЫСТРАЯ анимация (только Composite)\nfunction fastAnimate() {\n let position = 0;\n function frame() {\n position += 10;\n element.style.transform = `translateX(${position}px)`; // Только Composite!\n requestAnimationFrame(frame);\n }\n frame();\n}\n// Результат: гладкие 60fps, никаких проблем\n```\n\n## Практический пример: Оптимизация списка\n\n```javascript\n// ПЛОХО: вызывает много Layout операций\nfunction renderItems(items) {\n const container = document.getElementById('container');\n items.forEach(item => {\n const el = document.createElement('div');\n el.textContent = item.text;\n el.style.height = item.height + 'px'; // Layout!\n el.style.marginBottom = '10px';\n container.appendChild(el); // Trigger Layout!\n });\n}\n// Результат: N Layout операций для N элементов\n\n// ХОРОШО: батчим обновления\nfunction renderItems(items) {\n const container = document.getElementById('container');\n const fragment = document.createDocumentFragment();\n \n items.forEach(item => {\n const el = document.createElement('div');\n el.textContent = item.text;\n el.style.height = item.height + 'px';\n el.style.marginBottom = '10px';\n fragment.appendChild(el); // Не добавляем в DOM\n });\n \n container.appendChild(fragment); // Одна Layout операция!\n}\n// Результат: 1 Layout операция для всех элементов\n```\n\n## Core Web Vitals и Rendering Pipeline\n\n```\nLCP (Largest Contentful Paint) — зависит от:\n ├─ Parsing (быстро ли загружаются ресурсы)\n ├─ Style Calculation\n ├─ Layout\n └─ Paint\n\nFID (First Input Delay) — зависит от:\n ├─ JavaScript execution time\n └─ Длины задач (отложит отрисовку)\n\nCLS (Cumulative Layout Shift) — зависит от:\n └─ Неожиданные Layout изменения\n```\n\n## DevTools для отладки\n\n### Chrome DevTools - Performance\n\n```javascript\n// 1. Открыть DevTools → Performance\n// 2. Нажать Record\n// 3. Выполнить операцию\n// 4. Остановить Record\n// 5. Анализировать:\n\n// Синие блоки = Parsing\n// Зелёные блоки = Style Calculation + Layout\n// Оранжевые блоки = Paint\n// Фиолетовые блоки = Composite\n```\n\n### Chrome DevTools - Rendering\n\n```javascript\n// DevTools → More tools → Rendering\n// Включить:\n// - Paint flashing (показывает какие области перерисовываются)\n// - Layout shift regions (показывает CLS)\n// - Frame rendering stats (показывает FPS)\n```\n\n## Best Practices\n\n### 1. Используй transform для анимаций\n\n```css\n/* Вместо: */\n.slow { animation: slide 1s; }\n@keyframes slide { from { left: 0; } to { left: 100px; } }\n\n/* Используй: */\n.fast { animation: slide 1s; }\n@keyframes slide { from { transform: translateX(0); } to { transform: translateX(100px); } }\n```\n\n### 2. Батчи DOM операции\n\n```javascript\n// DocumentFragment для批量添加\nconst fragment = document.createDocumentFragment();\nfor (let i = 0; i < 1000; i++) {\n const div = document.createElement('div');\n fragment.appendChild(div);\n}\ndocument.body.appendChild(fragment); // Одна операция\n```\n\n### 3. Избегай forced reflow\n\n```javascript\n// ПЛОХО\nfor (let el of elements) {\n el.style.width = el.offsetWidth + 'px'; // Forced reflow каждый раз\n}\n\n// ХОРОШО\nconst widths = elements.map(el => el.offsetWidth); // Batch read\nelements.forEach((el, i) => {\n el.style.width = widths[i] + 'px'; // Batch write\n});\n```\n\n### 4. Используй will-change аккуратно\n\n```css\n/* Только для элементов которые часто меняются */\n.animated {\n will-change: transform;\n animation: rotate 2s infinite;\n}\n```\n\n## Итог\n\n**Знание этапов отрисовки важно для:**\n\n1. **Оптимизации производительности** — знаешь какие операции дорогие\n2. **Написания быстрого кода** — выбираешь правильные CSS свойства\n3. **Отладки проблем** — можешь использовать DevTools эффективно\n4. **Достижения Core Web Vitals** — улучшаешь LCP, FID, CLS\n5. **Создания smooth анимаций** — используешь transform вместо позиций\n6. **Масштабирования приложений** — оптимизируешь списки и таблицы\n\n**Простое правило:**\n- **Layout** (переток) — вызывают offsetWidth, offsetHeight, getComputedStyle()\n- **Paint** — вызывают box-shadow, text-shadow, filter, background-image\n- **Composite** — transform, opacity (дешёво!)\n\nЗная эти этапы, ты сможешь писать код который работает в 10 раз быстрее!\n","dateCreated":"2026-04-02T22:09:00.919472","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Для чего Frontend разработчику знать об этапах отрисовки?

1.8 Middle🔥 191 комментариев
#Браузер и сетевые технологии

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Зачем Frontend разработчику знать об этапах отрисовки (Rendering Pipeline)

Этапы отрисовки браузера — это критическое знание для оптимизации производительности и написания быстрого кода. Вот почему это важно.

Основные этапы отрисовки (Rendering Pipeline)

┌─────────────────────────────────────────────────┐
│ 1. Parsing                                      │
│    HTML → DOM Tree                              │
│    CSS → CSSOM Tree                             │
└─────────────────────────────────────────────────┘
                ↓
┌─────────────────────────────────────────────────┐
│ 2. Style Calculation                            │
│    Matching selectors → Style rules             │
└─────────────────────────────────────────────────┘
                ↓
┌─────────────────────────────────────────────────┐
│ 3. Layout (Reflow)                              │
│    Calculate positions & sizes                  │
└─────────────────────────────────────────────────┘
                ↓
┌─────────────────────────────────────────────────┐
│ 4. Paint                                        │
│    Draw pixels, text, images                    │
└─────────────────────────────────────────────────┘
                ↓
┌─────────────────────────────────────────────────┐
│ 5. Composite                                    │
│    Combine layers, send to GPU                  │
└─────────────────────────────────────────────────┘
                ↓
            Display

Почему это важно для Frontend разработчика

1. Понимание производительности

Когда вы меняете свойства CSS, браузер может сделать разное:

// Каждое изменение запускает весь pipeline!
element.style.width = '100px';    // Layout + Paint + Composite
element.style.backgroundColor = 'red'; // Paint + Composite (быстрее!)
element.style.transform = 'translateX(10px)'; // Только Composite (быстрее всех!)

// Результат: transform быстрее в 10x раз, чем width!

2. Избегание Forced Reflow

Если вы читаете размеры после изменения, браузер принудительно пересчитывает Layout:

// ПЛОХО: вызывает forced reflow!
for (let i = 0; i < 100; i++) {
  element.style.width = i + 'px';
  console.log(element.offsetWidth); // Браузер вынужден пересчитать Layout!
}
// Результат: 100 Layout операций = медленно

// ХОРОШО: читаем один раз
const width = element.offsetWidth;
for (let i = 0; i < 100; i++) {
  element.style.width = (width + i) + 'px';
}
// Результат: батчинг изменений = быстро

3. Оптимизация анимаций

// ПЛОХО: меняем width → Layout + Paint каждый frame
// 60fps = 60 Layout + Paint операций в секунду
function animate() {
  element.style.width = (element.offsetWidth + 1) + 'px';
  requestAnimationFrame(animate);
}

// ХОРОШО: используем transform → только Composite
// 60fps = 60 Composite операций (намного быстрее)
function animate() {
  let offset = 0;
  function frame() {
    offset++;
    element.style.transform = `translateX(${offset}px)`;
    requestAnimationFrame(frame);
  }
  frame();
}

Фаза 1: Parsing

Что происходит

HTML → DOM Tree (Document Object Model)
CSS → CSSOM Tree (CSS Object Model)

Как это влияет на код

<!-- ПЛОХО: Blocking CSS -->
<head>
  <link rel="stylesheet" href="large-style.css"> <!-- Блокирует парсинг HTML -->
</head>
<body>
  <h1>Content</h1>
</body>

<!-- ХОРОШО: Async CSS loading -->
<head>
  <link rel="stylesheet" href="critical-style.css"> <!-- Critical CSS inline -->
  <link rel="preload" href="non-critical.css" as="style">
</head>

<!-- ПЛОХО: Script в середине парсинга -->
<body>
  <h1>Content</h1>
  <script src="heavy-script.js"></script> <!-- Блокирует парсинг -->
</body>

<!-- ХОРОШО: Скрипты в конце или async -->
<body>
  <h1>Content</h1>
  <script src="heavy-script.js" defer></script>
</body>

Фаза 2: Style Calculation

Что происходит

Браузер матчит селекторы CSS и вычисляет стили

Как это влияет на код

/* ПЛОХО: сложные селекторы медленнее */
body > div > section > article > .container > p { color: red; }

/* ХОРОШО: простые селекторы быстрее */
.article-text { color: red; }

/* ПЛОХО: много селекторов */
.header, .nav, .sidebar, .main, .footer { margin: 0; }

/* ХОРОШО: одно правило */
body { margin: 0; }

Фаза 3: Layout (Reflow)

Что происходит

Браузер вычисляет позицию и размер каждого элемента

Как это влияет на код

// Свойства которые вызывают Layout (Reflow):
offsettop, offsetLeft, offsetWidth, offsetHeight
clientTop, clientLeft, clientWidth, clientHeight
scrollTop, scrollLeft, scrollWidth, scrollHeight
getComputedStyle()
getBoundingClientRect()
Element.offsetParent
Element.scrollIntoView()

// ПЛОХО: вызываем Layout каждый раз
for (let i = 0; i < elements.length; i++) {
  const width = elements[i].offsetWidth; // Layout!
  elements[i].style.width = (width * 0.9) + 'px';
}

// ХОРОШО: читаем один раз
const widths = elements.map(el => el.offsetWidth); // Layout один раз!
elements.forEach((el, i) => {
  el.style.width = (widths[i] * 0.9) + 'px';
});

Фаза 4: Paint

Что происходит

Браузер рисует пиксели (текст, изображения, фоны)

Как это влияет на код

/* ПЛОХО: дорогие paint операции */
box-shadow: 0 0 10px rgba(0,0,0,0.5); /* Рисует тень вокруг элемента */
text-shadow: 0 0 5px black;
filter: blur(10px); /* Очень дорого! */

/* ХОРОШО: дешёвые операции */
transform: scale(1.1); /* Только Composite! */
opacity: 0.5; /* Только Composite! */

/* ПЛОХО: много элементов с градиентами */
.gradient { background: linear-gradient(45deg, red, blue); }

/* ХОРОШО: используй один раз для контейнера */
.gradient-container { background: linear-gradient(45deg, red, blue); }

Фаза 5: Composite

Что происходит

Браузер объединяет слои (layers) и отправляет на GPU

Как это влияет на код

// Свойства которые не вызывают Layout или Paint:
// transform, opacity, filter (в некоторых случаях)

// МЕДЛЕННАЯ анимация (Layout + Paint)
function slowAnimate() {
  let position = 0;
  setInterval(() => {
    position += 10;
    element.style.left = position + 'px'; // Reflow + Paint
  }, 16);
}
// Результат: ~60fps, но может быть jank

// БЫСТРАЯ анимация (только Composite)
function fastAnimate() {
  let position = 0;
  function frame() {
    position += 10;
    element.style.transform = `translateX(${position}px)`; // Только Composite!
    requestAnimationFrame(frame);
  }
  frame();
}
// Результат: гладкие 60fps, никаких проблем

Практический пример: Оптимизация списка

// ПЛОХО: вызывает много Layout операций
function renderItems(items) {
  const container = document.getElementById('container');
  items.forEach(item => {
    const el = document.createElement('div');
    el.textContent = item.text;
    el.style.height = item.height + 'px'; // Layout!
    el.style.marginBottom = '10px';
    container.appendChild(el); // Trigger Layout!
  });
}
// Результат: N Layout операций для N элементов

// ХОРОШО: батчим обновления
function renderItems(items) {
  const container = document.getElementById('container');
  const fragment = document.createDocumentFragment();
  
  items.forEach(item => {
    const el = document.createElement('div');
    el.textContent = item.text;
    el.style.height = item.height + 'px';
    el.style.marginBottom = '10px';
    fragment.appendChild(el); // Не добавляем в DOM
  });
  
  container.appendChild(fragment); // Одна Layout операция!
}
// Результат: 1 Layout операция для всех элементов

Core Web Vitals и Rendering Pipeline

LCP (Largest Contentful Paint) — зависит от:
  ├─ Parsing (быстро ли загружаются ресурсы)
  ├─ Style Calculation
  ├─ Layout
  └─ Paint

FID (First Input Delay) — зависит от:
  ├─ JavaScript execution time
  └─ Длины задач (отложит отрисовку)

CLS (Cumulative Layout Shift) — зависит от:
  └─ Неожиданные Layout изменения

DevTools для отладки

Chrome DevTools - Performance

// 1. Открыть DevTools → Performance
// 2. Нажать Record
// 3. Выполнить операцию
// 4. Остановить Record
// 5. Анализировать:

// Синие блоки = Parsing
// Зелёные блоки = Style Calculation + Layout
// Оранжевые блоки = Paint
// Фиолетовые блоки = Composite

Chrome DevTools - Rendering

// DevTools → More tools → Rendering
// Включить:
// - Paint flashing (показывает какие области перерисовываются)
// - Layout shift regions (показывает CLS)
// - Frame rendering stats (показывает FPS)

Best Practices

1. Используй transform для анимаций

/* Вместо: */
.slow { animation: slide 1s; }
@keyframes slide { from { left: 0; } to { left: 100px; } }

/* Используй: */
.fast { animation: slide 1s; }
@keyframes slide { from { transform: translateX(0); } to { transform: translateX(100px); } }

2. Батчи DOM операции

// DocumentFragment для批量添加
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const div = document.createElement('div');
  fragment.appendChild(div);
}
document.body.appendChild(fragment); // Одна операция

3. Избегай forced reflow

// ПЛОХО
for (let el of elements) {
  el.style.width = el.offsetWidth + 'px'; // Forced reflow каждый раз
}

// ХОРОШО
const widths = elements.map(el => el.offsetWidth); // Batch read
elements.forEach((el, i) => {
  el.style.width = widths[i] + 'px'; // Batch write
});

4. Используй will-change аккуратно

/* Только для элементов которые часто меняются */
.animated {
  will-change: transform;
  animation: rotate 2s infinite;
}

Итог

Знание этапов отрисовки важно для:

  1. Оптимизации производительности — знаешь какие операции дорогие
  2. Написания быстрого кода — выбираешь правильные CSS свойства
  3. Отладки проблем — можешь использовать DevTools эффективно
  4. Достижения Core Web Vitals — улучшаешь LCP, FID, CLS
  5. Создания smooth анимаций — используешь transform вместо позиций
  6. Масштабирования приложений — оптимизируешь списки и таблицы

Простое правило:

  • Layout (переток) — вызывают offsetWidth, offsetHeight, getComputedStyle()
  • Paint — вызывают box-shadow, text-shadow, filter, background-image
  • Composite — transform, opacity (дешёво!)

Зная эти этапы, ты сможешь писать код который работает в 10 раз быстрее!

Для чего Frontend разработчику знать об этапах отрисовки? | PrepBro