Container Timing API

Editor’s Draft,

More details about this document
This version:
https://bloomberg.github.io/container-timing/
Test Suite:
https://github.com/web-platform-tests/wpt/tree/master/container-timing
Issue Tracking:
GitHub
Editors:
Jason Williams (Bloomberg)
(Igalia)

Abstract

This specification defines an API that enables monitoring when annotated sections of the DOM are displayed on screen and have finished their initial paint.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

GitHub Issues are preferred for discussion of this specification.

This document is governed by the 18 August 2025 W3C Process Document.

1. Introduction

The Container Timing API enables monitoring when annotated sections of the DOM are displayed on screen and have finished their initial paint. A developer can mark subsections of the DOM with the containertiming attribute (similar to elementtiming for the Element Timing API) and receive performance entries when that section has been painted for the first time.

This API allows developers to measure the timing of various components in their pages. As developers increasingly organize their applications into components, there’s a growing demand to measure performance on subsections of an application or a web page.

Unlike Element Timing, it is not possible for the renderer to know when a section of the DOM has finished painting (there could be future changes, asynchronous requests for new images, slow loading buttons, etc.), so this API emits candidates in the form of PerformanceEntry objects when there has been an update.

2. Motivation

Developers want to measure when subsections of the DOM have been painted, such as tables, widgets, or other components, so they can track paint times and submit them to analytics. Current Web APIs don’t adequately support this:

Web authors know their domain better than anyone else and want to communicate the performance of their own content blocks in ways their users or organization would understand (e.g., "time to first tweet").

3. Usage Example

The following example demonstrates how to register a container root and observe its paint timings.

Registration is on a per-element basis using the containertiming attribute:
<div containertiming="foobar">
  <main>...</main>
  <aside>...</aside>
</div>

<script>
  const observer = new PerformanceObserver((list) => {
    let perfEntries = list.getEntries();
    for (const entry of perfEntries) {
      console.log('Container painted:', entry.identifier,
                  'at', entry.startTime,
                  'size:', entry.size);
    }
  });
  observer.observe({ entryTypes: ["container"] });
</script>

The attribute should be set before the element is added to the document (in HTML, or if set in JavaScript, before adding it to the document). Setting the attribute retroactively will only capture subsequent events and future paints.

3.1. Ignoring Subtrees

Parts of the DOM tree can be ignored using the containertiming-ignore> attribute:
<div containertiming="foobar">
  <main>...</main>
  <!-- Aside updates won't trigger container timing events -->
  <aside containertiming-ignore>...</aside>
</div>

4. Terminology

A container root is an Element that has the containertiming attribute.

An ignored subtree is a subtree rooted at an Element with the containertiming-ignore> attribute.

A painted region is a region (collection of rectangles) representing all the painted portions of a container root accumulated since it was first observed.

The container timing API provides timing information about when container roots are painted to the screen.

5. The PerformanceContainerTiming Interface

[Exposed=Window]
interface PerformanceContainerTiming : PerformanceEntry {
    readonly attribute DOMString identifier;
    readonly attribute DOMRectReadOnly intersectionRect;
    readonly attribute unsigned long long size;
    readonly attribute DOMHighResTimeStamp firstRenderTime;
    readonly attribute Element? lastPaintedElement;
};
A PerformanceContainerTiming object reports timing information for a container root.

The identifier attribute returns the value of the containertiming attribute of the container root.

The intersectionRect attribute returns a DOMRectReadOnly representing the bounding box of all paints accumulated so far within this container root.

The size attribute returns the size in pixels of the combined painted region within this container root.

The firstRenderTime attribute returns a DOMHighResTimeStamp indicating when the container root was first painted.

The lastPaintedElement attribute returns the Element that was most recently painted within the container root, or null if no element has been painted yet.

The entryType attribute must return "container".

The name attribute must return the empty string.

The startTime attribute must return the DOMHighResTimeStamp of the latest paint time for this container root.

The duration attribute must return 0.

6. Processing Model

Note: A user agent implementing the Container Timing API would need to include "container" in supportedEntryTypes for Window contexts. This allows developers to detect support for container timing.

6.1. Extensions to the Element Interface

partial interface Element {
    [CEReactions] attribute DOMString containertiming;
    [CEReactions] attribute DOMString? containertimingIgnore;
};
The containertiming attribute is a DOMString that identifies the element as a container root. The value becomes the identifier in the corresponding PerformanceContainerTiming entry.

The containertiming-ignore attribute, when present, marks the element and its descendants as an ignored subtree that should not contribute to container timing measurements for ancestor container roots.

6.2. Registering Container Roots

When an Element with a [^containertiming^] content attribute is connected to the document:

  1. The user agent must register the element as a container root.

  2. The user agent must initialize an empty painted region for the container root.

  3. The user agent must track all paint operations within the container root’s subtree, excluding any ignored subtrees.

6.3. Reporting Paint Updates

When the rendering engine paints one or more elements within a container root:

To report a container paint given a container root containerRoot and a list of painted rectangles rects:
  1. Let paintedRegionUpdated be false.

  2. Let renderTime be the current high resolution time.

  3. Let firstRenderTime be containerRoot’s stored first render time, or renderTime if not yet set.

  4. If containerRoot does not have a stored first render time, set it to firstRenderTime.

  5. Let paintedRegion be the painted region associated with containerRoot.

  6. Let lastPaintedElement be null.

  7. For each rectangle rect in rects:

    1. If rect is within an ignored subtree, continue to the next rect.

    2. If paintedRegion already fully contains rect, continue to the next rect.

    3. Set paintedRegionUpdated to true.

    4. Set paintedRegion to the union of paintedRegion and rect.

    5. Set lastPaintedElement to the Element associated with rect.

  8. If paintedRegionUpdated is false, return.

  9. Queue a PerformanceContainerTiming entry with:

    • identifier: the value of containerRoot’s containertiming attribute

    • startTime: renderTime

    • firstRenderTime: firstRenderTime

    • intersectionRect: the bounding rectangle of paintedRegion

    • size: the total area of paintedRegion

    • lastPaintedElement: lastPaintedElement

To queue a PerformanceContainerTiming entry given identifier, startTime, firstRenderTime, intersectionRect, size, and lastPaintedElement:
  1. Let entry be a new PerformanceContainerTiming object with:

  2. Queue the PerformanceEntry entry

  3. Do not add entry to the performance timeline buffer.

Note: Container timing entries are only delivered to PerformanceObservers and are not added to the Performance Timeline buffer to avoid memory overhead from potentially frequent updates.

7. Security and Privacy Considerations

7.1. Cross-Origin Restrictions

The API respects cross-origin boundaries:

7.2. Information Exposure

Most information provided by this API can already be estimated through existing APIs:

The API does not expose:

7.3. Timing Attacks

The API uses DOMHighResTimeStamp which may be subject to resolution limitations for security purposes, consistent with other Performance APIs.

7.4. Privacy Considerations

The API does not:

8. Acknowledgments

Many thanks for valuable feedback and advice from:

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[GEOMETRY-1]
Simon Pieters; Chris Harrelson. Geometry Interfaces Module Level 1. URL: https://drafts.fxtf.org/geometry/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[PERFORMANCE-TIMELINE]
Nicolas Pena Moreno. Performance Timeline. URL: https://w3c.github.io/performance-timeline/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

IDL Index

[Exposed=Window]
interface PerformanceContainerTiming : PerformanceEntry {
    readonly attribute DOMString identifier;
    readonly attribute DOMRectReadOnly intersectionRect;
    readonly attribute unsigned long long size;
    readonly attribute DOMHighResTimeStamp firstRenderTime;
    readonly attribute Element? lastPaintedElement;
};

partial interface Element {
    [CEReactions] attribute DOMString containertiming;
    [CEReactions] attribute DOMString? containertimingIgnore;
};