元素不可见的三种方法
opacity=0
opacity用来设置元素的透明度。
当该值为0时,该元素变透明,但是不会改变页面布局。
并且若此元素绑定了事件,点击该元素所占区域时,响应事件同样会被触发。
visibility=hidden
visibility用来设置元素的可见性。
当该值为hidden时,该元素变为不可见,但是不会改变页面布局。
对用户不可见后,点击相应的区域也无法触发绑定的事件
display=none
display定义建立布局时元素生成的显示框类型。
当该值为none时,该元素不再展示,会改变页面布局
点击相应的区域也无法触发绑定的事件
opacity : 0 | visibility : hidden | display : none | |
---|---|---|---|
是否占据页面空间 | 是 | 是 | 否 |
对子元素的影响 | 覆盖子元素 opacity : 1 | 不覆盖子元素 visibility : visible | 覆盖子元素 display : none |
监听的事件是否触发 | 是 | 否 | 否 |
被遮罩元素的监听事件是否触发(使用绝对定位覆盖) | 否 | 是 | 是 |
回流与重绘
回流 reflow
若页面中某些元素的大小,位置,可见性等属性改变造成页面的布局需要重新构建时,产生回流。
回流又名重布局 或重排。
每个页面在第一次加载时也会回流。
重绘 repaint
当页面的元素的属性更新,造成元素的外观风格改变时(页面布局不改变),产生重绘。
回流必将引起重绘,而重绘不一定会引起回流
查看重绘区域
Chrome => DevTools => Rendering => Paint flashing
需要重绘的区域将被高亮
opacity | visibility | display | |
---|---|---|---|
回流 | 否 | 否 | 是 |
重绘 | 不一定 | 会 | 会 |
元素自身+transition&元素自身监听事件=>产生渐隐渐显效果 | 是 | 否 | 否 |
元素自身+transition&其他元素监听事件=>产生渐隐渐显效果 | 是 | 是 | 否 |
合成层
页面的绘制并不一定为在内存中的单层画面绘制,有时浏览器会将一帧画面绘制为多层画面,然后将若干层画面合并成一张图片显示到屏幕上。
将页面分层可以更好的区分开页面中静态部分和动态部分的绘制。
在 Blink 和 WebKit 内核的浏览器中,具有 transition 或 animation 的 opacity 元素,渲染层被提升为合成层。
translateZ(0) 或 translate3d(0,0,0)可以人为强制创建合成层。
而元素提升为合成层后,transform 和 opacity 不会触发 重绘制。如果不是合成层,则会触发重绘。
因为透明度改变后,GPU在绘制页面时可以改变之前画好的页面的透明值,而无需整体的重绘。
但是这个被修改的opacity必须为一个单独的图层,否则图层中的其他节点也会被重绘。
transition
opacity
逐渐过度的渐隐渐显
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.blue{
width: 200px;
height: 200px;
background: blue;
transition: 1s;
}
</style>
</head>
<body>
<div class="blue" id="target"></div>
<script>
var flag = false;
setInterval(function () {
flag = !flag;
target.style.opacity = flag ? 0 : 1;
},1000)
</script>
</body>
</html>
visibility
离散效果的延迟闪烁
可以将visibility : hidden
看成 visibility : 0
并且将visibility : visible
看成 visibility : 1;
visibility的值大于0时,元素就被显示。所以尽管visibility的值是从0到1平滑过度的,但是展示效果并不平滑。
在鼠标移进元素范围内的一秒后,visibility的值才为0,元素的隐藏效果被延迟。
而元素再次移动后,visibility的值迅速变为一个大于0的值,元素的展现效果不延迟。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.blue{
width:200px;
height:200px;
background:blue;
transition:1s;
visibility:visible;
}
.blue:hover{
visibility:hidden;
}
</style>
</head>
<body>
<div class='blue'></div>
</body>
</html>
设置visibility 从 hidden 至 visible 的方法
因为元素visibility : hidden时,监听的事件不会被触发。所以当设置visibility : visible 时,不可以直接绑定在 hidden 的元素上。
使用 a 控制其他元素样式的方法
使用a控制a的子元素 b
.a:hover .b {
background-color:blue;
}
使用a控制a的兄弟| 同级元素 c
.a:hover + .c {
color:red;
}
使用a控制a的就近元素d
.a:hover ~ .d {
color:pink;
}
红色方块控制蓝色方块的显示。
当鼠标移入红色方块时,蓝色方块visibility:visible
当鼠标移出红色方块1s后,蓝色方块visibility:hidden
移入蓝色方块区域不触发事件
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.red{
width:200px;
height:200px;
background:red;
}
.blue{
width:200px;
height:200px;
background:blue;
transition:1s;
visibility:hidden;
}
.red:hover+.blue{
visibility:visible;
}
</style>
</head>
<body>
<div class='red'></div>
<div class='blue'></div>
</body>
</html>
display
display不支持transition,且会使transition失效。
因为display:none的元素不会被渲染在页面上。
但是transition只对已经渲染在页面上的元素起做作用。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.blue{
width:200px;
height:200px;
background:blue;
}
.yellow{
width:100px;
height:100px;
background:yellow;
opacity:0;
display:none;
transition:1s
}
.blue:hover .yellow{
opacity:1;
display:block;
}
</style>
</head>
<body>
<div class='blue'>
<div class='yellow'></div>
</div>
</body>
</html>
如果需要子元素出现渐隐渐显效果,只能使用visibility而不能使用display。
或者使用setTimeOut函数
var blue = document.querySelector('.blue');
blue.addEventListener('mouseenter',function(){
var yellowDiv = document.querySelector('.yellow');
yellowDiv.style.display = 'block';
setTimeout(function(){
yellowDiv.style.opacity = '1';
},0);
})