- 1 year ago 180
Javascript Question

How to compute getBoundingClientRect() without considering transforms?

returns the coordinates of an element on the screen after being transformed. How do I calculate those coordinates before being transformed? i.e. without transforms.

The simplest way I found was: = 'none'; //temporarily reset the transform
var untransformedOffset = element.getBoundingClientRect().top; //get the value = ''; //set it back

but that causes slow layout thrashing, especially noticeable if done on many elements. Live demo:,console,output

Is there a better way?

That javascript code can be applied to:

<div id="element"></div>
<style> #element { transform: translateY(20px); }</style>

And the result will be 0 (excluding the page's margin)

The result of
will be 20 (excluding the page's margin)

Answer Source

Here is how I'm doing it :

var el = element,
offsetLeft = 0,
offsetTop  = 0;

    offsetLeft += el.offsetLeft;
    offsetTop  += el.offsetTop;

    el = el.offsetParent;
} while( el );

Just a reminder but this won't work if any of the parents has a transform applied to it.

Otherwise you could try to revert the transform. To do so you must first set transform-origin to 0,0,0 and surround yourself your transformation (scale, rotate) width translate(50%,50%) ... translate(-50%, -50%). Here is an example,
change that :

transform: scale(2) rotate(45deg) translate(20px);
transform-origin: 50% 50%; //default value


transform: translate(50%, 50%) scale(2) rotate(45deg) translate(-50%,-50%) translate(20px);
transform-origin: 0 0 0;

We need to do that because the matrix returned by getComputedStyle() does not include stuff done with transform-origin. Don't know really why.

Then you can use this code :

function parseTransform(transform){
    //add sanity check
    return transform.split(/\(|,|\)/).slice(1,-1).map( function(v){
        return parseFloat(v);

function convertCoord(transformArr, x, y, z){
    //add sanity checks and default values      

    if( transformArr.length == 6 ){
        //2D matrix
        //need some math to apply inverse of matrix
        var t = transformArr,
            det = t[0]*t[3] - t[1]*t[2];
        return {
            x: (  x*t[3] - y*t[2] + t[2]*t[5] - t[4]*t[3] )/det,
            y: ( -x*t[1] + y*t[0] + t[4]*t[1] - t[0]*t[5] )/det
    else /*if (transformArr.length > 6)*/{
       //3D matrix
       //haven't done the calculation to apply inverse of 4x4 matrix

var elRect = element.getBoundingClientRect(),
    st = window.getComputedStyle(element),

    topLeft_pos = convertCoord(
              parseTransform( st.transform ),

I won't explain the math part because I think it's beyond the scope of this post. Could still explain it somewhere else (another question maybe ? ).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download