面试题16:重绘(reflow)和回流(repaint),visibility: hidden 和 display: none的区别

45 篇文章 6 订阅

面试官:请说一下什么是重绘和回流和visibility: hidden 和 display: none的区别

回流与重绘
概念

当JS对页面的节点进行操作时,就会产生回流或重绘

回流/重排(reflow):

因为节点的尺寸布局显示(display: none/block)改变这些属性改变的时候,渲染树中的一部分或者全部需要重新构建,这种重新构建的现象就是回流。一个页面至少有一次回流。

重绘(repaint):
回流时,浏览器会看重新构建受影响部分的渲染树,只要渲染树一被改变或重新构建,就一定会引起重绘;

回流完成后,浏览器根据新的渲染树重新绘制回流影响的部分节点,这个重新绘制的过程叫做重绘;

不改变节点原有的尺寸、布局、显示、增删,就只会引起重绘。
 

小结

回流一定会引起重绘,重绘不一定是回流产生的后续反应。因为只要不是改变物理的位置、尺寸、显示,就不会引起回流。

引起回流的因素:

DOM节点增加、删除
DOM节点位置变化
元素的尺寸、边距、填充(文字、图片)、边框、宽高
DOM节点display显示与否,不包含visibility
页面渲染初始化(第一次加载页面)
浏览器窗口尺寸变化(resize)
向浏览器请求某些样式信息(offset、scroll、client、width/height、getComputedStyle、currentStyle)
除开以上几个因素以外只会引起重绘。

dom操作之所以消耗性能,就是因为容易引起回流,所以在做dom操作优化的时候就是以减少回流次数为依据来进行优化的,之所以需要缓存、文档碎片就是为了减少回流次数。
 

示例1

<div class="box">我是一个孤独的盒子</div>
<script>
    // 专给一个节点增加样式就可以这样缓存
    var oBoxStyle = document.getElementsByClassName('box')[0].style; //点语法是消耗性能的,这里缓存可以优化性能
    // 回流 + 重绘
    oBoxStyle.width = '200px';
    // 回流 + 重绘
    oBoxStyle.height = '200px';
    // 回流 + 重绘
    oBoxStyle.margin = '20px';
    // 重绘
    oBoxStyle.backgroundColor = 'green';
    // 回流 + 重绘
    oBoxStyle.border = '5px solid orange';
    // 重绘
    oBoxStyle.color = '#fff';
    // 回流 + 重绘
    oBoxStyle.fontSize = '30px';
</script>

示例2

<div class="box">我是一个孤独的盒子</div>
<script>
    var h1 = document.createElement('h1');
    h1.innerHTML = '我是一个孤独的标题';
    document.body.appendChild(h1)
</script>

h1追加在box后面只引起一次回流与重绘,但是如果追加在box前面的话,整个body里面的元素都会重新构建。所以要尽量避免插入在最前面。

在写dom的时候要考虑两个问题:

  1. 回流的问题;
  2. 回流所涉及到的节点数(一个父节点重新构建,里面的所有子节点都会重新构建)

 display:none和visibility:hidden的区别是:

相同点:

        两者都可以将dom元素隐藏

不同点:

1.display: none 隐藏之后不占用文档流(在渲染树里面不存在节点),而visibility: hidden却会占用文档流(在渲染树里面存在节点),如果要在隐藏元素的同时获取其尺寸信息,那就可以使用visibility: hidden

2.display: none 会引起页面的回流(重排)以及重绘,而visibility: hidden只会引起重绘,从性能角度上讲,visibility: hidden会稍微好点

3.display: none 的子元素不会进行显示,而visibility: hidden的子元素却是可以进行设置显示的

几种元素消失的属性:

  • display: none; 元素消失,不占位;
  • visibility: hidden; 元素消失,占位;
  • opacity: 0; 透明度设为0,元素看不见,占位;
  • width: 0; 宽度设为0,元素看不见,不占位。

1、display与元素的显隐

display: none显隐控制并不会影响CSS3 animation动画的实现,但会影响transition的过渡动画效果,因此如果要用到transition的话,建议使用visibility。

transition与display搭配使用时,会导致过渡消失,直接呈现或者消失元素,可能是transition过渡不支持display的改变,直接操作display会破坏transition的动画。

除了动画效果外,display: none还会影响CSS的计数队列。举个例子,10个列表从1开始计数,当第二个列表的display置为none,就会导致计数器忽略当前元素,原来的第三个列表则计数为2。

2、visibility与元素的显隐

visibility属性只是控制元素的可见性,不会使元素从渲染树中消失或改变整体布局,元素实际上已经存在于整个渲染树中,因此它的显隐不会触发浏览器的重排,仅仅是重绘。而display会让元素从渲染树中消失,是真正的不存在,因此如果显示的时候,会触发浏览器的重排,重新绘制整个渲染树。而重排是影响性能的主要问题,所以只要有可能,都要减少重排的出现。

visibility除了保留隐藏空间,还有很多有意思的属性,甚至跟display完全不一样的点。

首先visibility和display最大的区别点在于,父元素设置了visibility: hidden后,子元素也隐藏的深层原因在于子元素会继承父元素的visibility: hidden,因此,当我们需要隐藏父元素而又要显示部分子元素的时候,只需要把子元素继承的visibility改成默认的 visible属性即可,这点在被设置了display: none的元素上,无法实现。

visibility的元素的子元素只是单纯的继承了父元素的visibility,因此在CSS计数方面不会有任何影响,这点跟display: none也有所不同。同时transition过渡是支持visibility属性的,因此在使用过渡动画的时候,想让元素实现淡入淡出效果来控制显隐的可以使用visibility:hidden。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值