How many of the five Observer browsers have you used?

In web development, we often deal with user interaction. We will use addEventListener to add event listeners to listen to various user operations, such as click, mousedown, mousemove, input, etc., which are directly triggered by users.

What about some events that are not triggered directly by the user? For example, how to listen to such events as invisible elements, changes in element size, modification of element attributes and child nodes?

The browser provides five kinds of observers to monitor these changes: MutationObserver, IntersectionObserver, PerformanceObserver, ResizeObserver and ReportingObserver.

Let's take a look at:


How can an element be monitored when it is invisible or invisible?

Use IntersectionObserver.

IntersectionObserver can monitor the proportion of the intersection between an element and the visual area, and then trigger a callback when the visual proportion reaches a certain threshold.

We prepare two elements:

<div id="box1">BOX111</div>
<div id="box2">BOX222</div>

Add style:

#box1,#box2 {
    width: 100px;
    height: 100px;
    background: blue;
    color: #fff;

    position: relative;
#box1 {
    top: 500px;
#box2 {
    top: 800px;

These two elements are at the height of 500 and 800 px respectively, and we listen for changes in their visibility.

const intersectionObserver = new IntersectionObserver(
    function (entries) {
        entries.forEach(item => {
            console.log(, item.intersectionRatio)
    }, {
    threshold: [0.5, 1]

intersectionObserver.observe( document.querySelector('#box1'));
intersectionObserver.observe( document.querySelector('#box2'));

Create an IntersectionObserver object, listen to box1 and box2 elements, and trigger a callback when the visible ratio reaches 0.5 and 1.

Run the browser:

You can see that elements box1 and box2 trigger callbacks when the visual range reaches half (0.5) and all (1), respectively.

What's the use?

This is so useful. When we do some data collection, we want to know whether an element is visible and when it is visible. We can use this api to monitor. When we do lazy loading of pictures, we can trigger loading when the visual proportion reaches a certain proportion.

In addition to monitoring element visibility, you can also monitor the changes of element attributes and child nodes:


To monitor the changes of an ordinary JS object, we will use object Defineproperty or Proxy:

To monitor the changes of element attributes and child nodes, we can use MutationObserver:

MutationObserver can monitor the modification of element attributes and the addition, deletion and modification of its child nodes.

We prepare such a box:

<div id="box"><button>light</button></div>

Add style:

 #box {
    width: 100px;
    height: 100px;
    background: blue;

    position: relative;

That's it:

We modify it regularly:

setTimeout(() => { = 'red';

setTimeout(() => {
    const dom = document.createElement('button');
    dom.textContent = 'Dongdongdong';

setTimeout(() => {

Change the background color to red in 2s, add a sub element of button in 3s, and delete the first button in 5s.

Then monitor its changes:

const mutationObserver = new MutationObserver((mutationsList) => {

mutationObserver.observe(box, {
    attributes: true,
    childList: true

Create a MutationObserver object to listen for changes in the attributes and child nodes of the box.

Run the browser:

It can be seen that some information is monitored and printed during the three changes:

The first change is attributes, which is style:

The second change is childList, which adds a node:

The third time is to change the childList and delete a node:

I heard it!

What can this be used for? For example, if the article watermark is removed through devtools, you can monitor the change through MutationObserver, and then add it again so that the watermark cannot be removed.

Of course, there are many other uses. Here are just functions.

In addition to listening for changes in element visibility, attributes and child nodes, you can also listen for changes in size:


In the window, we can use addEventListener to listen to the resize event. What about the element?

The element can use ResizeObserver to monitor the change of size. When the width and height are modified, a callback will be triggered.

We prepare such an element:

<div id="box"></div>

Add style:

#box {
    width: 100px;
    height: 100px;
    background: blue;

Modify its height at 2s:

const box = document.querySelector('#box');

setTimeout(() => { = '200px';
}, 3000);

Then we use ResizeObserver to monitor its changes:

const resizeObserver = new ResizeObserver(entries => {
    console.log('Current size', entries)

Run in the browser:

The size change is monitored. Look at the printed information:

You can get the element and its position and size.

In this way, we have realized the listening for the resize of elements.

In addition to monitoring the changes of element size, visibility and attribute child nodes, it also supports the monitoring of performance recording behavior:


The browser provides an api for performance, which is used to record some time points, a certain time period, the time-consuming of resource loading, etc.

We hope to report the performance data as soon as it is recorded, but how do we know when the performance data will be recorded?

Use PeformanceObserver.

PerformanceObserver is used to monitor the behavior of recording performance data. Once recorded, it will trigger a callback, so that we can report these data in the callback.

For example, performance can use the mark method to record a certain time point:


Use the measure method to record a time period:

performance.measure('button clicked', 'from', 'to');

The last two parameters are the time point, which means from the beginning to the present.

We can monitor them with PerformanceObserver:

  <button onclick="measureClick()">Measure</button>

  <img src="" />

    const performanceObserver = new PerformanceObserver(list => {
      list.getEntries().forEach(entry => {
        console.log(entry);// Report
    performanceObserver.observe({entryTypes: ['resource', 'mark', 'measure']});


    function measureClick() {
      performance.measure('button clicked');

Create a PerformanceObserver object to listen to mark, measure and resource, which record time.

Then we use mark to record a certain time point. When we click button, we use measure to record the data of a certain time period and load a picture.

When these recording behaviors occur, we hope to trigger a callback, which can be reported.

Let's try it in the browser:

You can see that the time point record of mark, the time-consuming of resource loading and the measure time period record of clicking the button are all monitored.

The data of these three recording behaviors are printed respectively:


Picture loading:


With these data, you can report them for performance analysis.

In addition to elements and performance, the browser also has a listening function for reporting:


When the browser runs to the deprecation api, an obsolete report will be printed on the console:

The browser will also intervene in web page behavior in some cases, such as deleting iframe of advertisements that occupy too much cpu:

When the network is slow, the image will be replaced with a placeholder image, which will be loaded only after clicking:

These interventions are done by the browser, and a report will be printed on the console:

These interventions or outdated APIs are not error reports, so they cannot be obtained by error monitoring, but these situations may also be very important for web app s:

For example, my website is to display advertisements, but as soon as the browser intervened, I deleted the advertisements, but I didn't know. If I know, maybe I can optimize iframe.

For example, the image of my web page is very important. As a result, as soon as the browser intervened, I changed it to a bitmap, but I didn't know. If I know, I may optimize the image size.

Therefore, it is natural to listen. Therefore, the browser provides the api of ReportingObserver to listen to the printing of these reports. We can get these reports and upload them.

const reportingObserver = new ReportingObserver((reports, observer) => {
    for (const report of reports) {
}, {types: ['intervention', 'deprecation']});


ReportingObserver can monitor the printing of outdated api, browser intervention and other reports, and report them in the callback. These are data that cannot be monitored by error monitoring, but are very useful for understanding the operation of web pages.

The code in the article is uploaded to GitHub:


To monitor user interaction behavior, we will use addEventListener to monitor click, mousedown, keydown, input and other events, but for element changes, performance records, browser intervention behavior and other events that are not user interaction, we need to use the api of xxobserver.

The browser provides five kinds of observers:

  • IntersectionObserver: monitors the visibility changes of elements. It is often used for data collection of element display and lazy loading of pictures
  • MutationObserver: monitors the changes of element attributes and child nodes, such as watermarks that can not be removed
  • ResizeObserver: listen for element size changes

There are also two independent elements:

  • PerformanceObserver: monitor the behavior of performance records to report data
  • ReportingObserver: monitoring reports of outdated APIs and browser interventions can give us a more comprehensive understanding of the operation of web app s

These APIs are less used than the interactive events added by addEventListener, but they are very useful in specific scenarios.

How many of the five Observer browsers have you used? Under what circumstances has it been used? Let's discuss it.

Added by rupturedtoad on Thu, 03 Mar 2022 11:54:06 +0200