第 57 题:分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景
zeroone001 opened this issue · 21 comments
- display: none (不占空间,不能点击)(场景,显示出原来这里不存在的结构)
- visibility: hidden(占据空间,不能点击)(场景:显示不会导致页面结构发生变动,不会撑开)
- opacity: 0(占据空间,可以点击)(场景:可以跟transition搭配)
补充: opacity 场景: 自定义图片上传按钮
补充:株连性
如果祖先元素遭遇某祸害,则其子孙孙无一例外也要遭殃,比如:
opacity:0和display:none,若父节点元素应用了opacity:0和display:none,无论其子孙元素如何挣扎都不会再出现在大众视野;
而若父节点元素应用visibility:hidden,子孙元素应用visibility:visible,那么其就会毫无意外的显现出来。
display: none 会回流操作 性能开销较大,
visibility: hidden 是重回操作 比回流操作性能高一些,(回流会计算相邻元素甚至组先级元素的位置,属性等)
opacity: 0 重建图层,性能较高
总结一下:
结构:
display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击,
visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击
opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
继承:
display: none和opacity: 0:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。
visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。
性能:
displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大
visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容
opacity: 0 : 修改元素会造成重绘,性能消耗较少
联系:它们都能让元素不可见
display: none;
- DOM 结构:浏览器不会渲染
display属性为none的元素,不占据空间; - 事件监听:无法进行 DOM 事件监听;
- 性能:动态改变此属性时会引起重排,性能较差;
- 继承:不会被子元素继承,毕竟子类也不会被渲染;
- transition:
transition不支持display。
visibility: hidden;
- DOM 结构:元素被隐藏,但是会被渲染不会消失,占据空间;
- 事件监听:无法进行 DOM 事件监听;
- 性 能:动态改变此属性时会引起重绘,性能较高;
- 继 承:会被子元素继承,子元素可以通过设置
visibility: visible;来取消隐藏; - transition:
transition不支持display。
- opacity: 0;
- DOM 结构:透明度为 100%,元素隐藏,占据空间;
- 事件监听:可以进行 DOM 事件监听;
- 性 能:提升为合成层,不会触发重绘,性能较高;
- 继 承:会被子元素继承,且,子元素并不能通过
opacity: 1来取消隐藏; - transition:
transition不支持opacity。
display:none指的是元素完全不陈列出来,不占据空间,涉及到了DOM结构,故产生reflow与repaint。
visibility:hidden指的是元素不可见但存在,保留空间,不影响结构,故只产生repaint(脱离文档流),子元素可以通过设置 visibility: visible; 来取消隐藏;
opacity: 0:透明度为 100%,元素仍存在,不影响结构,不和动画属性一起则不会产生repaint(不脱离文档流),子元素并不能通过 opacity: 1 来取消隐藏;
visibility:hidden 隐藏元素,但是元素本身还是存在的
display: none 元素是不占据空间,
opacity: 0 透明度为 100%
总结一下:
结构:
display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击,
visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
继承:
display: none和opacity: 0:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。
visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。
性能:
displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大
visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容
opacity: 0 : 修改元素会造成重绘,性能消耗较少
联系:它们都能让元素不可见visibility: hidden; 不可以点击,拼写错了吧。
是的,该过来了
总结下
display:none: dom根本不生成 不占据空间 子元素会被株连 重新设置 会引发重绘 和 回流
visibility:hidden dom生成 占据空间 但是 不可以点击 不可见 重设会引发重绘 子元素可以动过设置visible设置为可见
opacity:0; dom生成 占据空间 只是透明度为0 不可见 可以点击 重设会引发重绘 子元素可以动过设置1设置为可见
display: none 会回流操作 性能开销较大,
visibility: hidden 是重回操作 比回流操作性能高一些,(回流会计算相邻元素甚至组先级元素的位置,属性等)
opacity: 0 重建图层,性能较高
浏览器在渲染的时候生成的layout tree并不会包含display:none的元素,为什么还会引起回流呢
补充:
display: none; 如果应用在了某个SEO场景,是会判SEO作弊的,这个要注意
1、display: none 触发回流,消耗性能较大
2、visibility: hidden 触发重绘,消耗性能较1少
3、opacity: 0 css3硬件加速,不触发回流重绘,大大减少性能消耗
display: none;
- DOM 结构:浏览器不会渲染
display属性为none的元素,不占据空间;- 事件监听:无法进行 DOM 事件监听;
- 性能:动态改变此属性时会引起重排,性能较差;
- 继承:不会被子元素继承,毕竟子类也不会被渲染;
- transition:
transition不支持display。
visibility: hidden;
- DOM 结构:元素被隐藏,但是会被渲染不会消失,占据空间;
- 事件监听:无法进行 DOM 事件监听;
- 性 能:动态改变此属性时会引起重绘,性能较高;
- 继 承:会被子元素继承,子元素可以通过设置
visibility: visible;来取消隐藏;- transition:
transition不支持display。
- opacity: 0;
- DOM 结构:透明度为 100%,元素隐藏,占据空间;
- 事件监听:可以进行 DOM 事件监听;
- 性 能:提升为合成层,不会触发重绘,性能较高;
- 继 承:会被子元素继承,且,子元素并不能通过
opacity: 1来取消隐藏;- transition:
transition不支持opacity。
transition 是支持 visibility 和 opacity 的噢,CSS animated properties可查。
- visibility 会立即显示,隐藏时会延时
- opacity 可以延时显示和隐藏
问:用 CSS 隐藏页面上的一个元素有哪几种方法?
这道题绝大多数人的答案都是 display:none visibility:hiden opacity:0 这三种,但如果还能说出下面三种我觉得也是加分的:
- 设置
fixed并设置足够大负距离的lefttop使其“隐藏”; - 用层叠关系
z-index把元素叠在最底下使其“隐藏”; - 用
text-indent:-9999px使其文字隐藏。
适用场景呢
我觉得上面关于 opacity 重绘说的都有问题。所以来总结下:
- 在一般情况下,opacity 会触发重绘,即
Recalculate style=>Update Layer Tree。不管你是否开启GPU提升为合成层与否 - 如果利用 animation 动画,对 opacity 做变化(animation会默认触发GPU加速),则只会触发 GPU 层面的 composite,不会触发重绘。
以上可以使用 performance 验证!!!
打个比方
- display: none 从这个世界消失了, 不存在了
- opacity: 0 视觉上隐身了, 看不见, 可以触摸得到
- visibility: hidden; 视觉和物理上都隐身了, 看不见也摸不到, 但是存在的
补充一点,使用ol+li计数时,display:none是不参与计数的,而visibility:hidden参与计数
display: none 会回流操作 性能开销较大,
visibility: hidden 是重回操作 比回流操作性能高一些,(回流会计算相邻元素甚至组先级元素的位置,属性等)
opacity: 0 重建图层,性能较高浏览器在渲染的时候生成的layout tree并不会包含display:none的元素,为什么还会引起回流呢
他说的容易引起歧义。准确地说应该是给元素设置 display: none 之后,会导致元素脱离布局树,触发重排。如果元素本身就是 display: none 了,那么针对它的其它操作不会再触发重排。
三种情况各有其使用场景,重点区别在于两点,
- visibility:hidden元素无法使用事件监听,而同为opacity: 0可以使用事件
- visibility: hidden元素具有继承属性,子元素使用 visibility: visible就是可以让元素展示
display: none;
- DOM 结构:浏览器不会渲染
display属性为none的元素,不占据空间;- 事件监听:无法进行 DOM 事件监听;
- 性能:动态改变此属性时会引起重排,性能较差;
- 继承:不会被子元素继承,毕竟子类也不会被渲染;
- transition:
transition不支持display。
visibility: hidden;
- DOM 结构:元素被隐藏,但是会被渲染不会消失,占据空间;
- 事件监听:无法进行 DOM 事件监听;
- 性 能:动态改变此属性时会引起重绘,性能较高;
- 继 承:会被子元素继承,子元素可以通过设置
visibility: visible;来取消隐藏;- transition:
transition不支持display。
- opacity: 0;
- DOM 结构:透明度为 100%,元素隐藏,占据空间;
- 事件监听:可以进行 DOM 事件监听;
- 性 能:提升为合成层,不会触发重绘,性能较高;
- 继 承:会被子元素继承,且,子元素并不能通过
opacity: 1来取消隐藏;- transition:
transition不支持opacity。
opacity: 0不会被子元素继承