理解和操作z-index

理解和操作z-index

z-index,这个css属性我感觉是很多人容易忽略的一个点。而且理解的不够好(当然也包括我自己啦),但是不理解一些其他影响元素层叠秩序的因素——层叠上下文,定位,透明度。

1.z-index究竟是什么?
=>盒子在堆叠上下文中的堆叠级别
=>盒子是否建立了一个堆叠上下文
什么是堆叠上下文,那就是我们看到的网页实际上是三维的,和设备屏幕垂直的就是元素所在的渲染层,元素就是在这个层上进行堆叠。

2.默认堆叠次序(没有z-index的元素)*
=>根节点的背景和边框
=>文档流中的后代元素,按照在html中出现的顺序
=>脱离文档流的定位元素,按照html中出现的顺序

3.重写默认堆叠次序,也就是赋值z-index
当z-index大于0,那么意味着这个元素“离”设备屏幕距离更近。z-index最高的那一个才是离设备屏幕最近的那个一,但是生效的前提是,元素处于同一个堆叠上下文当中

4.堆叠上下创建的条件
a.首先页面的根元素< html >创建的默认堆叠上下文
b.对于其他元素创建堆叠上下文的条件是:成为定位元素,并且具有非auto的z-index属性值,或者元素具有小于1的opacity属性

5.管理z-index
在简单的网页应用当中,堆叠上下文貌似不是一个什么重要的事情,但是当界面越来越复杂,并出现各种丰富的UI控件,页面就出现了多个堆叠上下文。当页面出现多个页面上下文时,管理z-index就会越来越复杂,同时也会变得越来越重要。
因此编程式的管理z-index就是一种非常可靠的方案。

/**
*管理z-index堆叠上下文
**/
let isPosZindex = (el)=>{/*具有非0的z-index的定位元素会创建堆叠上下文*/
	return el.style.position !=='static'&&el.style.zIndex !=='auto' 
}

let doesStyleZindex = (el)=>{/*这些值将会创建堆叠上下文*/
	let styles = el.style;
	if(styles.opacity<1){
		return true
	}
	if(styles.transform!=='none'){
		return true
	}
	if(styles.transformStyle ==='preserve-3d'){
		return true
	}
	if(styles.perspective !=='none'){
		return true
	}
	if(styles.flowFrom!=='none'&&styles.content!=='normal'){
		return true
	}
	if(styles.position ==='fixed'){
		return true
	}
	return false
}
let zindexAdmin = (global)=>{
	return{
		isStackCtx(el){//判断是否创建了堆叠上下文
			/*因为不同的游览器对于元素创建的堆叠上下文的规则是不同的,特性嗅探策略是*/
			return el.tagName ==='HTML'||(isPosZindex(el)&&doesStyleZindex(el));
		},
		getStackCtx(el){//得到创建堆叠上下文的祖先
			let parentNode = el.parentNode;
			while(!zindexAdmin.isStackCtx(parentNode)){//当没有父辈节点创建堆叠上下文时
				parentNode =parentNode.parentNode;
			}
			return parentNode
		},
		bringToFront(el,createStackingCtx,root){//将元素放在堆叠上下文顶部
			alterZindex(el,createStackingCtx,root,true);
		},
		sendToBack(el,createStackingCtx,root){//将元素放在堆叠上下文底部
			alterZindex(el,createStackingCtx,root,false);
		}
	}	
}
/**
*修改元素的z-index
**/
let modifyZindex = (el,increment)=>{
	let stackCtxEl = zindexAdmin.getStackCtx(el);
	let siblings = stackCtxEl.childNodes;
	let siblingMaxMinZindex = increment?0:-1;
	let siblingZindex;
	for(let i = 0;i<siblings.length;i++){
		if(siblings[i].nodeType ===1 &&isPosZindex(siblings[i])&&siblings[i] !==el){
			siblingZindex = parseInt(siblings[i].style.zIndex,10);//检查兄弟元素是否有z-index
			if(isNaN(siblingZindex)){
				continue
			}
			if(increment){
				/*更新兄弟元素的最大z-index的值*/
				siblingMaxMinZindex = siblingZindex>siblingMaxMinZindex?siblingZindex:siblingMaxMinZindex
			}else{
				siblingMaxMinZindex = siblingMaxMinZindex<0||siblingZindex<siblingMaxMinZindex?siblingZindex:siblingMaxMinZindex;
			}
		}
	}
	if(!siblingMaxMinZindex&&!increment){
		for(let i =0;i<siblings.length;i++){
			if(siblings[i].nodeType ===1&&siblings[i]!==el){
				siblingZindex = parseInt(siblings[i].style.zIndex,10)
				if(isNaN(siblingZindex)){
					continue
				}
				siblings[i].style.zIndex == ++siblingZindex;
			}
		}
	}
	el.style.zIndex = increment?siblingMaxMinZindex+1:(siblingMaxMinZindex?siblingMaxMinZindex-1:0)
}
/**
*修改元素的z-index
*设计思想:移动对应的元素,使之出现在元素所在的堆叠上下文顶部或者底部,并且在必要的时候,在父元素上创建堆叠上下文
*createStackingCtx参数控制这个行为:true,设置父元素为position:relative,z-index=0,
**/

let alterZindex = (el,createStackingCtx,root,increment)=>{
	let stackCtxEl = zindexAdmin.getStackCtx(el);
    if(createStackingCtx&&stackCtxEl!==el.parentNode){
    	if(isFunction(createStackingCtx)){
    		createStackingCtx(el.parentNode)
    	}else{
    		el.parentNode.style.position='relative';
    		el.parentNode.style.zIndex = 0;
    	}
    }
    modifyZindex(el,increment);
    if(root&&(root!==zindexAdmin.getStackCtx(el)&&stackCtxEl.tagName !=='HTML')){
    	alterZindex(stackCtxEl,createStackingCtx,root,increment);//递归
    }
}

喜欢的朋友赏个赞哈!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值