CSS Houdini APIs
CSS Houdini is a set of low-level browser APIs that let developers directly control the CSS rendering engine. It allows custom layouts, styles, animations, and properties without heavy JavaScript.
- Paint API: Draw custom graphics for backgrounds, borders, and masks.
- Layout API: Create new layout algorithms beyond Flexbox/Grid.
- Properties & Values API: Define typed CSS variables with validation.
- Animation Worklet: High-performance animations in the rendering pipeline.
CSS Houdini Paint API: Custom Rendering
The Paint API allows you to draw custom graphics directly in CSS using a JavaScript paint worklet, reducing reliance on JavaScript for styling.
<div class="box">Custom Gradient Border</div>
<script>
CSS.paintWorklet.addModule('gradient-border.js');
</script>
.box {
width: 200px;
height: 100px;
border: 10px solid;
border-image: paint(gradient-border) 10;
}
Paint Worklet (gradient-border.js
)
registerPaint('gradient-border', class {
paint(ctx, size) {
const gradient = ctx.createLinearGradient(0, 0, size.width, size.height);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(1, 'purple');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, size.width, size.height);
}
});
Layout Worklet
Define custom layout algorithms like masonry, circular, or grid variations.
Example:
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
.container {
display: layout(masonry); /* Requires a custom layout worklet */
gap: 10px;
}
.item {
background-color: lightblue;
padding: 20px;
border-radius: 8px;
text-align: center;
}
Animation Worklet
Enables high-performance animations tied to scroll, timeline, or custom triggers.
Example:
registerAnimator('scroll', class {
animate(context, timeline) {
// Scroll-driven animation logic
const progress = timeline.currentTime / timeline.duration;
context.element.style.transform = `translateX(${progress * 100}px)`;
}
});
Properties & Values Worklet
Allows custom CSS properties with type validation and dynamic behavior.
Example:
CSS.registerProperty({
name: '--custom-radius',
syntax: '<length>',
inherits: false,
initialValue: '10px'
});
Animated Example
Animate a custom property for a spinner element:
<div class="spinner"></div>
/* Register a custom property for rotation */
@property --spin-angle {
syntax: '<angle>';
inherits: false;
initialValue: 0deg;
}
/* Spinner element using the custom property */
.spinner {
--spin-angle: 0deg;
width: 100px;
height: 100px;
border: 8px solid lightgray;
border-top-color: steelblue;
border-radius: 50%;
animation: spin 2s linear infinite;
transform: rotate(var(--spin-angle));
}
/* Animate the custom property */
@keyframes spin {
to { --spin-angle: 360deg; }
}