当在 Web 浏览器中查看 HTML 文档时,DOM 节点被解析,并被渲染成盒模型(如下图),有时我们需要知道一些信息,比如盒模型的大小,盒模型在浏览器中的位置等等,本文我们就来详细了解下元素节点的几何量以及滚动几何量。

获取元素相对于 offsetParent 的 offsetTop 以及 offsetLeft 值


使用 offsetTop 和 offsetLeft 属性,我们可以获取元素节点相对于 offsetParent 的偏移像素量。这些元素节点属性告诉我们某元素上部与左侧边框最外沿到 offsetParent 上部和左侧边框内部的距离,以像素为单位。 offsetParent 的值判定依据为查找离该元素最近的 CSS 定位值不为 static 的祖先元素。如果没有,则 <body> 元素,某些人或称之为“文档”(而不是浏览器视区),即为 offsetParent 值。如果,在查询祖先过程中,找到 <td> <th><table> 元素,且它的定位为 static,则它将成为 offsetParent 的值。

<style>
  body {
    margin: 0;
  }

  #blue {
    width: 100px;
    height: 100px;
    background-color: blue;
    border: 10px solid gray;
    padding: 25px;
    margin: 25px;
  }

  #red {
    width: 50px;
    height: 50px;
    background-color: red;
    border: 10px solid gray;
  }
</style>

<div id='blue'>
  <div id='red'></div>
</div>

<script>
  var myDiv = document.querySelector('#red');

  console.log(myDiv.offsetLeft); // 60
  console.log(myDiv.offsetTop);  // 60
  console.log(myDiv.offsetParent);  // body
</script>

如果将以上代码中的蓝色 div 元素定位改为 absolute,那么将会得到完全不一样的结果,因为蓝色 div 会成为红色 div 的offsetParent。

offsetLeft 和 offsetTop 属性和包含元素有关,包含元素的引用保存在 offsetParent 属性中,而 offsetParent 属性不一定与 parentNode 的值相等。例如,<td> 元素的 offsetParent 是作为其祖先元素的 <table> 元素,因为 table 元素是在 DOM 层次中距离 td 元素最近的一个具有大小的元素。

要想知道某个元素在页面上的偏移量,将这个元素的 offsetLeft 和 offsetTop 与其 offsetParent 的相同属性相加,如此循环直至根元素,就可以得到一个基本准确的值。

function getElementLeft(element) {
  var actualLeft = element.offsetLeft;
  var current = element.offsetParent;

  while (current !== null) {
    actualLeft += current.offsetLeft;
    current = current.offsetParent;
  }

  return actualLeft;
}

function getElementTop(element) {
  var actualTop = element.offsetTop;
  var current = element.offsetParent;

  while (current !== null) {
    actualTop += current.offsetTop;
    current = current.offsetParent;
  }

  return actualTop;
}

对于简单的 CSS 布局的页面,这两函数可以得到非常准确的结果。但是对于利用表格和内嵌框架布局的页面,由于不同浏览器实现这些元素的方式不同,因此得到的值就不太精确了。一般来说,页面中的所有元素都会被包含在几个 div 元素中,而这些 div 元素的 offsetParent 又是 body 元素,所以 getElementLeft() 与 getElementTop() 会返回和 offsetLeft 和 offsetTop 相同的值。

使用 getBoundingClientRect() 获取元素相对于视区的 Top、Right、Buttom 以及 Left 边沿偏移量


使用 getBoundingClientRect() 方法,我们可以获取元素外边沿的位置。元素调用 getBoundingClientRect() 方法后会返回一个对象,该对象包含 top、right、bottom 以及 left 属性。

还是上面的代码:

 <style>
  body {
    margin: 0;
  }

  #blue {
    width: 100px;
    height: 100px;
    background-color: blue;
    border: 10px solid gray;
    padding: 25px;
    margin: 25px;
  }
</style>

<div id='blue'></div>

<script>
  var divEdges = document.querySelector('#blue').getBoundingClientRect();

  console.log(divEdges.top); // 25
  console.log(divEdges.right);  // 195
  console.log(divEdges.bottom);  // 195
  console.log(divEdges.left);  // 25
</script>

元素大小的获取


<style>
  body {
    margin: 0;
  }

  #blue {
    width: 100px;
    height: 50px;
    background-color: blue;
    border: 10px solid gray;
    padding: 25px;
    margin: 25px;
  }
</style>

<div id='blue'></div>

<script>
  var div = document.querySelector('#blue')
    , divEdges = div.getBoundingClientRect();

  // 获取元素大小
  // border + pading + content
  console.log(divEdges.width, divEdges.height); // 170 120

  // 也能取得元素大小
  console.log(div.offsetWidth, div.offsetHeight); // 170 120

  // padding + content 不含 border
  console.log(div.clientWidth, div.clientHeight); // 150 100
</script>

获取滚动几何量


<style>
  * {
    margin: 0;
    padding: 0;
  }

  div {
    width: 100px;
    height: 100px;
    overflow: auto;
  }

  p {
    width: 1000px;
    height: 1000px;
    background-color: red;
  }
</style>

<div><p></p></div>

<script>
  var div = document.querySelector('div');

  // 获取滚动元素的宽和高
  console.log(div.scrollWidth, div.scrollHeight);  // 1000 1000

  // scrollLeft 和 scrollTop 属性都是读写属性
  // 返回可滚动视区中因为滚动而暂时不可见的元素距离左边和上边的像素距离

  div.scrollLeft = 500;
  div.scrollTop = 500;

  console.log(div.scrollLeft, div.scrollTop);  // 500 500
</script>

使用 scrollIntoView() 滚动元素到视区


选取可滚动节点中某一节点后,我们可以使用 scrollIntoView() 方法告诉选取的节点滚动到可视区域。

<style>
  div {
    width: 30px;
    height: 30px;
    overflow: auto;
  }

  p {
    background-color: red;
  }
</style>

<div>
  <content>
    <p>0</p>
    <p>1</p>
    <p>2</p>
    <p>3</p>
    <p>4</p>
    <p>5</p>
    <p>6</p>
    <p>7</p>
    <p>8</p>
    <p>9</p>
  </content>
</div>

<script>
  document.querySelector('content').children[4].scrollIntoView(true);
</script>

DOM 元素节点几何量与滚动几何量的更多相关文章

  1. JavaScript HTML DOM 元素(节点)

    JavaScript HTML DOM 元素(节点) 创建新的 HTML 元素 创建新的 HTML 元素 如需向 HTML DOM 添加新元素,您必须首先创建该元素(元素节点),然后向一个已存在的元素 ...

  2. JavaScript 要点(十四)HTML DOM 元素(节点)

    A.创建新的 HTML 元素 如需向 HTML DOM 添加新元素,必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素. <div id="div1"> ...

  3. 围绕DOM元素节点的增删改查

    HTML 文档中的所有内容都是节点: 整个文档是一个文档节点 document 每个 HTML 元素是元素节点 element HTML 元素内的文本是文本节点 每个 HTML 属性是属性节点 注释是 ...

  4. JavaScript HTML DOM元素节点常用操作接口

    在文档对象模型 (DOM) 中,每个节点都是一个对象.DOM 节点有三个重要的属性 : 1. nodeName : 节点的名称 2. nodeValue :节点的值 3. nodeType :节点的类 ...

  5. 吴裕雄--天生自然 JAVASCRIPT开发学习:HTML DOM 元素 (节点)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  6. 深入理解DOM节点类型第五篇——元素节点Element

    × 目录 [1]特征 [2]子节点 [3]特性操作[4]attributes 前面的话 元素节点Element非常常用,是DOM文档树的主要节点:元素节点是html标签元素的DOM化结果.元素节点主要 ...

  7. DOM中元素节点、属性节点、文本节点

    DOM中有12中节点,但最常用到的是元素节点,属性节点,文本节点. 元素节点的节点类型(nodeType)是1: 属性节点的节点类型(nodeType)是2: 文本节点的节点类型(nodeType)是 ...

  8. DOM中元素节点、属性节点、文本节点的理解

    DOM中元素节点.属性节点.文本节点的理解 节点信息 每个节点都拥有包含着关于节点某些信息的属性.这些属性是:nodeName(节点名称) nodeValue(节点值) nodeType(节点类型)  ...

  9. JavaScript HTML DOM 元素(节点)

    添加和删除节点(HTML 元素) 创建新的 HTML 元素  如需向 HTML DOM 添加新元素,您必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素. 例如:这段代码创建新的 < ...

随机推荐

  1. ASP.NET features need application service database support

    搭建的web程序出现如上图所示的错误 原因程序使用以下ASP.NET 特性 Membership (the SqlMembershipProvider class). Role management ...

  2. Java Se:Java Security

    Java API中有很多都使用了SecurityManager,这到底是什么玩意?最近看公司的产品的源码,也有不少SecurityManager.AccessControlContext等相关的代码, ...

  3. 弹出层在兼容模式和IE8模式下显示不正常

    弹出层在火狐.谷歌.360极速模式.IE6下都能100%面积正常显示,但在IE8和360的兼容模式下只显示弹出层下半部分或右半部分的内容,在主页面加上: <meta http-equiv=&qu ...

  4. MySQL 调优基础(三) Linux文件系统

    Linux的文件系统有点像MySQL的存储引擎,它支持各种各样的文件系统.它最上层是通过 virtual files system虚拟文件系统作为一个抽象接口层来对外提供调用的.然后下层的各种文件系统 ...

  5. hadoop2.6分布式部署时 livenodes等于1的原因

    1.问题描述 在进行hadoop2.x版本的hdfs分布式部署时,遇到了一个奇怪的问题: 使用start-dfs.sh命令启动dfs之后,所有的datanode节点上均能看到datanode进程,然而 ...

  6. db2存储过程

    一. 使用存储过程的好处 1. 减少客户机与服务器之间的网络使用率,以及数据库锁定保持的时间 应用程序通常在执行每个SQL语句都要跨网络两次,存储过程可以将SQL语句集中在一起, 从而使得对于每一组S ...

  7. 元组tuple

    tuple和list的主要区别就是tuple里的元素的是不能改变的,即tuple时immutable的 #创建tuple >>> tupa = (12 , 'ed' , 34) &g ...

  8. Linux服务器开机没响应,BIOS信息都没有

    于2015-10-16,记得是4月份装的服务器,上边ineedle都部署完毕,当时没有派上用场,这次华为测试需要一台ineedle测试机,便把这个安装好的ineedle请出来了,插上电源后,接上网线, ...

  9. Altium Desiner 警告 adding hidden net

    这是因为 一些元件 隐藏了 vcc GND 或者没有使用vcc GND ,用不着它也报警告了. 这里可以将 vcc GND删掉这个管脚.

  10. Linux 下从头再走 GTK+-3.0 (一)

    原本由于项目需求在 Linux 下学习过一段时间的 GTK+2.0 图形开发,时隔一段时间,想真正深入学习一下 GTK . 这次直接从头学习 GTK+-3.0 ,并写下博文便于日后查看,也方便新手入门 ...