diff --git a/.gitignore b/.gitignore
index a6de460..3c7ef84 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ polyfill.js
polyfill.js.map
demo-overlays.js
demo-overlays.js.map
+public
diff --git a/ORIGIN_TRIAL.md b/ORIGIN_TRIAL.md
index 5523a90..98b5e87 100644
--- a/ORIGIN_TRIAL.md
+++ b/ORIGIN_TRIAL.md
@@ -10,9 +10,9 @@ This document describes the Chrome experimental feature enabling developers to m
- **Issue Tracker**: [GitHub Issues](https://github.com/WICG/container-timing/issues)
- **Blog Post**: [Container Timing: Measuring Web Components Performance](https://blogs.igalia.com/dape/2026/02/10/container-timing-measuring-web-components-performance/)
-## Implementation in Chrome v147+
+## Origin Trial available from m148 - m153
-Chrome v147 introduced support for the Container Timing API behind the experimental web platform features flag. The API allows developers to mark sections of the DOM with the `containertiming` attribute and receive performance entries when those sections are painted.
+The Chrome Origin Trial introduces support for the Container Timing API behind the experimental web platform features flag. The API allows developers to mark sections of the DOM with the `containertiming` attribute and receive performance entries when those sections are painted.
### Basic Usage
diff --git a/README.md b/README.md
index 6e99318..9c21d93 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Container Timing: Explainer
-_Note: This API plans to go to [Origin Trial](./ORIGIN_TRIAL.md) during Chrome v147-152, please try it out!_
+_Note: This API plans to go to [Origin Trial](./ORIGIN_TRIAL.md) during Chrome m148-153, please try it out!_
## Authors
diff --git a/examples/adding-content/index.shadowed.html b/examples/adding-content/index.shadowed.html
deleted file mode 100644
index 2edd9f7..0000000
--- a/examples/adding-content/index.shadowed.html
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
- Adding Content to a component
-
-
-
-
-
-
-
Some title for the container
-
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
- minim veniam, quis nostrud exercitation ullamco laboris nisi ut
- aliquip ex ea commodo consequat. Duis aute irure dolor in
- reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
- pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
- culpa qui officia deserunt mollit anim id est laborum."
-
-
-
-
Some inner content
-
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
- minim veniam, quis nostrud exercitation ullamco laboris nisi ut
- aliquip ex ea commodo consequat. Duis aute irure dolor in
- reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
- pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
- culpa qui officia deserunt mollit anim id est laborum."
-
-
-
-
-
-
diff --git a/examples/adding-content/index.transparent.html b/examples/adding-content/index.transparent.html
deleted file mode 100644
index bae2ff4..0000000
--- a/examples/adding-content/index.transparent.html
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
- Adding Content to a component
-
-
-
-
-
-
-
Some title for the container
-
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
- minim veniam, quis nostrud exercitation ullamco laboris nisi ut
- aliquip ex ea commodo consequat. Duis aute irure dolor in
- reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
- pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
- culpa qui officia deserunt mollit anim id est laborum."
-
-
-
-
Some inner content
-
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
- eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
- minim veniam, quis nostrud exercitation ullamco laboris nisi ut
- aliquip ex ea commodo consequat. Duis aute irure dolor in
- reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
- pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
- culpa qui officia deserunt mollit anim id est laborum."
-
-
-
-
-
-
diff --git a/examples/canvas-2d/index.html b/examples/canvas-2d/index.html
new file mode 100644
index 0000000..c939173
--- /dev/null
+++ b/examples/canvas-2d/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+ Canvas 2D - Container Timing
+
+
+
+
+
+
+
+
diff --git a/examples/canvas-2d/index.js b/examples/canvas-2d/index.js
new file mode 100644
index 0000000..28c1d88
--- /dev/null
+++ b/examples/canvas-2d/index.js
@@ -0,0 +1,35 @@
+const canvas = document.getElementById("canvas");
+const ctx = canvas.getContext("2d");
+
+// Gradient background
+const gradient = ctx.createLinearGradient(0, 0, 400, 300);
+gradient.addColorStop(0, "#1a1a2e");
+gradient.addColorStop(1, "#16213e");
+ctx.fillStyle = gradient;
+ctx.fillRect(0, 0, 400, 300);
+
+// Colored circles
+const colors = ["#e94560", "#0f3460", "#533483", "#e94560", "#0f3460"];
+for (let i = 0; i < 5; i++) {
+ ctx.beginPath();
+ ctx.arc(50 + i * 75, 150, 40, 0, Math.PI * 2);
+ ctx.fillStyle = colors[i];
+ ctx.fill();
+}
+
+// Label
+ctx.fillStyle = "#ffffff";
+ctx.font = "bold 18px Arial";
+ctx.textAlign = "center";
+ctx.fillText("2D Canvas", 200, 270);
+
+const observer = new PerformanceObserver((list) => {
+ list.getEntries().forEach((entry) => {
+ console.log(entry);
+ });
+});
+
+observer.observe({ type: ["element"], buffered: true });
+observer.observe({ type: ["paint"], buffered: true });
+observer.observe({ type: ["largest-contentful-paint"], buffered: true });
+observer.observe({ type: ["container"], buffered: true });
diff --git a/examples/index.html b/examples/index.html
new file mode 100644
index 0000000..5dbebfa
--- /dev/null
+++ b/examples/index.html
@@ -0,0 +1,153 @@
+
+
+
+
+
+ Container Timing Examples
+
+
+
+ Container Timing Examples
+ Demos for the Container Timing API .
+
+
+
+
+ Example
+ Description
+ Chromium support
+
+
+
+
+ Adding content
+ Dynamically adds elements inside a containertiming container and observes the resulting timing entries, including intersectionRect and damagedRects.
+ Yes (with flag) ?
+
+
+ Canvas 2D
+ Tracks container timing for a <canvas> element painted with the 2D API.
+ Not supported
+
+
+ Shadow DOM
+ Shows container timing behaviour with a declarative shadow root (shadowrootmode="open") containing observed elements.
+ Not supported
+
+
+ Skeleton layout
+ Replaces a shimmer skeleton with real content after a delay. Tests that the low-entropy filter correctly ignores solid-colour placeholder blocks.
+ Yes (with flag) ?
+
+
+ SVG
+ Measures container timing for an inline SVG with nested groups, gradients, and decorative paths.
+ Not supported
+
+
+ SVG as image
+ Tracks timing when an SVG file is loaded via an <img src="…svg"> tag rather than inlined.
+ Yes (with flag) ?
+
+
+ SVG with image
+ Measures timing for an SVG that embeds a raster image deep within its group hierarchy.
+ Yes (with flag) ?
+
+
+ SVG with multiple images
+ Like the above, but with multiple raster images embedded inside the SVG via <image> elements.
+ Yes (with flag) ?
+
+
+ SVG with text
+ Measures timing for an SVG containing text elements at multiple nesting levels.
+ Yes (with flag) ?
+
+
+ Table
+ Container timing for a complex flexbox-based virtualized table layout with transform-positioned rows and columns.
+ Yes (with flag) ?
+
+
+ Video (no poster)
+ Tracks container timing for a <video> element without a poster image.
+ Not supported
+
+
+ Video (with poster)
+ Like the above, but with a poster attribute to test timing when an initial poster frame is displayed.
+ Yes (with flag) ?
+
+
+ WebGL
+ Tracks container timing for a <canvas> element rendered with WebGL.
+ Not supported
+
+
+
+
+
+
diff --git a/examples/svg-as-image/image.svg b/examples/svg-as-image/image.svg
new file mode 100644
index 0000000..d16d9fb
--- /dev/null
+++ b/examples/svg-as-image/image.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+ SVG as image src
+
diff --git a/examples/svg-as-image/index.html b/examples/svg-as-image/index.html
new file mode 100644
index 0000000..395f5dc
--- /dev/null
+++ b/examples/svg-as-image/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+ SVG as image src - Container Timing
+
+
+
+
+
+
+
+
diff --git a/examples/svg-as-image/index.js b/examples/svg-as-image/index.js
new file mode 100644
index 0000000..fb11b9c
--- /dev/null
+++ b/examples/svg-as-image/index.js
@@ -0,0 +1,10 @@
+const observer = new PerformanceObserver((list) => {
+ list.getEntries().forEach((entry) => {
+ console.log(entry);
+ });
+});
+
+observer.observe({ type: ["element"], buffered: true });
+observer.observe({ type: ["paint"], buffered: true });
+observer.observe({ type: ["largest-contentful-paint"], buffered: true });
+observer.observe({ type: ["container"], buffered: true });
diff --git a/examples/svg-with-image/index.html b/examples/svg-with-image/index.html
new file mode 100644
index 0000000..a8ec010
--- /dev/null
+++ b/examples/svg-with-image/index.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ SVG with image - Container Timing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/svg-with-image/index.js b/examples/svg-with-image/index.js
new file mode 100644
index 0000000..fb11b9c
--- /dev/null
+++ b/examples/svg-with-image/index.js
@@ -0,0 +1,10 @@
+const observer = new PerformanceObserver((list) => {
+ list.getEntries().forEach((entry) => {
+ console.log(entry);
+ });
+});
+
+observer.observe({ type: ["element"], buffered: true });
+observer.observe({ type: ["paint"], buffered: true });
+observer.observe({ type: ["largest-contentful-paint"], buffered: true });
+observer.observe({ type: ["container"], buffered: true });
diff --git a/examples/svg-with-images/index.html b/examples/svg-with-images/index.html
new file mode 100644
index 0000000..0773529
--- /dev/null
+++ b/examples/svg-with-images/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+ Images within SVG - Container Timing
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/svg-with-images/index.js b/examples/svg-with-images/index.js
new file mode 100644
index 0000000..fb11b9c
--- /dev/null
+++ b/examples/svg-with-images/index.js
@@ -0,0 +1,10 @@
+const observer = new PerformanceObserver((list) => {
+ list.getEntries().forEach((entry) => {
+ console.log(entry);
+ });
+});
+
+observer.observe({ type: ["element"], buffered: true });
+observer.observe({ type: ["paint"], buffered: true });
+observer.observe({ type: ["largest-contentful-paint"], buffered: true });
+observer.observe({ type: ["container"], buffered: true });
diff --git a/examples/svg-with-images/sample.jpg b/examples/svg-with-images/sample.jpg
new file mode 100644
index 0000000..1f48466
Binary files /dev/null and b/examples/svg-with-images/sample.jpg differ
diff --git a/examples/svg-with-text/index.html b/examples/svg-with-text/index.html
new file mode 100644
index 0000000..c9e9af9
--- /dev/null
+++ b/examples/svg-with-text/index.html
@@ -0,0 +1,66 @@
+
+
+
+
+
+ SVG with text - Container Timing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Container
+ Timing API
+
+
+
+
+
+
+
+
diff --git a/examples/svg-with-text/index.js b/examples/svg-with-text/index.js
new file mode 100644
index 0000000..fb11b9c
--- /dev/null
+++ b/examples/svg-with-text/index.js
@@ -0,0 +1,10 @@
+const observer = new PerformanceObserver((list) => {
+ list.getEntries().forEach((entry) => {
+ console.log(entry);
+ });
+});
+
+observer.observe({ type: ["element"], buffered: true });
+observer.observe({ type: ["paint"], buffered: true });
+observer.observe({ type: ["largest-contentful-paint"], buffered: true });
+observer.observe({ type: ["container"], buffered: true });
diff --git a/examples/svg/index.js b/examples/svg/index.js
index 90e7f02..6dea166 100644
--- a/examples/svg/index.js
+++ b/examples/svg/index.js
@@ -5,6 +5,18 @@ const observer = new PerformanceObserver((list) => {
});
observer.observe({
- entryTypes: ["element", "paint", "largest-contentful-paint", "container"],
+ type: ["element"],
+ buffered: true,
+});
+observer.observe({
+ type: ["paint"],
+ buffered: true,
+});
+observer.observe({
+ type: ["largest-contentful-paint"],
+ buffered: true,
+});
+observer.observe({
+ type: ["container"],
buffered: true,
});
diff --git a/examples/video/no-poster/index.html b/examples/video/no-poster/index.html
new file mode 100644
index 0000000..4e11930
--- /dev/null
+++ b/examples/video/no-poster/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Video (no poster) - Container Timing
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/video/no-poster/index.js b/examples/video/no-poster/index.js
new file mode 100644
index 0000000..fb11b9c
--- /dev/null
+++ b/examples/video/no-poster/index.js
@@ -0,0 +1,10 @@
+const observer = new PerformanceObserver((list) => {
+ list.getEntries().forEach((entry) => {
+ console.log(entry);
+ });
+});
+
+observer.observe({ type: ["element"], buffered: true });
+observer.observe({ type: ["paint"], buffered: true });
+observer.observe({ type: ["largest-contentful-paint"], buffered: true });
+observer.observe({ type: ["container"], buffered: true });
diff --git a/examples/video/video.mp4 b/examples/video/video.mp4
new file mode 100644
index 0000000..084efec
Binary files /dev/null and b/examples/video/video.mp4 differ
diff --git a/examples/video/video.webm b/examples/video/video.webm
new file mode 100644
index 0000000..c49cbe0
Binary files /dev/null and b/examples/video/video.webm differ
diff --git a/examples/video/with-poster/index.html b/examples/video/with-poster/index.html
new file mode 100644
index 0000000..55fcc7a
--- /dev/null
+++ b/examples/video/with-poster/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Video (with poster) - Container Timing
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/video/with-poster/index.js b/examples/video/with-poster/index.js
new file mode 100644
index 0000000..fb11b9c
--- /dev/null
+++ b/examples/video/with-poster/index.js
@@ -0,0 +1,10 @@
+const observer = new PerformanceObserver((list) => {
+ list.getEntries().forEach((entry) => {
+ console.log(entry);
+ });
+});
+
+observer.observe({ type: ["element"], buffered: true });
+observer.observe({ type: ["paint"], buffered: true });
+observer.observe({ type: ["largest-contentful-paint"], buffered: true });
+observer.observe({ type: ["container"], buffered: true });
diff --git a/examples/video/with-poster/poster.jpg b/examples/video/with-poster/poster.jpg
new file mode 100644
index 0000000..5f19687
Binary files /dev/null and b/examples/video/with-poster/poster.jpg differ
diff --git a/examples/webgl/index.html b/examples/webgl/index.html
new file mode 100644
index 0000000..062f19f
--- /dev/null
+++ b/examples/webgl/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+ WebGL - Container Timing
+
+
+
+
+
+
+
+
diff --git a/examples/webgl/index.js b/examples/webgl/index.js
new file mode 100644
index 0000000..962a1fd
--- /dev/null
+++ b/examples/webgl/index.js
@@ -0,0 +1,70 @@
+const canvas = document.getElementById("canvas");
+const gl = canvas.getContext("webgl");
+
+const vertexShaderSource = `
+ attribute vec2 a_position;
+ attribute vec3 a_color;
+ varying vec3 v_color;
+ void main() {
+ gl_Position = vec4(a_position, 0.0, 1.0);
+ v_color = a_color;
+ }
+`;
+
+const fragmentShaderSource = `
+ precision mediump float;
+ varying vec3 v_color;
+ void main() {
+ gl_FragColor = vec4(v_color, 1.0);
+ }
+`;
+
+function createShader(type, source) {
+ const shader = gl.createShader(type);
+ gl.shaderSource(shader, source);
+ gl.compileShader(shader);
+ return shader;
+}
+
+const program = gl.createProgram();
+gl.attachShader(program, createShader(gl.VERTEX_SHADER, vertexShaderSource));
+gl.attachShader(program, createShader(gl.FRAGMENT_SHADER, fragmentShaderSource));
+gl.linkProgram(program);
+gl.useProgram(program);
+
+// Interleaved position (x, y) and color (r, g, b) for a triangle
+const data = new Float32Array([
+ // x y r g b
+ 0.0, 0.8, 1.0, 0.2, 0.2, // top — red
+ -0.8, -0.8, 0.2, 1.0, 0.2, // bottom-left — green
+ 0.8, -0.8, 0.2, 0.2, 1.0, // bottom-right — blue
+]);
+
+const buffer = gl.createBuffer();
+gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
+
+const stride = 5 * Float32Array.BYTES_PER_ELEMENT;
+
+const posLoc = gl.getAttribLocation(program, "a_position");
+gl.enableVertexAttribArray(posLoc);
+gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, stride, 0);
+
+const colorLoc = gl.getAttribLocation(program, "a_color");
+gl.enableVertexAttribArray(colorLoc);
+gl.vertexAttribPointer(colorLoc, 3, gl.FLOAT, false, stride, 2 * Float32Array.BYTES_PER_ELEMENT);
+
+gl.clearColor(0.1, 0.1, 0.1, 1.0);
+gl.clear(gl.COLOR_BUFFER_BIT);
+gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+const observer = new PerformanceObserver((list) => {
+ list.getEntries().forEach((entry) => {
+ console.log(entry);
+ });
+});
+
+observer.observe({ type: ["element"], buffered: true });
+observer.observe({ type: ["paint"], buffered: true });
+observer.observe({ type: ["largest-contentful-paint"], buffered: true });
+observer.observe({ type: ["container"], buffered: true });
diff --git a/index.bs b/index.bs
index f12fba2..1aecca7 100644
--- a/index.bs
+++ b/index.bs
@@ -183,7 +183,7 @@ For each {{Document}}, the user agent must maintain a container root
Extensions to the {{Element}} Interface {#extensions-to-element}
----------------------------------------------------------------
-This section will be removed once the [[DOM]] specification had been modified.
+This section will be removed once the [[DOM]] specification had been modified.
We extend the {{Element}} interface as follows:
diff --git a/package-lock.json b/package-lock.json
index 050ee99..37bd89f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -187,9 +187,9 @@
"license": "MIT"
},
"node_modules/follow-redirects": {
- "version": "1.15.11",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
- "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
"funding": [
{
"type": "individual",
diff --git a/package.json b/package.json
index d17885c..832e40a 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
- "start": "http-server ./examples -c-1 -a 127.0.0.1 -p 8080 -o"
+ "build": "rm -rf public && mkdir -p public/demo-overlays && cd demo-overlays && npm run build && cd .. && cp -r examples public/examples && cp demo-overlays/demo-overlays.js demo-overlays/demo-overlays.js.map demo-overlays/demo-overlays.css public/demo-overlays/",
+ "start": "npm run build && http-server ./public -c-1 -a 127.0.0.1 -p 8080 -o /examples"
},
"author": "",
"license": "ISC"