CSSOM视图模式(CSSOM View Module)相关整理

2016-10-09

2016-10-08,国庆刚完,状态尚未回来,看到张鑫旭大神的一篇关于CSS的文章,讲的很详细,还有一个测试兼容性的网站www.quirksmode.org

文档视图(DocumentView)和元素视图(ElmentView)方法

有四个访法,如下:

elementFromPoint();
getBoundingClientRect();
getClientRects();
scrollIntoView();

1. elementFromPoint() -不常用

返回给定坐标处所在的元素。是个目前而言,兼容性不错的方法。这里的兼容我并没写的很详细,可以去看原文,非常详细。

IE8 IE9+ FF6+ Chrome

如下示例:
document.elementFromPoint(100,100) 这里可选中相对页面左上角(100,100)坐标处的元素。不过不同浏览器差异很大,这个方法可以用来检测元素是否发生重叠或是碰撞。

2. getBoundingClientRect()

得到矩形元素的界线,返回一个对象,包含 top,left,right,bottom,width,height 6个属性值,但是在IE中没有 width,height 不过可以通过以下方法获得:

//兼容所有浏览器写法
var obj = dom.getBoundingClientRect();
var top = obj.top,
    right = obj.right,
    bottom = obj.bottom,
    left = obj.left;
var width = obj.width || right - left,
    height = obj.height || bottom - top;
IE8 IE9+ FF6+ Chrome

该方法与 getClientRects() 方法是近亲, 两者都是 Range接口 方法。

3. getClientRects()

返回元素的数个矩形区域,返回的结果是个对象列表,具有数组特性。这里的矩形区域只针对inner box ,因此,只针对 a,span,em 这类标签元素,兼容性:

IE8 IE9+ FF6+ Chrome

这里附上原文demo

IE6,7的bug

getClientRects() 方法是跟着 inner box 模型走的,其返回的每个矩形区域其实就是一个 inner boxes ,也就是一行文字内容。可以看看 inner box 的相关内容。
也就是说,例如一段文字在一个 span 标签内有两行,则 getClientRects() 返回的就是含有两个 Rect 对象的列表,如果文字有三行则三个。
然而在 IE6,7 下,其返回的区域个数像是吃了激素一样,完全不受控制,数目很多,都不知道从哪冒出来的!
IE6,7 还有一个文字,就是按照定义,如果是 block 水平标签内的文字,不管文字有多少行,返回的都是这个 block 水平标签区域。但是,IE6,,7 却不走寻常路,反而“正常模样” 的返回行数等。例如demo页面,如果把 span 换成 p ,则其他浏览器返回的列表个数是1,就 IE6,7 返回的是文字行数相等的矩形区域。
总结为, IE6,7 把针对 inline 水平标签的方法应用到了 block 水平标签上了,而 inline 水平标签像弃婴一样,扔在一旁,bug横生啊。

getClinetRects() 和 getBoundingClinetRect() 差异

getClientRects() 返回的是数组,数组中有很多类似 getBoundingClientRect() 返回的对象。 getClientRects() 是多行文字区域的坐标偏移集合,在非IE下,只对 inline 水平标签有作用。
一般 getBoundingClientRect() 方法用的多。我们可以很容易的获取某个元素的偏移值。甚至高宽都可以轻松的计算出来。

4. scrollIntoView()

让元素滚动到可视区域。兼容性:

IE8 IE9+ FF6+ Chrome

简单实例: element.srcollIntoView() ,原文demo。这个方法很好用,这是为我们实现元素的锚点跳转又敞开了一条新的途径。

元素视图属性

关于元素大小位置等信息的一些属性:

clientLeft clientTop
clientWidth clientHeight
offsetLeft offsetTop
offsetParent
offsetWidth offsetHeight
scrollLeft scrollTop
scrollWidth scrollHeight

兼容性:

IE8 IE9+ FF6+ Chrome

1. clientLeft 和 clientTop

标示内容区域的左上角相对于整个元素左上角的位置(包括边框)。
原文demo
可以发现,在FF和IE下弹出3,chrome下弹出2,这是因为FF和IE的按钮默认3像素,chrome为2像素。但是通常我们不会直接使用浏览器默认的样式,而是要加以修改这样不同浏览器下计算的值就会统一起来。

2. clientWidth 和 clientHeight

表示内容区域的高度和宽度,包括 padding 大小,但是不包括表边框和滚动条。
原文demo

3. offsetLeft 和 offsetTop

表示相对于最近的祖先定位元素 (CSS position 属性被设置为 relative absolute fixed 的元素) 的左右偏移值。
原文demo
可以看到两次弹出的只是不同的,以为最近祖先定位元素发生了变化。

4. offsetParent

第一个祖先定位元素 (即用来计算上面的 offsetLeftoffsetTop 的元素)。
原文demo
offsetParent 元素只可能是下面几种情况:

  • <body>
  • position 不是 static 的元素
  • <table><th><td> , 但必须要 position: static
    在本demo中,页面按钮没有任何祖先定位元素,于是点击按钮后返回的就是 <body> 标签了。
    <body> 元素为定位元素的终极Boss,所以其上面就没有其他定位元素了。也就是说 body 元素没有 offsetParent (尽管有时候 html 进入 offsetParent 链)。另外,在IE下, position: fixed 的元素没有 offsetParent

5. offsetWidth 和 offsetHeight

整个元素的尺寸(包括边框)。
原文demo。可以对比上面的clientWidth 和 clientHeight 的demo,多出的值就是边框的值。

6. scrollLeft 和 scrollTop

表示元素滚动的像素大小,可读可写很常用。
简单实用实例:

element.scrollLeft
element.scrollTop
element.scrollTop = 50

原文demo
点击按钮后页面滚动高度100像素,如下:

document.getElementsByTagName('body')[0].scrollTop = 100; //document.body.scrollTop = 100;
document.getElementsByTagName('html')[0].scrollTop = 100;

7. scrollWidth 和 scrollHeight

表示整个内容区域的宽高,包括隐藏的部分。如果元素没有隐藏的部分,则相关的只应该等用于 clientWidthclientHeight 。当你向下滚动滚动条的时候, scrollHeight 应该等于 scrollTop + clientHeight
兼容性IE8以下不准确,就是当元素没有设置 overflow 属性,但是里面的内容超过外部宽高的情况,例如将demo页面中类名为 box 样式中的 overflow: auto 去掉,IE7返回的却是里面图片元素的尺寸,为256,191。

鼠标位置 (Mouse Position)

与鼠标事件(例如不同的单击)相关的一些属性。这个东西基本上 javascript 一些必备书籍(例如《javascript高级程序设计》)上都有介绍。这里就简单展示下兼容性和一些必要的文字介绍。
相关的属性:

clientX clientY
offsetX offsetY
pageX pageY
screenX screenY
x y

1. clientX 和 clientY

相对于 window,为鼠标相对于 window 的偏移。在iphone上,这个只返回的位置就等同于下面要提到的 pageX/Y 。兼容性:

IE5.5 IE6 IE7 IE8 IE9pr3 FF3 FF3.5 FF3.6 FF4b1 Saf4 win Saf5 win chrome4 chrome5

简单实用实例:

var event = e || window.event
event.clientX
event.clientY

原文demo
可以发现,点在按钮的位置不同,弹出的职业不一样,因为偏移大小是鼠标相对于 window 窗口的大小。

2. offsetX 和 offsetY

表示鼠标相对与当前被点击元素 padding box 的左上偏移值,各个浏览器的兼容性五花八门,如下:

IE5.5 IE6 IE7 IE8 IE9pr3 FF3 FF3.5 FF3.6 FF4b1 Saf4 win Saf5 win chrome4 chrome5
有bug 有bug 有bug border box border box border box border box

简单实用实例:

var event = e || window.event
event.offsetX
event.offsetY

在IE7及以下的浏览器下,只有当当前目标元素为 offsetParent 时才计算坐标值,否则,他就会拿当前目标元素的 offsetParent 来计算。还有当发现元素应用了 position: relative 后,IE会去寻找下一个 offsetParent 来计算 offsetY ,但又不是 offsetX 。是的,读两次,很蛋疼!

3. pageX 和 pageY

为鼠标相对与 document 的坐标。IE6~8 不支持,如下:

IE5.5 IE6 IE7 IE8 IE9pr3 FF3 FF3.5 FF3.6 FF4b1 Saf4 win Saf5 win chrome4 chrome5

简单实用实例:

var event = e || window.event
event.pageX
event.pageY

原文demo。在 IE6~8 下得到的是 undefined

4. screenX 和 screenY

鼠标相对与显示器屏幕的偏移坐标,兼容性:

IE5.5 IE6 IE7 IE8 IE9pr3 FF3 FF3.5 FF3.6 FF4b1 Saf4 win Saf5 win chrome4 chrome5

简单实用实例:

var event = e || window.event
event.screenX
event.screenY

原文demo
在iphone中,这个属性基本上就等同于 pageX/Y ,尽管通常会有1~2像素的差异。谁叫iphone的显示器区域跟window区域跟文档区域都是一样的呢?

5. x 和 y

相当于 clientX/Y 。既然已经有了 clientX/Y ,为什么还需要 x/y 呢? = =! ,兼容性:

IE5.5 IE6 IE7 IE8 IE9pr3 FF3 FF3.5 FF3.6 FF4b1 Saf4 win Saf5 win chrome4 chrome5
page X/Y page X/Y

原文demo
在FF6下,依旧不鸟这个FF可能觉得多余的属性。弹出 undefined

文章摘录自:张鑫旭-鑫空间-鑫生活