JavaScript - getClientRects() method

revision:


Category : element

The getClientRects() method of the Element interface returns a collection of DOMRect objects that indicate the bounding rectangles for each CSS border box in a client.

Most elements only have one border box each, but a multiline inline-level element (such as a multiline <span> element, by default) has a border box around each line.

This is an experimental technology

Syntax :

        getClientRects()
    

Parameters:none

Examples:

          range = document.createRange();
          range.selectNode(document.getElementsByTagName("div").item(0));
          rectList = range.getClientRects();
        

Practical examples

example

A paragraph with a span inside

Both the span and the paragraph have a border set. The client rects are in red. Note that the p has only one border box, while the span has multipleborder boxes.

Original

Paragraph that spans multiple lines

p's rect

Paragraph that spans multiple lines

span's rect

Paragraph that spans multiple lines

A list

Note that the border box doesn't include the number, so neither do the client rects.

Original
  1. Item 1
  2. Item 2
ol's rect
  1. Item 1
  2. Item 2
each li's rect
  1. Item 1
  2. Item 2

A table with a caption

Although the table's border box doesn't include the caption, the client rects do include the caption.

Original
caption
thead
tbody
table's rect
caption
thead
tbody
code:
                <div>
                    <h3>A paragraph with a span inside</h3>
                    <p>Both the span and the paragraph have a border set. The client rects are in red. Note that the p
                    has only one border box, while the span has multipleborder boxes. </p>
                    <div class="rect-1">
                        <strong>Original</strong>
                        <p>
                            <span>Paragraph that spans multiple lines</span>
                        </p>
                    </div>
                    <div>
                        <strong>p's rect</strong>
                        <p class="withClientRectsOverlay">
                            <span>Paragraph that spans multiple lines</span>
                        </p>
                    </div>
                    <div>
                        <strong>span's rect</strong>
                        <p>
                            <span class="withClientRectsOverlay"
                            >Paragraph that spans multiple lines</span
                            >
                        </p>
                    </div>
                    <h3>A list</h3>
                    <p> Note that the border box doesn't include the number, so neither do the client rects. </p>
                    <div class="rect-1">
                        <strong>Original</strong>
                        <ol>
                            <li>Item 1</li>
                            <li>Item 2</li>
                        </ol>
                    </div>
                    <div class="rect-1">
                        <strong>ol's rect</strong>
                        <ol class="withClientRectsOverlay">
                            <li>Item 1</li>
                            <li>Item 2</li>
                        </ol>
                    </div>
                    <div class="rect-1">
                        <strong>each li's rect</strong>
                        <ol>
                            <li class="withClientRectsOverlay">Item 1</li>
                            <li class="withClientRectsOverlay">Item 2</li>
                        </ol>
                    </div>
                    <h3>A table with a caption</h3>
                    <p>Although the table's border box doesn't include the caption, the client rects do include the caption. </p>
                    <div class="rect-1">
                      <strong>Original</strong>
                      <table>
                        <caption>
                          caption
                        </caption>
                        <thead>
                          <tr>
                            <th>thead</th>
                          </tr>
                        </thead>
                        <tbody>
                          <tr>
                            <td>tbody</td>
                          </tr>
                        </tbody>
                      </table>
                    </div>
                    <div class="rect-1">
                      <strong>table's rect</strong>
                      <table class="withClientRectsOverlay">
                        <caption>
                          caption
                        </caption>
                        <thead>
                          <tr>
                            <th>thead</th>
                          </tr>
                        </thead>
                        <tbody>
                          <tr>
                            <td>tbody</td>
                          </tr>
                        </tbody>
                      </table>
                    </div>
                </div>
                <style>
                    strong { text-align: center;}
                    div .rect-1 { display: inline-block; width: 15vw;}
                    div.rect-1 p, ol, table {border: 0.1vw solid blue;}
                    span, li, th, td {border: 0.1vw solid green;}
                </style>
                <script>
                    function addClientRectsOverlay(elt) {
                    /* Absolutely position a div over each client rect so that its border width is the same as the rectangle's width.
                        Note: the overlays will be out of place if the user resizes or zooms. */
                        const rects = elt.getClientRects();
                        for (const rect of rects) {
                            const tableRectDiv = document.createElement("div");
                            tableRectDiv.style.position = "absolute";
                            tableRectDiv.style.border = "1px solid red";
                            const scrollTop =
                            document.documentElement.scrollTop || document.body.scrollTop;
                            const scrollLeft =
                            document.documentElement.scrollLeft || document.body.scrollLeft;
                            tableRectDiv.style.margin = tableRectDiv.style.padding = "0";
                            tableRectDiv.style.top = `${rect.top + scrollTop}px`;
                            tableRectDiv.style.left = `${rect.left + scrollLeft}px`;
                            // We want rect.width to be the border width, so content width is 2px less.
                            tableRectDiv.style.width = `${rect.width - 2}px`;
                            tableRectDiv.style.height = `${rect.height - 2}px`;
                            document.body.appendChild(tableRectDiv);
                        }
                    }
                    (() => {
                        /* Call function addClientRectsOverlay(elt) for all elements with
                            assigned class "withClientRectsOverlay" */
                        const elts = document.getElementsByClassName("withClientRectsOverlay");
                        for (const elt of elts) {
                            addClientRectsOverlay(elt);
                        }
                    })();
                    
                </script>