compositingCompositing
Compare compositor-friendly properties, hardware-acceleration hints, and layout-triggering properties.
Preview
Compositing assembles painted layers into the final frame and can update transforms or opacity without repeating layout.
Implement Compositing: Compare compositor-friendly properties, hardware-acceleration hints, and layout-triggering properties. Use Demo duration 520ms, Distance 80px, Compared property transform, Easing linear. Trigger it once when state changes and keep it replayable. Use semantic HTML, scope CSS to .motion-demo--compositing. Provide equivalent low-motion behavior for prefers-reduced-motion and .force-reduced-motion.
<div class="motion-demo motion-demo--compositing" data-motion="compositing" aria-label="Compositing demo">
<article class="motion-surface">
<strong>Compositing</strong>
<span class="motion-line"></span>
<span class="motion-line"></span>
</article>
</div>.motion-demo.motion-demo--compositing {
box-sizing: border-box;
position: relative;
display: grid;
place-items: center;
width: min(100%, 34rem);
min-height: 15rem;
padding: 2rem;
overflow: hidden;
color: #18181b;
background: #fafafa;
border: 1px solid #e4e4e7;
border-radius: 16px;
isolation: isolate;
}
.motion-demo.motion-demo--compositing *, .motion-demo.motion-demo--compositing *::before, .motion-demo.motion-demo--compositing *::after {
box-sizing: border-box;
}
.motion-demo.motion-demo--compositing .motion-surface {
position: relative;
display: grid;
gap: 0.65rem;
width: min(100%, 18rem);
padding: 1.25rem;
background: #ffffff;
border: 1px solid #e4e4e7;
border-radius: 16px;
box-shadow: none;
}
.motion-demo.motion-demo--compositing .motion-surface strong { font-weight: 500; }
.motion-demo.motion-demo--compositing .motion-line {
display: block;
width: 100%;
height: 0.5rem;
background: #e4e4e7;
border-radius: 999px;
}
.motion-demo.motion-demo--compositing .motion-line:last-child { width: 62%; }
.motion-demo.motion-demo--compositing .motion-button {
position: relative;
min-height: 2.75rem;
padding: 0.75rem 1.1rem;
color: white;
font: inherit;
font-weight: 700;
background: #18181b;
border: 0;
border-radius: 999px;
cursor: pointer;
}
.motion-demo.motion-demo--compositing .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }
.motion-demo.motion-demo--compositing .motion-action-row {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-top: 0.85rem;
}
.motion-demo.motion-demo--compositing .motion-replay-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--compositing .motion-pausable-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--compositing button.motion-surface {
color: inherit;
font: inherit;
text-align: start;
cursor: pointer;
}
.motion-demo.motion-demo--compositing .motion-replay-button,
.motion-demo.motion-demo--compositing .motion-undo-button,
.motion-demo.motion-demo--compositing .motion-dismiss-button,
.motion-demo.motion-demo--compositing .motion-pause-button {
min-height: 2.75rem;
padding: 0.65rem 0.9rem;
color: #18181b;
font: 650 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
background: #ffffff;
border: 1px solid #d4d4d8;
border-radius: 8px;
cursor: pointer;
}
.motion-demo.motion-demo--compositing .motion-replay-button:focus-visible,
.motion-demo.motion-demo--compositing .motion-undo-button:focus-visible,
.motion-demo.motion-demo--compositing .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--compositing .motion-pause-button:focus-visible,
.motion-demo.motion-demo--compositing [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--compositing [data-swipe-target]:focus-visible {
outline: 3px solid rgb(37 99 235 / 32%);
outline-offset: 3px;
}
.motion-demo.motion-demo--compositing .motion-status {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.motion-demo.motion-demo--compositing .motion-ripple-ink {
position: absolute;
width: 12px;
height: 12px;
pointer-events: none;
background: rgb(255 255 255 / 72%);
border-radius: 50%;
transform: translate(-50%, -50%) scale(0.95);
opacity: 0;
}
.motion-demo.motion-demo--compositing .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--compositing .motion-state { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: #ffffff; border: 1px solid #e4e4e7; border-radius: 16px; }
.motion-demo.motion-demo--compositing .motion-state--to { background: #18181b; color: white; }
.motion-demo.motion-demo--compositing .motion-scroll-track > span { color: #71717a; font: 600 0.72rem/1.2 ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.motion-demo.motion-demo--compositing .motion-orbit-item { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; color: white; background: #2563eb; border-radius: 50%; }
.motion-demo.motion-demo--compositing .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--compositing svg { width: min(100%, 20rem); height: auto; }
.motion-demo.motion-demo--compositing .motion-surface { position: relative; animation: motion-compositing 520ms linear infinite alternate; }
@keyframes motion-compositing { from { transform: translateX(-80px); } to { transform: translateX(80px); } }
@keyframes motion-compositing-reduced-fade {
from { opacity: 0.84; }
to { opacity: 1; }
}
.force-reduced-motion .motion-demo.motion-demo--compositing {
animation: motion-compositing-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.force-reduced-motion .motion-demo.motion-demo--compositing *,
.force-reduced-motion .motion-demo.motion-demo--compositing *::before,
.force-reduced-motion .motion-demo.motion-demo--compositing *::after {
animation: none !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-property: opacity, color, background-color, border-color !important;
transition-duration: 160ms !important;
transition-delay: 0ms !important;
scroll-behavior: auto !important;
}
.force-reduced-motion .motion-demo.motion-demo--compositing .motion-button,
.force-reduced-motion .motion-demo.motion-demo--compositing [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--compositing [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--compositing [data-spring-target] {
transform: none !important;
}
.force-reduced-motion .motion-demo.motion-demo--compositing .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--compositing .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--compositing .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
@media (prefers-reduced-motion: reduce) {
.motion-demo.motion-demo--compositing {
animation: motion-compositing-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.motion-demo.motion-demo--compositing *, .motion-demo.motion-demo--compositing *::before, .motion-demo.motion-demo--compositing *::after {
animation: none !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-property: opacity, color, background-color, border-color !important;
transition-duration: 160ms !important;
transition-delay: 0ms !important;
scroll-behavior: auto !important;
}
.motion-demo.motion-demo--compositing .motion-button,
.motion-demo.motion-demo--compositing [data-reorder-item],
.motion-demo.motion-demo--compositing [data-swipe-target],
.motion-demo.motion-demo--compositing [data-spring-target] {
transform: none !important;
}
.motion-demo.motion-demo--compositing .motion-path { stroke-dashoffset: 0 !important; }
.motion-demo.motion-demo--compositing .motion-word--from { opacity: 0 !important; visibility: hidden; }
.motion-demo.motion-demo--compositing .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}Learn more
Terms and distinctions
compositingCompositing
合成Compositing assembles painted layers into the final frame and can update transforms or opacity without repeating layout.
合成会把已绘制的图层组合成最终画面;独立图层上的 transform 或 opacity 更新可跳过布局,并可能跳过重绘。
will-changewill-change
will-changeThe will-change property warns the browser about an upcoming property change so it can prepare relevant rendering resources.
一种 CSS 渲染提示,告知浏览器某项属性即将变化,以便浏览器按需提前准备优化。
will-change is an optimization hint; Compositing is the rendering stage that lets the GPU handle layers.
layout-thrashingLayout thrashing
布局抖动Repeated interleaving of layout reads and writes forces synchronous recalculation and consumes the frame budget.
交替读取布局信息并写入样式,会反复触发同步布局计算并耗尽帧预算。
Layout thrashing comes from repeated layout calculation; compositor-friendly transform and opacity can avoid that work.
hardware-accelerationHardware acceleration
硬件加速Hardware acceleration uses compositor and GPU resources for eligible visual updates, helping frames meet display deadlines.
符合条件的视觉更新可利用合成线程和 GPU 资源,帮助画面赶上显示刷新期限。
Hardware acceleration describes using the GPU to keep motion smooth; Compositing is the rendering stage that hands independent layers to the GPU.
Before implementation
- Purpose
- Compare compositor-friendly properties with layout- or paint-triggering properties to choose a stable rendering path.
- Frequency
- Review during new motion implementation, performance regressions, and integration into complex pages.
- Trigger
- Trigger from property selection or a performance experiment while recording main-thread, layout, paint, and compositing activity.
- Enter / exit
- Switch property strategies directly and keep metric changes readable without extra transitions affecting results.
- Interruptibility
- Allow tests to stop and reset layer state, enabling will-change only shortly before it is needed.
- Gesture and keyboard
- Drive compared strategies with identical gesture distance and speed.
- Reduced-motion strategy
- Reduced-motion mode still favors transform and opacity while limiting persistent layer allocation.
Accessibility
Reduced-motion mode still favors transform and opacity while limiting persistent layer allocation.
Parameter reference
| Parameter | Range / options | Default | Purpose |
|---|---|---|---|
duration | 300ms–1200ms | 520ms | Uses a longer demo duration so the full change stays observable; immediate production UI feedback should stay under 300ms. |
distance | 0px–180px | 80px | Controls how far the element travels. |
property | Transform / Left / Opacity | Transform | Selects compared property. |
ease | Soft / Snap / Calm / Linear | Linear | Controls how velocity changes over time. |
Pre-delivery review
- Distinguish Compositing, will-change, and Layout thrashing.
- Inspect layer count, memory use, and cleanup after completion.