← Назад к вопросам
Будет ли вызван Reflow при изменении высоты и ширины элемента?
2.0 Middle🔥 201 комментариев
#HTML и CSS#Браузер и сетевые технологии
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Будет ли вызван Reflow при изменении высоты и ширины элемента?
Ответ: ДА, Reflow будет вызван при изменении высоты и ширины элемента.
Высота и ширина — это ключевые параметры макета (layout), поэтому их изменение обязательно пересчитает макет всей страницы или части её.
Что такое Reflow?
Reflow (перекомпоновка) — это процесс браузера, во время которого:
- Браузер пересчитывает позицию и размер каждого элемента
- Обновляет "box model" (отступы, границы, содержимое)
- Проверяет влияние изменений на другие элементы
- Может вызвать каскадное обновление соседних элементов
Это дорогая операция, которая блокирует рендеринг.
Какие свойства CSS вызывают Reflow?
// ДА, эти свойства вызывают REFLOW:
element.style.width = '200px'; // Изменение ширины
element.style.height = '100px'; // Изменение высоты
element.style.padding = '10px'; // Изменение отступов
element.style.margin = '5px'; // Изменение внешних отступов
element.style.top = '50px'; // Изменение позиции
element.style.left = '10px'; // Изменение позиции
element.style.display = 'block'; // Изменение отображения
element.style.position = 'relative';// Изменение позиционирования
element.style.fontSize = '14px'; // Изменение размера шрифта
element.style.fontWeight = 'bold'; // Влияет на ширину текста
element.textContent = 'New text'; // Изменение контента
element.appendChild(newChild); // Добавление элемента
element.removeChild(child); // Удаление элемента
// НЕТ, эти свойства вызывают только REPAINT:
element.style.color = 'red'; // Только цвет текста
element.style.backgroundColor = '#fff'; // Только фон
element.style.opacity = '0.5'; // Прозрачность (иногда оптимизируется)
element.style.boxShadow = '0 0 5px'; // Тень (может оптимизироваться)
Разница: Reflow vs Repaint
// REPAINT - обновляет только визуальное отображение
// Не влияет на макет
const element = document.querySelector('div');
element.style.color = 'red'; // Только перекрашивание
element.style.backgroundColor = 'blue'; // Только перекрашивание
element.style.opacity = '0.5'; // Только перекрашивание
// REFLOW - пересчитывает весь макет
// Гораздо медленнее
element.style.width = '200px'; // Reflow!
element.style.height = '100px'; // Reflow!
Визуально:
Reflow (дорого): Parse HTML -> Recalculate Layout -> Paint -> Composite
Repaint (дешево): Paint -> Composite
Пример: множественные Reflow
// ПЛОХО: 10 Reflow!
const element = document.querySelector('div');
element.style.width = '100px'; // Reflow #1
element.style.height = '100px'; // Reflow #2
element.style.padding = '10px'; // Reflow #3
element.style.margin = '5px'; // Reflow #4
element.style.border = '1px solid'; // Reflow #5
element.style.top = '20px'; // Reflow #6
// ... итого 6+ Reflow
// ХОРОШО: 1 Reflow!
element.style.cssText = `
width: 100px;
height: 100px;
padding: 10px;
margin: 5px;
border: 1px solid;
top: 20px;
`;
// cssText применяется одним Reflow!
// ХОРОШО: 1 Reflow с classList
element.classList.add('my-style'); // 1 Reflow
// CSS класс:
// .my-style {
// width: 100px;
// height: 100px;
// padding: 10px;
// }
Практический пример: анимация без Reflow
// ПЛОХО: Reflow на каждый фрейм анимации
function animateBadly() {
let position = 0;
const interval = setInterval(() => {
position += 10;
element.style.left = position + 'px'; // Reflow каждый фрейм!
if (position > 500) clearInterval(interval);
}, 16); // 60fps
}
// ХОРОШО: используем CSS animations
function animateGood() {
element.style.animation = 'slideRight 2s ease-in-out';
}
// CSS:
// @keyframes slideRight {
// from { left: 0; }
// to { left: 500px; }
// }
// Браузер оптимизирует анимацию!
// ОЧЕНЬ ХОРОШО: используем transform (оптимизировано на GPU)
function animateBest() {
element.style.animation = 'slideRight 2s ease-in-out';
}
// CSS:
// @keyframes slideRight {
// from { transform: translateX(0); }
// to { transform: translateX(500px); }
// }
// transform НЕ вызывает Reflow!
Чтение свойств тоже может вызвать Reflow!
// ЛОВУШКА: Чтение вызывает Reflow перед вычислением
const width = element.offsetWidth; // Чтение могут вызвать Reflow
const height = element.offsetHeight;
const top = element.offsetTop;
// Потому что браузер должен обновить layout перед возвратом значения
// Данные свойства ПРИЧИНЫ Reflow при чтении:
element.offsetHeight
element.offsetWidth
element.offsetTop
element.offsetLeft
element.scrollHeight
element.scrollWidth
element.scrollTop
element.scrollLeft
element.clientHeight
element.clientWidth
element.getComputedStyle() // Очень дорого!
window.getComputedStyle(element)
Оптимизация: избежать множественных Reflow
// ПЛОХО: множественные Reflow
const elements = document.querySelectorAll('.item');
elements.forEach(el => {
el.style.width = el.offsetWidth * 1.5 + 'px'; // Читаем + пишем = 2 Reflow
});
// Итого: N * 2 Reflow
// ХОРОШО: сначала читаем, потом пишем
const widths = Array.from(elements).map(el => el.offsetWidth); // N Reflow
elements.forEach((el, i) => {
el.style.width = widths[i] * 1.5 + 'px'; // N Reflow
});
// Итого: 2 больших Reflow вместо 2N маленьких
// ЛУЧШЕ: использовать DocumentFragment или скрыть элемент
const fragment = document.createDocumentFragment();
elements.forEach((el, i) => {
const newEl = el.cloneNode(true);
newEl.style.width = widths[i] * 1.5 + 'px';
fragment.appendChild(newEl);
});
const parent = elements[0].parentNode;
parent.innerHTML = '';
parent.appendChild(fragment); // Один Reflow!
Реальный пример: изменение высоты в React
function ResizeableBox({ initialHeight = 200 }) {
const [height, setHeight] = useState(initialHeight);
const ref = useRef<HTMLDivElement>(null);
const handleResize = () => {
// ПЛОХО: Reflow в каждом фрейме
setHeight(height + 10);
};
// ХОРОШО: использовать CSS transitions
useEffect(() => {
if (ref.current) {
// Один Reflow при монтировании
ref.current.style.transition = 'height 0.3s ease';
}
}, []);
return (
<div
ref={ref}
style={{
height: `${height}px`,
// Добавляем transition через CSS класс
transition: 'height 0.3s ease'
}}
>
Content
</div>
);
}
Инструменты для измерения Reflow
// Chrome DevTools Performance tab:
// 1. Открыть DevTools (F12)
// 2. Перейти в Performance tab
// 3. Нажать Record
// 4. Выполнить операцию
// 5. Нажать Stop
// 6. Смотреть Layout events в timeline
// Или programmatically:
performance.mark('reflow-start');
element.style.width = '100px';
performance.mark('reflow-end');
performance.measure('reflow', 'reflow-start', 'reflow-end');
const measure = performance.getEntriesByName('reflow')[0];
console.log(`Reflow took ${measure.duration}ms`);
Итоговая таблица
| Операция | Reflow | Repaint | Оптимизирована |
|---|---|---|---|
| width/height изменение | Да | Да | Нет |
| color изменение | Нет | Да | Да |
| transform изменение | Нет | Нет | Да (GPU) |
| opacity изменение | Нет | Да* | Зависит |
| position изменение | Да | Да | Нет |
| padding/margin | Да | Да | Нет |
| display изменение | Да | Да | Нет |
| visibility: hidden | Нет | Да | - |
| animation с transform | Нет | Нет | Да |
| animation с left/top | Да | Да | Нет |
Вывод
Изменение width и height ОБЯЗАТЕЛЬНО вызывает Reflow, потому что:
- Это параметры макета
- Влияют на расчёт размеров других элементов
- Требуют пересчёта позиций и размеров
Для оптимизации:
- Используй transform вместо left/top
- Группируй изменения CSS через cssText или классы
- Избегай чтения offsetWidth/offsetHeight в циклах
- Используй CSS анимации вместо JavaScript
- Профилируй с помощью DevTools Performance