display和visbility顾名思义都是为了隐藏页面元素,下面来看看二者的区别。opacity最后再说。

一、display:none

1、给元素设置了display:none属性后,该元素就隐藏了,占用的空间也消失了。
原来是这样:

    <div>
      <button>A按钮</button>
      <button>B按钮</button>
      <button>C按钮</button>
    </div>

image.png

加了display:none 属性后

    <div>
      <button>A按钮</button>
      <button style="display: none">B按钮</button>
      <button>C按钮</button>
    </div>

image.png

事实证明,“B按钮” 占用的空间也消失了。

2、给父元素设置display:none属性后,子属性也跟着隐藏。
原来的样子:

    <div>
      <button>A按钮</button>
      <button>B按钮</button>
      <button>C按钮</button>
      <ol>
        <li>hello</li>
        <li>hello2</li>
      </ol>
    </div>

image.png

给父元素加上display:none后,子元素都消失了

    <div>
      <button>A按钮</button>
      <button>B按钮</button>
      <button>C按钮</button>
      <ol style="display: none">
        <li>hello</li>
        <li>hello2</li>
      </ol>
    </div>

image.png

即使给子元素加上block也不会显示。

  <div>
     <button>A按钮</button>
     <button>B按钮</button>
     <button>C按钮</button>
     <ol style="display: none">
       <li style="display: block">hello</li>
       <li>hello2</li>
     </ol>
   </div>

image.png
3、因为display:none后元素就消失了,在li标签下会影响计数。比如
原来的代码:

    <div>
      <button>A按钮</button>
      <button>B按钮</button>
      <button>C按钮</button>
      <ol>
        <li>hello</li>
        <li>hello2</li>
        <li>hello3</li>
      </ol>
    </div>

image.png
给子元素加上隐藏:

  <div>
     <button>A按钮</button>
     <button>B按钮</button>
     <button>C按钮</button>
     <ol>
       <li>hello</li>
       <li style="display: none">hello2</li>
       <li>hello3</li>
     </ol>
   </div>

image.png

因为子元素被隐藏了,下面的元素就自动上移了。

二、visibility:hidden

1、使用visibility隐藏属性后,元素仍然占用原来的页面空间。

 <div>
   <button>A按钮</button>
   <button style="visibility: hidden">B按钮</button>
   <button>C按钮</button>
 </div>

隐藏后
image.png
2、父元素会影响子元素,以及如果子元素设置显示后,会消除隐藏属性。

<div>
      <button>A按钮</button>
      <button>B按钮</button>
      <button>C按钮</button>
      <ol style="visibility: hidden">
        <li>hello</li>
        <li>hello2</li>
        <li>hello3</li>
      </ol>
    </div>

image.png

 <div>
   <button>A按钮</button>
   <button>B按钮</button>
   <button>C按钮</button>
   <ol style="visibility: hidden">
     <li>hello</li>
     <li style="visibility: visible">hello2</li>
     <li>hello3</li>
   </ol>
 </div>

image.png

由此可见,第三点,visibility也不会影响计算,只是给隐藏的那些元素披上了隐身衣而已,不会影响别的元素。

最后一点:
首先了解下浏览器的渲染过程:
1.解析HTML,根据文档构建DOM树
2.解析CSS样式表,构建CSSOM(CSS Object Model)
3.将DOM和CSSOM进行合并生成Render Tree(渲染树);在DOM树基础上根据节点的属性(margin/padding/width/height)生成reder树,不包括display:none、head节点但包括visibility:hidden节点)
4.根据Render Tree计算布局,计算每个元素的位置,又叫layout的reflow过程
5.依据Render Tree进行渲染,调用操作系统的 Native GUI的API绘制。

其次了解两个概念,重绘和回流
1.重绘(repoint):当Render Tree中的一些元素需要更新属性,但这些属性只会影响元素的外观,风格,而不会影响布局。
2.回流(reflow):当Render Tree中的一部分(或所有)因为其中元素的规模尺寸、布局、隐藏等改变而需要重新构建Render Tree。

因为display:none 会改变页面布局,所以会触发reflow(回流),而visibility:hidden并不影响 页面布局,只是给元素穿上了“隐身衣”,所以只会触发 repoint(重绘)

总结:

(下面display:none就简写为display,visibility:hidden就简写为visibility)
1) display的隐藏会直接把元素去掉,其占用的空间也消失;visibility相反,只是给隐藏的元素穿了层“隐身衣”,其占用的空间并不会消失。
2) display父元素设置为隐藏后子元素也会隐藏,但是子元素若设置为显示并不奏效;
visibility父元素隐藏子元素隐藏,父元素隐藏子元素显示会奏效。
3) display因为直接把元素去掉了,所以会影响计数,比如上面例子里的li标签,就下面的元素自动替补被隐藏的元素了。visibility因为只是单纯的隐藏,所以不会影响计数。
4)由于display影响页面布局,所以会触发reflow(回流),visibility则只会触发repoint(重绘)。

千言万语汇成一句话

就是display把一个元素丢出界面,所以空间会消失、别的元素会替补以及触发回流(重新布局)。而visibility只是给元素穿了个“隐身衣”,所以其空间还在、不会影响计数、只会触发重绘(布局不变,但是要增加“隐身衣”效果。)

补充:其实还有个方法可以隐藏元素,那就是opacity:0,这个属性是设置透明度的,取值范围是0-1,设置为0就是隐藏了,1就是完全显示,这个方法和visibility的特质一样,简而言之就是给元素穿了隐身衣而已。

参考文章:
浏览器的渲染原理简介:https://coolshell.cn/articles...


Catalpa
9 声望1 粉丝