elewinso
elewinso

Reputation: 2521

getBoundingClientRect not working as expected on body after transform

$( document ).ready(function() {
		
    $('body').append('<div id="tester2"></div>');
    $('#tester2').css({
    	position:'absolute',
      background:'blue',
      width: 10,
      height:10
    });
    setInterval(function(){ 
      var x = $('#tester')[0].getBoundingClientRect();
      $('#tester-pos').text('top: ' + x.top + ', left:' + x.left);
      $('#tester2').css({
	      top:x.top,
  	    left:x.left
    	});
    }, 1000);
    
    $('#jquery-version').text('jquery version: ' + $.fn.jquery);
});
#tester{
  position:absolute;
  top:50px;
  left:50px;
  width:10px;
  height:10px;
  background:red;
}

#page{
  min-height:200px;
}

body{
  border:2px solid green;
  transform: scale(1) translate(20px, 40px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="tester">
</div>
<div id="page">
getBoundingClientRect on red tester returned:
<span id="tester-pos"></span>
<div id="jquery-version"></div>
</div>

I need to place a div over an existing div. The existing div is contained inside the body of and HTML document that has the CSS transform property set. I need to place the new div after the document was rendered and transformed.

When I call getBoundingClientRect() on the div that I need to hide (red square in attached fiddle) I get the wrong top/left. I set the top/left of the blue square to the output of getBoundingClientRect() and they do not overlap.

setInterval(function(){ 
    var x = $('#tester')[0].getBoundingClientRect();
    $('#tester-pos').text('top: ' + x.top + ', left:' + x.left);
    $('#tester2').css({
        top:x.top,
        left:x.left
    });
}, 1000);

How can this be solved?

Upvotes: 2

Views: 10920

Answers (2)

sabithpocker
sabithpocker

Reputation: 15566

You can just take the offsetTop and offsetLeft without worrying about the transform as the same transform is applied to the newly added div as well. I'm guessing that from the example.

$(document).ready(function() {

  $('body').append('<div id="tester2"></div>');
  $('#tester2').css({
    position: 'absolute',
    background: 'blue',
    width: 10,
    height: 10,
    opacity: 0.6
  });
  var tester = document.getElementById('tester');
  $('#tester2').css({
    top: tester.offsetTop - 2, // 2px border for body
    left: tester.offsetLeft - 2
  });

  $('#jquery-version').text('jquery version: ' + $.fn.jquery);
});
#tester {
  position: absolute;
  top: 50px;
  left: 50px;
  width: 10px;
  height: 10px;
  background: red;
}

#page {
  min-height: 200px;
}

body {
  border: 2px solid green;
  transform: scale(1) translate(20px, 40px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="tester">
</div>
<div id="page">
  getBoundingClientRect on red tester returned:
  <span id="tester-pos"></span>
  <div id="jquery-version"></div>
</div>

Upvotes: 1

JO3-W3B-D3V
JO3-W3B-D3V

Reputation: 2134

I have an answer that works, it may not be the best answer yet, but it works 100% for me.

$( document ).ready(function() {
		
    $('body').append('<div id="tester2"></div>');
    $('#tester2').css({
    	position:'absolute',
      background:'blue',
      width: 10,
      height:10,
    });
    
    setInterval(function(){ 
      var x = $('#tester')[0].getBoundingClientRect();
      $('#tester-pos').text('top: ' + x.top + ', left:' + x.left);
      $('#tester2').css({
	      'top':x.top/2,
  	    'left':(x.left/2)+x.width
    	});
    }, 1000);
    
    $('#jquery-version').text('jquery version: ' + $.fn.jquery);
	});
#tester{
  position:absolute;
  top:50px;
  left:50px;
  width:10px;
  height:10px;
  background:red;
}

#page{
  min-height:200px;
}

body{
  border:2px solid green;
  transform: scale(1) translate(20px, 40px);
}

#tester2{
  transform: scale(1) translate(0, 0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="tester">
</div>
<div id="page">
getBoundingClientRect on red tester returned:
<span id="tester-pos"></span>
<div id="jquery-version"></div>
</div>


Edit

The only time that my potential solution gets a bit weird is when you have to scroll... So be warned there.

Upvotes: 0

Related Questions