相对于视口的元素位置,与滚动条无关(跨浏览器)

时间:2018-10-14 22:41:13

标签: javascript html css dom scrollbar

我正在搜索一种跨浏览器解决方案,以获取元素在视口中的确切左/右位置。与滚动条无关

我在网上找到的所有解决方案都提供了从滚动条的右/左边缘(如果有)而不是从视口边缘开始计算偏移量的解决方案。 我想从浏览器视口的边缘向左/向右偏移

如果没有滚动条,就没有问题。我可以从视口获得左右位置。

如果有一个滚动条,例如在html标记的左侧,如果element浮动在左侧,则其偏移量将为0,但是我想向左偏移滚动条的宽度(IE 16像素,Chrome 17像素...),它是距视口左边缘的实际偏移量。

scrollbar and element on the left

scrollbar and element on the right

我们在这些图片上可以看到,左偏移量为0(但应为滚动条的宽度,在IE上为16px),而右偏移量没有任何计算方法。确实,当元素向右浮动时,它将始终具有窗口innerWidth的大小或body.clientWidth(+ element.clientWidth)的大小向左偏移,无论是否滚动条在左侧还是右侧...

使用clientLeft是一个不错的解决方案,但它与Safari,Edge和IE不兼容。

另一个可能的解决方案是使用getBoundingClientRect().x,但是兼容性非常有限。不幸的是,this table的x / y属性主要是错误的。确切的兼容性是:

  • IE =>无法正常工作
  • Safari => v11或更高版本
  • Opera => v48或更高版本
  • Chrome => v61或更高版本
  • Firefox => v52或更高版本
  • Edge =>不起作用

注意:要测试并制作左侧/右侧的滚动条/元素,您可以使用以下代码段:

<!DOCTYPE html>
<html dir="ltr">

<head>
  <meta charset="utf-8">
  <title></title>
  <style>
    html,
    body {
      height: 100%;
      padding: 0;
      margin: 0;
      overflow: hidden;
    }
    
    body {
      overflow-y: auto;
    }
    
    p {
      width: 300px;
      margin: 0 auto;
      font-size: 2em;
      text-align: justify;
    }
    
    #sc {
      position: relative;
      float: right;
      width: 50px;
      height: 50px;
      background-color: red;
    }
  </style>
</head>

<body>
  <div id="sc"></div>
  <button id="toggle_scrollbar">toggle rtl / ltr</button>
  <button id="toggle_sc">toggle sc element</button>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
    eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>


  <script>
    var html = document.getElementsByTagName('html')[0];
    var body = document.getElementsByTagName('body')[0];
    var sc = document.getElementById('sc');
    sc.style.float = 'right';
    
    var toggle_scrollbar = document.getElementById('toggle_scrollbar');
    toggle_scrollbar.addEventListener('click', function (e) {
      html.setAttribute('dir', (html.getAttribute('dir') === 'rtl') ? 'ltr' : 'rtl');
      display();
    });
    
    var toggle_sc = document.getElementById('toggle_sc');
    toggle_sc.addEventListener('click', function (e) {
      sc.style.float = (sc.style.float === 'right') ? 'left' : 'right';
      display();
    });

    function display () {
      console.log('window.pageXOffset ---> ', window.pageXOffset);
      console.log('window.scrollX ---> ', window.scrollX);
      console.log('window.innerWidth ---> ', window.innerWidth);
      console.log('window.outerWidth ---> ', window.outerWidth);
      console.log('element.offsetLeft ---> ', sc.offsetLeft);
      console.log('element.scrollLeft ---> ', sc.scrollLeft);
      console.log('element.clientLeft ---> ', sc.clientLeft);
      console.log('element.clientWidth ---> ', sc.clientWidth);
      console.log('element.getBoundingClientRect().left ---> ', sc.getBoundingClientRect().left);
      console.log('element.getBoundingClientRect().x ---> ', sc.getBoundingClientRect().x);
      console.log('body.offsetLeft ---> ', body.offsetLeft);
      console.log('body.scrollLeft ---> ', body.offsetLeft);
      console.log('body.clientLeft ---> ', body.clientLeft);
      console.log('body.clientWidth ---> ', body.clientWidth);
      console.log('body.getBoundingClientRect().left ---> ', body.getBoundingClientRect().left);
      console.log('body.getBoundingClientRect().x ---> ', body.getBoundingClientRect().x);
      console.log('document.documentElement.offsetLeft ---> ', document.documentElement.offsetLeft);
      console.log('document.documentElement.scrollLeft ---> ', document.documentElement.scrollLeft);
      console.log('document.documentElement.clientLeft ---> ', document.documentElement.clientLeft);
      console.log('document.documentElement.clientWidth ---> ', document.documentElement.clientWidth);
      console.log('html.offsetLeft ---> ', html.offsetLeft);
      console.log('html.scrollLeft ---> ', html.offsetLeft);
      console.log('html.clientLeft ---> ', html.clientLeft);
      console.log('html.clientWidth ---> ', html.clientWidth);
      console.log('html.getBoundingClientRect().left ---> ', html.getBoundingClientRect().left);
      console.log('html.getBoundingClientRect().x ---> ', html.getBoundingClientRect().x);
    }
  </script>
</body>

</html>

(我更改了body标签上的滚动条使其可以在chrome / Firefox上运行,但是当滚动也位于html标签上时,我也在寻找解决方案)

有人有找到跨浏览器解决方案的想法吗?预先谢谢你。

0 个答案:

没有答案