当在 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. IO流03--毕向东JAVA基础教程视频学习笔记

    提要 16 读取转换流17 写入转换流18 流操作规律-119 流操作规律-220 改变标准输入输出设备21 异常的日志信息22 系统信息 16 读取转换流 字符流体系中的InputStreamRea ...

  2. Javascript之旅——第十一站:原型也不好理解?

    写到这篇,我的js系列也快接近尾声了,所以这个系列不会遗留js来实现面向对象的核心——原型,有些人说原型不好理解,其实嘛,要想系统 的理解原型,最便捷的方式就是看看经典的书,少看些博客,博客这东西只是 ...

  3. MemSQL分布式架构介绍(一)

    最近在了解MemSQL架构,看了些官方文档,在这里做个记录,原文在这里:http://docs.memsql.com/latest/concepts/distributed_architecture/ ...

  4. linux的“自动化”

    h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h ...

  5. dyld: Library not loaded: @rpath/libswiftCore.dylib 解决方法

    解决: 设置Build Setting - > 搜索 embe关键字 -> 修改属性 见如下图: 如果更新了Xcode 8 这里变成:

  6. bootstrap简单的过一遍

    注:.xxxx 表示类(class=xxxx) <h1>到<h6>均可使用.另外还提供了.h1到.h6的class .lead可以让段落突出显示 <small>  ...

  7. 准备使用 Office 365 中国版--安装

    温故而知新,先附上一个链接:Office 365常见问题 Office 365中Office套件的安装介质和传统Office套件的安装介质是有些区别的,虽然功能都一样.因此,如果购买了带Office套 ...

  8. 单元测试实战 - 如何使用Eclipse

    一.Eclipse工具的使用 1. 进入官网: http://www.eclipse.org  ,点击download,根据系统版本选择自己需要的版本,下载之后,会得到一个zip文件,将这个文件解压到 ...

  9. DPM(voc-release5) Matlab模型文件 Mat转XML

    (转载请注明作者和出处 楼燚(yì)航的blog :http://www.cnblogs.com/louyihang loves baiyan/ 未经允许请勿用于商业用途) 由于目前DPM模型训练的代 ...

  10. Servlet分页技术

    这是看韩顺平老师的servlet视频,自己动手写的,楼主看韩顺平老师的servlet是2006制作的,用的是sql server数据库,自己又用的是oracle数据库,所以怕有的同学遇到同样的问题,不 ...