跳到主要内容

DOM-元素节点几何量

· 阅读需 8 分钟

最后更新于 2016-05-19 14:54:00

当我们在查看 HTML 文档时,每个元素节点被解析后,都画成了可视形状。我们可以获取每个元素节点的几何量(宽、高、偏移量)以及页面滚动距离。

元素节点几何量

通常我们将一个元素抽象成一个盒子模型,具有 content(内容)、padding(填充、内边距)、border(边框)、margin(外边距)这些尺寸属性。

定位偏移量

使用元素节点的 offsetTopoffsetLeft 属性,我们可以分别获取该元素节点顶部与左侧外边框相对于 offsetParent顶部与左侧内边框的偏移像素量。

  • offsetParent
  • offsetTop
  • offsetLeft

一个元素节点的 offsetParent 判定依据为查找距离该元素节点最近的 CSS 定位(position)值不为 static(默认值)的祖先元素,直至 body 元素为止。如果在查询过程中,找到 tdthtable 元素之一,且它的定位值为 static,则将它作为 offsetParent

<style>
#out{
width: 200px;
height: 200px;
background-color: #ccc;
border: 5px solid yellow;
padding: 10px;
margin: 15px;
position: relative;
}
#in{
width: 100px;
height: 100px;
background-color: red;
border: 3px solid blue;
padding: 6px;
margin: 9px;
}
</style>
<body>
<div id="out">
<div id="in"></div>
</div>
</body>
<script>
// 查看内部DIV的offsetParent
console.log(document.querySelector("#in").offsetParent);
// 输出<div id="out">...</div>
// 这是因为外部DIV的position="relative/absolute"

// 验证内部DIV的offsetTop与offsetParent的值
console.log(document.querySelector("#in").offsetTop); // 输出19
console.log(document.querySelector("#in").offsetLeft); // 输出19
</script>

上述示例可以看出,符合外边框到 offsetParent 内边框的计算方式。通俗的说就是,我们将一个小盒子放到一个大盒子中,小盒子外侧到大盒子内侧的距离就是我们要计算的值。

盒子属性

在可视区(浏览器 HTML 文档显示区,不包含浏览器导航、地址栏等)内,我们可以通过 getBoundingClientRect() 方法获取某个元素的矩形盒子基本属性。

  • getBoundingClientRect()

exp:

<style>
body{
border: 0px;
padding: 0px;
margin: 0px;
}
div{
width: 200px;
height: 200px;
background-color: #ccc;
border: 10px solid yellow;
padding: 30px;
margin: 50px;
}
</style>
<body>
<div></div>
</body>
<script>
// 获取DIV的矩形盒子基本属性
console.log(document.querySelector("div").getBoundingClientRect());
// 输出ClientRect{top: 50, right: 330, bottom: 330, left: 50, width: 280, height: 280}

// 可以单独获得某项基本属性
console.log(document.querySelector("div").getBoundingClientRect().top);
// 输出50
</script>

上述示例可以看出,topbottomleftright 属性表示该元素矩形的上、下、左、右外边框相对于浏览器可视区上、下、左、右边沿的偏移像素量。通俗的说就是,在存放快递盒子的仓库中,每个盒子四周外侧到仓库四周墙壁的距离就是我们要计算的值。

widthheight 属性表示该元素矩形的可视尺寸(宽、高),不包括 margin(外边距)。

盒子尺寸

我们可以通过一些属性获取可视区(浏览器 HTML 文档显示区,不包含浏览器导航、地址栏等)内元素矩形的尺寸。

  • offsetWidth
  • offsetHeight
  • clientWidth
  • clientHeight

exp:

<style>
div{
width: 200px;
height: 200px;
background-color: #ccc;
border: 10px solid yellow;
padding: 30px;
margin: 50px;
}
</style>
<body>
<div></div>
</body>
<script>
// 获取DIV的矩形盒子尺寸
console.log(document.querySelector("div").offsetWidth); // 输出280
console.log(document.querySelector("div").offsetHeight); // 输出280

console.log(document.querySelector("div").clientWidth); // 输出260
console.log(document.querySelector("div").clientHeight); // 输出260
</script>

上述示例可以看出,offsetWidthoffsetHeight 属性表示的是元素矩形的可视尺寸(宽、高),不包括 margin(外边距)。

但是,clientWidthclientHeight 属性表示的是元素矩形的有效尺寸(宽、高),不包括 margin(外边距)、border(边框)。

获取特定点上最顶层元素节点

我们可以使用 elementFromPoint() 方法获取可视区(浏览器 HTML 文档显示区,不包含浏览器导航、地址栏等)内,特定点上最顶层元素节点的引用。

  • elementFromPoint()

exp:

<script>
// 获取文档可视区内left=50,top=50处最顶层元素节点
console.log(document.elementFromPoint(50,50));
</script>

如果没有设置 z 轴索引值 z-index,则最顶层元素节点就是 HTML 文档中该点上最后被解析的元素节点。

滚动几何量

当 HTML 文档太大(页面元素太多)时,或者当某个元素节点内内容太多时,会出现左右滚动条。此时,我们可能需要知道该元素节点的滚动区域、滚动距离等等。

滚动尺寸

我们可以通过以下属性来获取 HTML 页面或者某个元素节点的滚动尺寸(总高、总宽)。

  • scrollWidth
  • scrollHeight

exp:

<style>
div{
width: 200px;
height: 200px;
background-color: #ccc;
overflow: auto;
}
p{
width: 1000px;
height: 10000px;
margin: 0px;
}
</style>
<body>
<div>
<p></p>
</div>
</body>
<script>
// 获取DIV的滚动尺寸
console.log(document.querySelector("div").scrollWidth); // 输出1000
console.log(document.querySelector("div").scrollHeight); // 输出1000
</script>

当滚动条未出现(滚动区域<元素尺寸)时,这两个属性将返回 clientWidthclientHeight 属性的值,也就是有效尺寸。

滚动距离

通常页内导航可以将视区跳转到页内某个区域内,或者当页面向下滚动时才继续加载图片等等。这些功能的实现都要获取(设置)所滚动的距离。

  • scrollLeft
  • scrollTop

exp:

<style>
p{
width: 10000px;
height: 10000px;
}
</style>
<body>
<p></p>
</body>
<script>
// 利用事件将窗口滚动距离显示在标题上
window.onscroll=function(){
scroll_left=document.body.scrollLeft || document.documentElement.scrollLeft;
scroll_top=document.body.scrollTop || document.documentElement.scrollTop;
document.title=scroll_left+","+scroll_top;
}
</script>

如果我们想让页面滚动到某一处,直接给 scrollLeftscrollTop 属性赋值即可。

滚动元素节点到视区内

页内导航通常也可以根据选取特定元素,将视区跳转到该元素节点上来实现,这样实现的方式是最科学的。

  • scrollIntoView()

exp:

<style>
button{
margin: 10px;
}
p{
height: 1000px;
background-color: #ccc;
}
</style>
<body>
<button>跳转到第一段</button>
<button>跳转到第二段</button>
<button>跳转到第三段</button>
<button>跳转到第四段</button>
<button>跳转到第五段</button>
<p id="p1">第一段</p>
<p id="p2">第二段</p>
<p id="p3">第三段</p>
<p id="p4">第四段</p>
<p id="p5">第五段</p>
</body>
<script>
// 获取按钮集合并转换为数组
var buttons=document.getElementsByTagName("button");
buttons=Array.prototype.slice.call(buttons);
// 利用事件实现按钮跳转
for (var i = buttons.length - 1; i >= 0; i--) {
buttons[i].onclick=function(){
var index=buttons.indexOf(this)+1;
document.querySelector("#p"+index).scrollIntoView();
}
}
</script>

结语

元素节点的几何量(尺寸、定位偏移量),页面元素的滚动距离等等都是我们经常使用的值,所以清楚的了解什么属性、方法获取什么值是非常有必要的。

参考

  • 《DOM 启蒙》,Cody Lindley,陈养剑 译