JS中的盒模型
1、高度问题:
● 内容的宽度和高度:我们设置的width/heigth这两个样式就是内容的宽和高,如果没有设置height值,容器的高度会更具里面内容自己进行适应,这样获取的值就是真实内容的高;如果设置固定的高度了,不管内容是多了还是少了,其实我们内容的高度指的都是设定的那个值得
● 真实内容的宽度和高度:这个代指的是实际内容的宽高(和我们设置的height没有必然的联系),例如:设置高度为200px,如果内容有溢出,那么真实内容的高度是要把溢出内容的高度也要加进来的
1、client系列(当前元素的几个私有的属性)
//->clientWidth/clientHeight:内容的宽度/高度+左右/上下填充(和内容溢出没有关系)
//->clientLeft:左边框的宽度 clientTop:上边框的高度(border[left/Top]Width)
2、 offset系列
//-> offsetWidth/offsetHeight:clientWidth/clientHeight+左右/上下边框(和内容是否溢出也是没有任何关系)
//-> offsetParent:当前元素的父级参照物
//-> offsetLeft/offsetTop:当前元素的外边框距离父级参照物的内边框的偏移量
3、 scroll系列
//-> scrollWidth/scrollHeight:和我们的clientWidth/clientHeight一模一样(前提是:容器中的内容没有溢出的情况下)
//-> 如果容器中的内容有溢出,我们获取的结果是如下规则:
//scrollWidth:真实内容的宽度(包含溢出)+左填充
//scrollHeight:真实内容的高度(包含溢出)+上填充
//->获取到的结果都是约等于的值,因为:同一个浏览器,我们是否设置overflow='hidden'对于最终的结果是由影响的;在不同的浏览器中我们获取到的结果也是不想同的
//scrollLeft/scrollTop:滚动条卷去的宽度和高度
2、关于JS盒子模型属性取值的问题
● 通过上面这13个属性值获取的结果永远不可能出现小数,都是整数;浏览器在获取结果的时候,在原来真实结果的基础上进行四舍五入
3、关于操作浏览器本身的盒子模型信息
● clientWidth/clientHeight是当前浏览器可视窗口的(一屏幕的宽度和高度)
● scrollWidth/scrollHeight是当前页面的真实宽度和高度(所有屏加起来的宽度和高度~但是是一个约等于的值)
//-> 我们不管哪些属性,也不管是什么浏览器,也不管是获取还是设置,想要都兼容的话,需要写两套
document.documentElement[attr]||document.body[attr]
//->必须document.documentElement在前
//[获取要写两套]
document.documentElement.clientHeight||document.body.clientHeight
//[设置也要写两套]
document.documentElement.scrollTop=0;
document.body.scrollTop = 0;
小练习:
● win:编写一个有关于操作浏览器盒子模型的方法
//如果值传递了attr没有传递value,默认的意思是"获取"
//如果两个参数都传递了,意思是"设置"
//->不严谨来说这就是有关于"类的重载":同一个方法,通过传递参数的不同实现了不同的功能
function win(attr,value){
if(typeof value === "undefined"){ //没有传递value值 -> '获取'
return document.documentElement[attr] || document.body[attr]
}
// -> 设置
document.documentElement[attr] = value
document.body[attr] = value
}
获取元素的某一个具体的样式属性值
1、元素.style.属性名
//->需要我们把元素的样式写在行内样式上才可以(写在样式表中是不管用的)
console.log(box.style.height) //-> ""
//如果样式都写在行内,这样就不能属性CSS和HTML想分离
2、使用window.getComputedStyle这个方法获取所有经过浏览器计算过的样式
//->所有经过浏览器计算过的样式;只要当前的元素标签可以在页面中呈现出来,那么它的所有的样式都是经过浏览器计算过的(渲染过的) -> 哪怕有些样式没有写,也可以获取到
console.log(window.getComputedStyle(box,null)['height']) //200px
// ->window.getComputedStyle(当前要操作的元素对象,当前元素的伪类[一般不用伪类写null])
// ->获取的结果是CSSStyleDeclaration这个类的一个实例:包含了当前元素的所有的样式属性和值
// console.log(window.getComputedStyle(box,null)['height'])
3、ie6-8不兼容
//在ie下,可以使用currentStyle来获取浏览器计算过的样式
console.log(box.currentStyle.height)
小练习
● getCss:获取当前元素所有经过浏览器计算过的样式中的[attr]对应的值
//curEle:[object]当前要操作的元素对象
//attr:[String]要获取的样式属性的名称
//1、使用try、catch来处理兼容
//->前提:必须保证try中的代码在不兼容浏览器中执行的时候报错,这样才可以用catch捕获到异常信息,进行其他的处理
function getCss(curEle,attr){
let val = null;
try{
val = window.getComputedStyle(curEle,null)[attr]
} catch(e) {
val = curEle.currentStyle[attr]
}
return val
}
//2、判断当前浏览器中是否存在这个属性或者方法,存在就是兼容,不存在就是不兼容
function getCss(curEle,attr){
let val = null;
if("getComputedStyle" in window){ //如果进来了代表兼容
val = window.getComputedStyle(curEle,null)[attr]
}else{
val = curEle.currentStyle[attr]
}
return val
}
function getCss(curEle,attr){
let val = null;
if(winodw.getComputedStyle){ //如果进来了代表兼容
val = window.getComputedStyle(curEle,null)[attr]
}else{
val = curEle.currentStyle[attr]
}
return val
}
//3、通过检测浏览器版本和类型来处理兼容
window.navigator.userAgent
//4、升级getCss
//第一次升级,把单位去掉
function getCss(curEle,attr){
let val = null;
let reg = null;
if("getComputedStyle" in window){ //如果进来了代表兼容
val = window.getComputedStyle(curEle,null)[attr]
}else{
val = curEle.currentStyle[attr]
}
reg = /^(-?\d+(\.\d+)?)(px|pt|rem|rem|em)?$/i;
return reg.test(val) ? parseFloat(val) : val;
}
console.log(getCss(box,'float'))
console.log(getCss(box,'border'))
用getComputedStyle获得伪类的样式
window.getComputedStyle(box,"before").content
window.getComputedStyle(box,"after").height
//第二个参数写上before或者after
offset系列用法:
1、parentNode:父亲节点 HTML结构层级关系中的上一级元素
2、offsetParent:父级参照物,在同一个平面中,最外层的元素是里面所有元素的父级参照物(和HTML层级结构没有必然的联系)
● 一般来说一个页面中所有元素的父级参照物都是body
document.body.offsetParent ->null
● 想要改变父级参照物需要通过position定位来进行改变:absolute、relative、fixed任意一个值都可以把父级参照物进行修改
//position:absolute
//position:relative
//position:fixed
ele.style.position = 'absolute' //ele是指元素
3、offsetTop/offsetLeft:当前元素(外边框)距离其父级参照物(内边框)的偏移距离
小练习
offset:等同于jQuery中的offset方法,实现获取页面中任意一个元素,距离body的偏移(包含左偏移和上偏移),不管当前元素的父级参照物是谁
/*->offset:等同于jQuery中的offset方法,实现获取页面中任意一个元素,
距离body的偏移(包含左偏移和上偏移),不管当前元素的父级参照物是谁*/
//-> 获取的结果是一个对象{left:距离body的左偏移,top:距离body的上偏移}
function offset(curEle){
let totoleft = null;
let totoTop = null;
let par = curEle.offsetParent;
//-> 首先把自己本身的进行累加
totoleft += curEle.offsetLeft;
totoTop += curEle.offsetTop;
//->只要没找到Body,就把父级参照物的边框和偏移也进行累加
while(par){
//->累加父级参照物的边框
totoleft += par.clientLeft;
totoTop += par.clientTop;
//->累加父级参照物本身的偏移
totoleft += par.offsetLeft;
totoTop += par.offsetTop;
par = par.offsetParent;
}
return {left:totoleft,top:totoTop}
}
console.log(offset(box).left)
可读写属性扩展
1、 上面的JS盒子模型中:client系列/offset系列/scrollWidth/scrollHeight都是"只读"属性->只能通过属性获取值,不能通过属性修改元素的样式
2、scrollTop/scrollLeft:滚动条卷去的高度/宽度(这两个属性是唯一"可读写"属性)
box.scrollTop = 0; //->直接回到了容器的顶部
/* ->scrollTop的值是存在边界值(最大和最小值的),我们设置的值比最小值小或者比最大值大都没用,起到
效果的依然是边界的值*/
//[最小值是0]
// box.scrollTop = -1000 // ->直接回到了容器的顶部,没有超出
// console.log(box.scrollTop) // -> 0
//[最大值 = 真实的高度 - 当前容器一屏幕的高度]
let maxTop = box.scrollHeight - box.clientHeight
console.log(maxTop)