Description
前言
看《javascript高级程序设计》的时候,对于JS中获取各种宽度和距离,让我们很容易混淆,还有各个浏览器的兼容问题等等,所以想把他们总结一下。
偏移量
元素的可见大小由其高度,宽度决定,包括所有内边距、滚动条、和边框大小但是不包括外边距。
- offsetHeight: 元素在垂直方向上占用的大小,以像素计。包括高度,(可见的)水平滚动条的高度、上边框的高度和下边框的高度。
- offsetWidth: 元素在水平方向上占用的大小,以像素计。包括高度,(可见的)垂直滚动条的宽度、上边框的高度和下边框的高度。
- offsetLeft: 元素的左外边距至包含元素的左内边框之间的像素距离。
- offsetTop: 元素的上外边距至包含元素的上内边框之间的像素距离。
其中,offsetTop和offsetLeft属性与包含元素有关,包含元素的引用保存在offsetParent属性中,offsetParent不一定与parentNode的值相等,例如td元素的offsetParent是作为其祖先元素的table元素,
这个是因为table在DOM中是居td元素最近的一个具有大小的元素。
如果想知道某个元素在页面上的偏移量的话,将这个元素的offsetLeft和pffsetTop与其offsetParent的属性相加,如此循环直至根元素。
function getElementLeft(element) {
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
//一直循环offsetParent元素,知道找不到
while(current != null) {
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
return actualLeft;
}
同样的原理,我们也可以球场offsetLeft的值。
注意,所以的这些偏移量属性都是只读的,而且每次访问都需要重新计算。因此应该尽量避免重复访问这些属性,如果需要重复使用这些值的话,可以保存在局部变量中,以提高性能
客户端的大小
元素的客户区的大小,指的是元素的内容以及内边距所占据的空间大小。
- clientWidth: 元素的内容区域宽度加上左右内边距宽度。
- clientHeight: 元素内容区域高度加上上下内边距的高度。
我们可以看见,客户区的大小就是元素内部的空间大小,因此滚动条占用的空间不计算在内。例如,如何确定浏览器的视口大小?需要考虑到兼容性,在IE7之前的版本,我们需要使用的是document.body,而其他版本的需要使用的是document.documentElement。
function getViewport() {
//如果,浏览器模式是混杂模式的话
if(document.compatMode == 'BackCompat') {
return {
width: document.body.clientWidth,
height: document.body.clientHeight
}
}else {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
}
}
}
滚动大小
滚动大小:指的的是包含滚动内容的元素大小。有些元素(例如html元素),即使没有执行任何代码也能自动添加滚动条,但是另一些元素,则需要通过css的overflow属性进行设置才能滚动。
- scrollHeight: 在没有滚动条的情况下,元素内容的总高度。
- scrollWidth: 在没有滚动条的情况下,元素内容的总宽度。
- scrollLeft: 被隐藏在内容区域左侧的像素数,通过设置这个属性可以改变元素的滚动位置。
- scrollTop: 被隐藏在内容区域上方的像素数,通过设置这个属性可以改变元素的滚动位置。
jQuery中的height()、innerheight()、outerheight()的区别
- height:height
- innerHeight:height+padding
- outerHeight(false)(默认):height+padding+border
- outerHeight(true):height+padding+border+margin
width是同高度类似的。
jQuery中的offset()和position()
offset()
获取匹配元素在当前视口的相对偏移。
返回的对象包含两个整形属性:top 和 left。此方法只对可见元素有效。
position():
获取匹配元素相对父元素的偏移。
返回的对象包含两个整形属性:top 和 left。为精确计算结果,
请在补白、边框和填充属性上使用像素单位。此方法只对可见元素有效。
- 使用position()方法时事实上是把该元素当绝对定位来处理,获取的是该元素相当于最近的一个拥有绝对或者相对定位的父元素的偏移位置。
- 使用position()方法时如果其所有的父元素都为默认定位(static)方式,则其处理方式和offset()一样,是当前窗口的相对偏移
- 使用offset()方法不管该元素如何定位,也不管其父元素如何定位,都是获取的该元素相对于当前视口的偏移。
jQuery中的scrollLeft()和scrollTop()的区别
scrollLeft()
- 该方法设置或返回被选元素的水平滚动条位置。提示:当滚动条位于最左侧时,位置是 0。
- 当用于返回位置时:该方法返回第一个匹配元素的滚动条的水平位置。
- 当用于设置位置时:该方法设置所有匹配元素的滚动条的水平位置。
scrollTop()
- 该方法设置或返回被选元素的垂直滚动条位置。提示:当滚动条位于最顶部时,位置是 0。
- 当用于返回位置时:该方法返回第一个匹配元素的滚动条的垂直位置。
- 当用于设置位置时:该方法设置所有匹配元素的滚动条的垂直位置。
下图可以对jquery的尺寸的区别。
window和document
- window和document的区别?
window对象表示浏览器打开的窗口,window对象是可以省略的。例如window.alert()
可以直接写成'alert()'。
document对象是window对象的一部分,浏览器的html文档称为Document对象。
‘window.document.body’省略为document.body
。
2.window.location和document.location是一样吗?
window对象的location属性引用的是location对象,表示该窗口中当前显示文档的URL。document对象的location对象属性也是引用location对象。
window.location === document.location //true
window下相关的宽高
- window.innerWidth:浏览器窗口去掉滚动条的宽度
- window.outerWidth:浏览器窗口的宽度
- window.innerHeight:浏览器窗口去掉顶部上面那栏的宽度
- window.outerHeight:浏览器窗口顶部的高度
- window.screen(这个对象包含有关用户屏幕的信息)
- window.screen.height::用户屏幕的高度
- window.screen.width:用户屏幕的宽度
- window.screen.availHeight: 用户屏幕的可用高度
- window.screen.availWidth: 用户屏幕的可用宽度
- window.screenTop: 浏览器窗口距屏幕顶部的高度
- window.screenLeft: 浏览器窗口距屏幕左侧的宽度
对于window.inner和outer这两个属性是存在兼容性的问题的,他们仅支持IE9及以上的浏览器。对于兼容问题,后面进行讲解的。
document下的宽高
与client相关的宽高
- document.body.clientWidth
- document.body.clientHeight
- document.body.clientLeft
- document.body.clientTop
document.body.clientWidth
和document.body.clientHeight
该属性是指元素的可视部分宽度和高度,即padding+content
如果没有出现滚动条,即为元素设定的高度和宽度,如果出现滚动条,滚动条会遮盖元素的宽度,那么改属性就是其本来的宽度减去滚动条的宽高。
.content {
width: 200px;
height: 200px;
background: #ddd;
border:4px solid #666;
overflow: auto;
}
如果内容特别多,出现了滚动条的话,console.log(content.clientWidth); //183
因为width为200px.减去滚动条为17px,则为183px。在Mac下,浏览器的滚动条是不占位的,所以宽度还是200px。
假如无padding和滚动的话,clientWidth = style.width
假如有padding无滚动的话,clientWidth = style.width + style.padding
假如有padding和滚动的话,clientWidth = style.width + style.padding-滚动轴的宽高
document.boby.clientLeft
和document.boby.clientTop
这两个返回是元素周围边框的厚度,如果不指定一个边框或者不定位该元素,那么该值就是0.
这一对属性是用来读取元素的border的宽度和高度的。
clientTop = border-top的border-width;
clientLeft = border-left的border-width;
与offset相关的
- document.body.offsetWidth
- document.body.offsetHeight
- document.body.offsetLeft
- document.body.offsetTop
offsetWidth
和offsetHeight
这一对属性指的是元素的border+padding+content的宽度和高度。
该元素和其内部的内容是否超出元素大小无关,只和本来设定的border以及width和height有关。
假如无padding无滚动条无border: offsetWidth = client.width = style.width
假如有padding无滚动条有border: offsetWidth = style.width+padding+border = clientWidth+border
假如有padding有滚动条有border:offsetWidth = style.width+padding+border = clientWidth+border+滚动条宽。
offsetLeft
和offsetTop
这两个属性。
-
如果当前元素的父级元素没有进行css定位(position为absolute或者relative),offsetParent为body。
-
如果当前元素的父级元素中有css定位(position为absolute或者relative)。offsetParent取最近的那个父级元素。
在IE6/7中:offsetLeft = (offsetParent的padding-left)+(当前元素的margin-left)
在IE8及以上和chrome中:offsetLeft = (offsetParent的margin-left)+(offsetParent的borde宽度)+(offsetParent的padding-left)+(当前元素的margin-left)
在FireFox中:offsetLeft = (offsetParent的margin-left)+(offsetParent的padding-left)+(当前元素的margin-left)
body {
border: 20px solid #ccc;
margin: 10px;
padding: 40px;
height: 350px;
width: 500px;
}
.box {
width: 400px;
height: 200px;
padding: 20px;
margin: 10px;
background-color: red;
border: 20px solid #ddd;
}
<body>
<div id="box" class='box'></div>
</body>
window.onload = function(){
var div = document.getElementById("box");
alert(div.offsetLeft);
alert(div.offsetTop);
//chrome80 80
// ie7 50 40
//firefox 60 60
//opera 80 80
}
与scroll相关的宽高
- document.body.scrollWidth
- document.body.scrollHeight
- document.body.scrollTop
- document.body.scrollLeft
scrollWidth
和scrollHeight
在document.body和div是有区别的。
body {
border:20px solid #ccc;
margin: 10px;
padding: 40px;
background :#eee;
height: 350px;
width: 500px;
overflow:scroll;
}
alert(document.body.scrollWidth);
alert(document.body.scrollHeight);
在chrome中,document.body的scrollWidth和scrollHeight。
-
如果body给定宽高小于浏览器的窗口的宽高的话: document.body的scrollWidth通常是浏览器的宽度,
document.body的scrollHeight通常是浏览器的高度。 -
如果body给定宽高大于浏览器的窗口的宽高的话,且body里面的内容小于body的宽高:document.body的scrollWidth是body给定宽度+其padding+margin+border
document.body的scrollHeight是body给定高度+其padding+margin+border -
如果body给定宽高大于浏览器的窗口的宽高的话,且body里面的内容大于body的宽高:
document.body的scrollWidth是内容给定宽度+其padding+margin+border+(body左边一边padding+border+margin)
document.body的scrollHeight是内容给定高度+其padding+margin+border+(body顶部一边padding+border+margin)
对于某个div的scrollWidth和scrollHeight
- 在无滚动轴的情况下:scrollWidth = clientWidth = style.width+padding
- 在有滚动轴的情况下:scrollWidth = 实际内容+padding
在firefox中,把body当成了div进行处理的。
document.body.scrollTop与document.documentElement.scrollTop兼容
scrollLeft和scrollTop,指的是当元素其中的内容超出其高宽的时候,元素被卷起的高度和宽度。
有文档声明(即网页第一句的docType)的情况下,标准浏览器是只认识documentElement.scrollTop的,但chrome在有文档声明时,chrome也只认识document.body.scrollTop.
document.body.scrollTop与document.documentElement.scrollTop两者有个特点,就是同时只会有一个值生效。比如document.body.scrollTop能取到值的时候,document.documentElement.scrollTop就会始终为0;反之亦然。所以,如果要得到网页的真正的scrollTop值,可以这样:
//兼容做法
var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
//或者
var scrollTop =document.body.scrollTop || document.documentElement.scrollTop;
//或者这样
var scrollTop =document.body.scrollTop+document.documentElement.scrollTop;
documentElement和body的关系
一个HTML文档中,文档节点是每一个文档的根节点、文档节点只有一个子节点即html
元素。我们称之为文档元素。文档元素是文档的最外层元素。文档中的其他元素都包含在文档元素中。每个文档只能有一个文档元素。在HTML页面中,文档元素始终都是html
元素,在XML中,没有预定义的元素,因此任何元素都可能成为文档元素。
alert(document.documentElement); //html
alert(document.body); //body
//还是上面那段CSS
alert(document.documentElement.clientHeight);
alert(document.body.clientHeight);
//chrome 974 430
这两者的关系是包含关系。
- 这个
document.documentElement.clientHeight
是可视区域的大小,’document.body.clientHeight‘是body的宽度+padding为430px。这两个谁大谁小是不确定的。 <!DOCTYPE html>
把这个html去掉<!DOCTYPE>
这个两个大小是相同的。- 如果把body上的css去掉的话,那么这个
document.documentElement.clientHeight
是可视区域的大小
’document.body.clientHeight‘是body的宽度+padding为280为里面div的大小。
所以浏览器窗口可视区域大小,兼容写法
var w= document.documentElement.clientWidth || document.body.clientWidth;
var h= document.documentElement.clientHeight || document.body.clientHeight;