2

$( 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?

dllhell
  • 1,987
  • 3
  • 34
  • 51
elewinso
  • 2,453
  • 5
  • 22
  • 27

2 Answers2

1

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>
sabithpocker
  • 15,274
  • 1
  • 42
  • 75
  • but what if the tester is inside another container with position:relative. the offsetTop will be relative to it and not the entire body as I need it to be. – elewinso Nov 15 '17 at 10:09
  • You can append the new `div` as a sibling to the existing one instead of adding it to body, that way the same position can be used and it will inherit all other transformations as well. – sabithpocker Nov 16 '17 at 07:36
0

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.

JO3-W3B-D3V
  • 2,124
  • 11
  • 30