ryoakg
2/16/2017 - 6:25 PM

differences between offsetTop, clientTop, scrollTop, offsetLeft ...

differences between offsetTop, clientTop, scrollTop, offsetLeft ...

<style>
 body{
   background-color: #ddd;
 }
 .container{
   height:200px;
   width: 400px;

   border-style:dashed;
   border-color:#aaa;

   margin:150px auto;

   /* overflow:hidden; */
   overflow:scroll;
 }
 .content{
   width:640px;
   height:292px;
   background-image: url(https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Leonardo_Da_Vinci_-_Annunciazione.jpeg/320px-Leonardo_Da_Vinci_-_Annunciazione.jpeg);
   background-size: 640px 292px;
 }
 .scroll-x {
   background-color: rgba(0,0,0,0);
   border:2px;
   border-style:solid;
   border-color:#00c;
   color:#00c;
   position:absolute;
 }
 .client-x {
   background-color: rgba(0,0,0,0);
   border-top-width:0;  border-left-width:0;
   border-bottom-width:2px; border-right-width:2px;
   border-style:solid;
   border-color:#0c0;
   color:#0c0;
   position:absolute;
 }
 .offset-x {
   background-color: rgba(0,0,0,0);
   border-top-width:2px;  border-left-width:2px;
   border-bottom-width:0; border-right-width:0;
   border-style:solid;
   border-color:#f00;
   color:#f00;
   position:absolute;
 }
</style>

<form id="container-border-control" action="javascript:false">
  <label for="value">border-width:</label>
  <input type="text" name="value">
  <button type="button" name="swap">swap !</button>
</form>
<button id="scroll-button">scroll !</button>
<div id="container" class="container">
  <div class="content"></div>
</div>


<p>
  <a href="https://commons.wikimedia.org/wiki/Commons:Reuse_of_PD-Art_photographs#Japan">Reuse of PublicDomain-Art photographs</a>
</p>

see also:
<ul>
  <li><a href="http://stackoverflow.com/questions/22675126/what-is-offsetheight-clientheight-scrollheight/22675563#22675563">What is offsetHeight, clientHeight, scrollHeight? | stackoverflow</a></li>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop">offsetTop | MDN</a></li>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/clientTop">clientTop | MDN</a></li>
  <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop">scrollTop | MDN</a></li>
  <li><a href="http://jsfiddle.net/shibualexis/yVhgM/3/">http://jsfiddle.net/shibualexis/yVhgM/3/</a></li>
</ul>

<script>
 (function(){
   var container = document.getElementById('container');
   var refreshes = [];
   container.style.borderWidth = 20; // initial value
   var container_border_ctrl = document.getElementById('container-border-control');
   container_border_ctrl.elements.value.value = container.style.borderWidth;
   container_border_ctrl.elements.swap.addEventListener('click',function(){
     container.style.borderWidth = container_border_ctrl.elements.value.value;
   });

   function refresh(src, dest, echo, prop_prefix, compute_left, compute_top) {
     var width_prop  = prop_prefix+'Width';
     var height_prop = prop_prefix+'Height';
     var top_prop  = prop_prefix+'Top';
     var left_prop = prop_prefix+'Left';

     dest.style.left       = compute_left(src) + 'px';
     dest.style.top        = compute_top(src) + 'px';
     dest.style.height     = src[height_prop]+'px';
     dest.style.width      = src[width_prop] +'px';
     echo.innerHTML = width_prop + ' X ' + height_prop +
                      '( ' + src[width_prop] + ' x '+ src[height_prop] + " ),<br />" +
                        top_prop + ' X ' + left_prop +
                        '( ' + src[top_prop] + ' x '+ src[left_prop] + ' )';
   }

   refreshes.push((function(){
     var frame = document.createElement("div");
     var echo  = document.createElement("div");
     document.body.appendChild(frame);

     frame.appendChild(echo);
     frame.classList.add('offset-x');

     echo.style.marginTop = '-2.5em';

     var $refresh = refresh.bind(null, container, frame, echo, 'offset',
                                 function(elm){return elm.offsetLeft;},
                                 function(elm){return elm.offsetTop;});
     return $refresh;
   })());

   refreshes.push((function(){
     var frame = document.createElement("div");
     var echo  = document.createElement("div");
     document.body.appendChild(frame);

     frame.appendChild(echo);
     frame.classList.add('client-x');

     echo.style.position = 'absolute';
     echo.style.bottom = 0;
     echo.style.right = 0;
     echo.style.marginBottom = '-4.5em';

     var $refresh = refresh.bind(null, container, frame, echo, 'client',
                                 function(elm){return elm.offsetLeft + elm.clientLeft;},
                                 function(elm){return elm.offsetTop  + elm.clientTop;});
     return $refresh;
   })());

   refreshes.push((function(){
     var frame = document.createElement("div");
     var echo  = document.createElement("div");
     document.body.appendChild(frame);

     frame.appendChild(echo);
     frame.classList.add('scroll-x');

     echo.style.position = 'absolute';
     echo.style.bottom = 0;
     echo.style.right = 0;
     echo.style.marginBottom = '-2.5em';

     var $refresh = refresh.bind(null, container, frame, echo, 'scroll',
                                 function(elm){return elm.offsetLeft + elm.clientLeft - elm.scrollLeft;},
                                 function(elm){return elm.offsetTop  + elm.clientTop  - elm.scrollTop;});
     window.addEventListener('resize',$refresh);
     $refresh();

     document.getElementById('scroll-button').onclick = function(){
       (new Promise(function(next) {
         var max = container.scrollWidth - container.clientWidth
         var step = Math.floor(max / 20);
         function loop(amount){
           $refresh();
           setTimeout(function() {
             container.scrollLeft = amount;
             if (amount < max) loop(Math.min(amount+step, max));
             else              next();
           }, 100);
         }
         loop(0);
       })).then(function() {
         return new Promise(function(next) {
           var max = container.scrollHeight - container.clientHeight;
           var step = Math.floor(max / 20);
           function loop(amount){
             $refresh();
             setTimeout(function() {
               container.scrollTop = amount;
               if (amount < max) loop(Math.min(amount+step, max));
               else              next();
             }, 100);
           }
           loop(0);
         });
       }).then(function () {
         return new Promise(function(next) {
           var top_step  = Math.floor(container.scrollTop  / 20);
           var left_step = Math.floor(container.scrollLeft / 20);
           function loop(amount_top, amount_left){
             $refresh();
             setTimeout(function() {
               container.scrollTop  = amount_top;
               container.scrollLeft = amount_left;
               if (amount_top >= 0) loop(Math.max(amount_top  - top_step, 0),
                                         Math.max(amount_left - left_step, 0));
             }, 100);
           }
           loop(container.scrollTop, container.scrollLeft);
         });
       })
     }
     return $refresh;
   })());

   refreshes.forEach(function(r){
     r();
     window.addEventListener('resize',r);
     container_border_ctrl.elements.swap.addEventListener('click', setInterval.bind(null,r,0));
   });
 })();
</script>