• 你真的懂offset与scroll吗?


    背景

    身为一个前端工程师,每次在做关于滚动或者定位之类的交互时,或多或少都会用到offset、scroll之类的元素属性值来计算距离,但是每次都是现用现百度,从来没有真正系统地弄明白其中的原理及用法;在马上十一国庆假期以及项目压力较小的情况下,特作此篇总结以弥补相关知识的缺失

    offset相关

    以offset开头的属性有5个,分别是:offsetParentoffsetWidthoffsetHeightoffsetTop以及offsetLeft,下面我们来一一了解它们

    1.offsetParent

    代码

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <meta charset="utf-8" />
     5   <title>offsetParent</title>
     6   <style>
     7 
     8   </style>
     9 </head>
    10 <body>
    11 <!--1.除了浏览器默认的,我们没有设置任何样式-->
    12 <div id="outer">
    13   <div id="inner">
    14     我是div
    15   </div>
    16 </div>
    17 <script>
    18   // 2.我们看看id="inner"元素的offsetParent是哪一个
    19   var inner = document.getElementById('inner')
    20   console.log(inner.offsetParent)
    21 </script>
    22 </body>
    23 </html>

    运行结果

    offsetParent.png

    从控制台我们得到inner的offsetParent是body元素,那么就有问题了“inner的父元素是outer啊,但为什么offsetParent不是它?”,那是因为元素的offsetParent是距离它最近的一个具有定位的父辈元素,这里“具有定位”4个字很重要,如果你怀疑这个结论,那我们就再往下看

    代码

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <meta charset="utf-8" />
     5   <title>offsetParent</title>
     6   <style>
     7     /*这里我们给outer一个相对定位*/
     8     #outer {
     9       position: relative;
    10     }
    11   </style>
    12 </head>
    13 <body>
    14 <!--1.除了浏览器默认的,我们没有设置任何样式-->
    15 <div id="outer">
    16   <div id="inner">
    17     我是div
    18   </div>
    19 </div>
    20 <script>
    21   // 2.我们看看id="inner"元素的offsetParent是哪一个
    22   var inner = document.getElementById('inner')
    23   console.log(inner.offsetParent)
    24 </script>
    25 </body>
    26 </html>

    看出不同了吗,outer有了相对定位,结果呢?

    运行结果

    offsetParent.png

    很明显,inner在一层层向上查找时,找到outer的时候,发现outer有定位(inner不管outer具体是什么定位,只要有定位就好,除了position: static),那么关于element.offsetParent,我们可以有以下结论“元素的offsetParent是距离该元素最近的且具有定位的父辈元素,如果没有符合条件的父辈元素,那么body就是它的offsetParent”

     

    2.offsetWidth与offsetHeight

    以offsetWidth为例,offsetWidth=width+padding*2+border*2+[横向滚动条width],这里滚动条的高度是否计算在offsetWidth内,各浏览器在具体实现上存在差异,例如chrome就没有将它计算在内;说到这,何为offsetWidth与offsetHeight?不着急,看看下面的代码示例

    代码

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <meta charset="utf-8" />
     5   <title>offsetWidth</title>
     6   <style>
     7     #outer {
     8       position: relative;
     9       width: 360px;
    10       height: 300px;
    11       padding: 40px;
    12 
    13       overflow: scroll;
    14       border: 20px solid #ff552e;
    15     }
    16   </style>
    17 </head>
    18 <body>
    19 <div id="outer">
    20   我是outer
    21 </div>
    22 <script>
    23   var outer = document.getElementById('outer')
    24 
    25   console.log('offsetWidth:' + outer.offsetWidth)
    26 </script>
    27 </body>
    28 </html>

    运行结果

    offsetWidth.png
     

    可以注意到,我们设置outer的width是360px,但在页面中,outer的实际宽度是480px,这是因为offsetWidth是元素的布局宽度,而非样式宽度,即当元素真正渲染到页面后的宽度,我们在屏幕上看到的这个宽度就是width+padding*2+border*2后的结果值,所以,关于offsetWidth的结论是:“offsetWidth是元素渲染到页面后的实际宽度尺寸,同理,offsetHeight就是元素渲染到页面后的实际高度尺寸”

     

    3.offsetTop与offsetLeft

    关于这两个属性,我想聪明的小伙伴已经猜到了,它们就是“元素与它的offsetParent的上边界与左边界的距离”

    代码

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <meta charset="utf-8" />
     5   <title>offsetTop&offsetLeft</title>
     6   <style>
     7     #outer {
     8       position: relative;
     9       width: 360px;
    10       height: 300px;
    11       /*使用padding让outer与inner产生距离*/
    12       padding-top: 20px;
    13       padding-left: 10px;
    14 
    15       border: 1px solid #666;
    16     }
    17     #inner {
    18       height: 100px;
    19       border: 1px solid #ff552e;
    20     }
    21   </style>
    22 </head>
    23 <body>
    24 <div id="outer">
    25   <div id="inner">
    26     我是inner
    27   </div>
    28 </div>
    29 <script>
    30   var inner = document.getElementById('inner')
    31 
    32   console.log('offsetTop:' + inner.offsetTop)
    33   console.log('offsetLeft:' + inner.offsetLeft)
    34 </script>
    35 </body>
    36 </html>

    运行结果

    offsetTop&offsetLeft.png

    那么我们再扩展一下,如果outer不具有定位呢,offsetTop与offsetLeft会是什么?当然是inner距离body的上边界与左边界的值了

     

    scroll相关

    1.scrollWidth

    一个元素要想在scrollWidth有值,那么它要满足至少以下两点:

    1.元素要有宽度,并且宽度是生效的(如果你给一个行内元素设置width,宽度是不生效的)

    2.元素的内部要有一个子元素,或者文本;子元素的width要大于该元素;如果是文本,那么文本在不换行的情况下要超出该元素的水平边界。

    总结一句就是:元素必须是可滚动的

    看下面示例:

    代码

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <meta charset="utf-8" />
     5   <title>scrollWidth</title>
     6   <style>
     7     #outer {
     8       position: relative;
     9       /*注意此处的值*/
    10       width: 360px;
    11       height: 300px;
    12 
    13       overflow: scroll;
    14       border: 1px solid #666;
    15     }
    16     #inner {
    17       /*注意此处的值*/
    18       width: 600px;
    19       height: 100px;
    20       
    21       /*padding: 10px;*/
    22       border: 1px solid #ff552e;
    23     }
    24   </style>
    25 </head>
    26 <body>
    27 <div id="outer">
    28   <div id="inner">
    29     我是inner
    30   </div>
    31 </div>
    32 <script>
    33   var outer = document.getElementById('outer')
    34 
    35   console.log('scrollWidth:' + outer.scrollWidth)
    36 </script>
    37 </body>
    38 </html>

    运行结果

    scrollWidth.png

    细心的童鞋注意到outer.scrollWidth不等于outer的宽度,而且inner的宽度,更准确的说是inner.offsetWidth,不信你可以把inner的padding注释打开看看O(∩_∩)O哈!

     

    2.scrollHeight

    同上,原理相同

     

    3.scrollTop&scrollLeft

    scrollTop与scrollLeft就是当可滚动的元素发生滚动时,里面的子元素分别从上边界和左边界出去了多少距离

    代码

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <meta charset="utf-8" />
     5   <title>scrollTop&scrollLeft</title>
     6   <style>
     7     #outer {
     8       position: relative;
     9       width: 360px;
    10       height: 300px;
    11 
    12       overflow: scroll;
    13       border: 1px solid #666;
    14     }
    15     #inner {
    16       /*inner的宽高都大于outer,所以outer水平垂直滚动条都会出现*/
    17       width: 600px;
    18       height: 600px;
    19 
    20       padding: 10px;
    21       border: 1px solid #ff552e;
    22     }
    23   </style>
    24 </head>
    25 <body>
    26 <div id="outer">
    27   <div id="inner">
    28     我是inner
    29   </div>
    30 </div>
    31 <script>
    32   var outer = document.getElementById('outer')
    33 
    34   // 未滚动
    35   console.log('未滚动')
    36   console.log('scrollTop:' + outer.scrollTop)
    37   console.log('scrollLeft:' + outer.scrollLeft)
    38 
    39   // 手动滚动,然后再次输出scrollTop
    40   setTimeout(function () {
    41     console.log('已滚动')
    42     console.log('scrollTop:' + outer.scrollTop)
    43     console.log('scrollLeft:' + outer.scrollLeft)
    44   }, 2000)
    45 </script>
    46 </body>
    47 </html>

    运行结果

    scrollTop&scrollLeft.png
     

     

    结语

    以上就是关于offset和scroll的总结,知识点并不深,但却可以对相关知识加深理解,如有错误之处,欢迎指正

    原文地址:https://kittyslave.github.io/2017/09/29/%E4%BD%A0%E7%9C%9F%E7%9A%84%E6%87%82offset%E4%B8%8Escroll%E5%90%97%EF%BC%9F/

  • 相关阅读:
    2019 上海网络赛 J stone name (01背包)
    CodeForces
    2019 年百度之星·程序设计大赛
    CodeForces
    POJ 3728 The merchant (树形DP+LCA)
    HihoCoder
    HihoCoder 1055 刷油漆 (树上背包)
    HI3518E平台ISP调试环境搭建
    有用的调节
    【HI3520DV200】sample
  • 原文地址:https://www.cnblogs.com/sampapa/p/7773453.html
Copyright © 2020-2023  润新知