0

The DOM-API method Element.getBoundingClientRect returns the bounds of an element. Unfortunately, this is not necessarily the bounds to which content is actually rendered. Given the following examples shows there is a discrepancy:

<html>
<head>
    <style>
        #float { float: left; }
    </style>
    <script>
        function info() {
            const boundFirst = document.getElementById('first').getBoundingClientRect();
            const boundScnd = document.getElementById('scnd').getBoundingClientRect();
            alert("First x: " + boundFirst.x + "; second x: " + boundScnd.x);
        }
    </script>
</head>
<body>
    <p id="first">First</p>
    <p id="float">XXXXX</p><p id="scnd">Second</p>

    <p onclick="info()">Info</p>
</body>
</html>

The text is rendered as follows (more or less):

First
XXXXX Second
Info

Clicking on Info shows the following message:

First x: 8; second x: 8

However, obviously the text content of the second paragraph is not rendered at the same x location as the text content of the first paragraph.

How can I determine the actual location of the (second) rendered text?

I found a workaround, which does not work in all cases by simply adding an empty span as first element to the paragraphs and retrieving the location of that span. But this does not work in all cases and the span may have some other side effects as well.

Context: I need that functionality for tests (using selenium webdriver). I also tried the webdriver's API function WebElement.getRect, but that returns the same result as getBoundingClientRect (which is used under the hood according to its documentation).

My question is not about fixing the layout, it is about retrieving the coordinates of the displayed text for testing purposes (e.g., for finding broken layouts).

Jens
  • 299
  • 2
  • 7
  • When I put your HTML into a file, load it in the browser, opened the dev console, and hovered over the "Second" line, it actually shows the element extending all the way to the left edge of the screen which corresponds to x: 8 that it's displaying. – JeffC Feb 21 '23 at 06:04

1 Answers1

0

I'm not the right person to explain why both elements are returning x: 8. My guess is that the second *element* actually extends to the left edge of the screen and that's why it's also returning 8 while the text is out floating to the right.

Having said that, I ended up finding a hack/workaround to get the correct coords. While trying to find an alternative JS method to get the correct coords, I ran across another SO answer that had code to retrieve the coords for selected text on the page. Once I had that, I just added to code to double-click the "Second" element which selects the desired text and then get the x-coord of the selection.

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var e = wait.Until(ExpectedConditions.ElementToBeClickable(By.Id("scnd")));
new Actions(driver).DoubleClick(e).Perform();
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
Console.WriteLine((double)js.ExecuteScript("return window.getSelection().getRangeAt(0).getClientRects()[0].x"));

I've tested this on your provided HTML and it's working. I even added/removed some more Xs to move the text around and verified that the x value is changing.

JeffC
  • 22,180
  • 5
  • 32
  • 55