關於display:none與visibility:hidden

分析和研究兩者css屬性的差異和特性


在前端開發中,display:nonevisibility:hidden 是兩個常用的 CSS 屬性,用來控制元素的顯示和隱藏。雖然它們都能達到隱藏元素的效果,但在應用場景、性能和影響上卻有顯著差異。本文將深入探討這兩個屬性,並對它們的優勢和劣勢進行詳細比較。

TLDR

  • display:none 完全移除元素,不佔用空間,適合需要暫時不顯示內容的情況,但會觸發Reflow
  • visibility:hidden 隱藏元素但保留空間,適合需要保持布局不變的情況,性能開銷較低,但會保留事件響應問題。
  • 兩者都會參與構建DOM Tree

一、display:nonevisibility:hidden 的基本概念

1.1 display:none

display:none 是一個用來完全移除元素的 CSS 屬性。當元素被設置為 display:none 時,它不僅從視覺上消失,還會完全從 DOM 的渲染樹中移除,不佔用任何空間,但仍有參與構建DOM Tree (使用getElementById去check)。

Example:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Example</title>
    <style>
      .hidden {
        display: none;
      }
    </style>
  </head>
  <body>
    <div class="visible">可見元素</div>
    <div id="hidden-element" class="hidden">隱藏元素</div>
 
    <script>
      var hiddenElement = document.getElementById('hidden-element');
      console.log(hiddenElement);
    </script>
  </body>
</html>

1.2 visibility:hidden

visibility:hidden 是一個用來隱藏元素的CSS屬性。但與 display:none 不同,visibility:hidden 只是讓元素不可見,元素依然佔據原本的位置和空間。並且也參與構建DOM Tree。

Example:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>visibility:hidden 示例</title>
    <style>
      .hidden {
        visibility: hidden;
      }
    </style>
  </head>
  <body>
    <div class="visible">可見元素</div>
    <div id="hidden-element" class="hidden">隱藏元素,佔據空間</div>
 
    <script>
      var hiddenElement = document.getElementById('hidden-element');
      console.log(hiddenElement);
    </script>
  </body>
</html>

二、display:nonevisibility:hidden 的區別

這裡以三個常見的隱藏方法去做比較

  • display:none

    • DOM結構:瀏覽器不會渲染 display 屬性為 none 的元素,但仍參與DOM Tree構建,不佔據空間。
    • 事件監聽:無法進行 DOM 事件監聽,因為元素從渲染樹中移除。
    • 性能:動態改變此屬性時會引起 Reflow,性能開銷較大。
    • 繼承:不會被子元素繼承,因為子元素也不會被渲染。
  • visibility:hidden

    • DOM結構:元素被隱藏,但會被渲染,不會消失,並佔據空間。
    • 事件監聽:無法進行 DOM 事件監聽,因為元素不可見。
    • 性能:動態改變此屬性時會引起 Repaint,性能開銷較低。
    • 繼承:會被子元素繼承,子元素可以通過設置 visibility: visible; 來取消隱藏。
  • opacity: 0

    • DOM結構:透明度為 0%,元素隱藏,但佔據空間。
    • 事件監聽:可以進行 DOM 事件監聽,因為元素仍在渲染樹中。
    • 性能:提升為合成層,不會觸發 Repaint,性能較高。
    • 繼承:會被子元素繼承,但子元素無法通過 opacity: 1 來取消隱藏。

三、優勢與劣勢

3.1 display:none 的優勢與劣勢

優勢:

  1. 完全移除元素: 可以完全移除元素,適合用於需要暫時不顯示的內容,比如彈出框、選單等。
  2. 不佔用空間: 因為元素完全從布局中移除,所以不會影響其他元素的布局,適合用於需要動態改變布局的場景。
  3. 提升性能: 在某些情況下,display:none 可能會提升性能,因為瀏覽器不需要為隱藏的元素計算樣式和佈局。

劣勢:

  1. Reflow 開銷大: 設置或移除display:none會觸發 Reflow,性能開銷較大。
  2. 不可用於過渡效果: 無法與 CSS 過渡效果一起使用,因為元素會立即從 DOM 中移除。

3.2 visibility:hidden 的優勢與劣勢

優勢:

  1. 保留空間: 保留了元素在頁面上的空間,適合用於需要保持布局不變的情況,比如表格中的單元格隱藏。
  2. 低性能開銷: 只會觸發 Repaint,性能開銷較低,適合頻繁顯示或隱藏元素的場景。
  3. 可用於過渡效果: 可以與 CSS 過渡效果一起使用,適合需要淡入淡出的場景。

劣勢:

  1. 仍然佔用空間: 元素仍然佔用空間,可能會影響布局和其他元素的顯示。
  2. 事件響應問題: 雖然元素不可見,但仍然存在於 DOM 中,可能會導致一些意想不到的事件響應問題。

五、常見案例

5.1 Example: 動態隱藏和顯示導航菜單

在某些情況下,我們需要動態隱藏和顯示導航菜單。在這個案例中,我們可以使用 display:nonevisibility:hidden 來實現不同的效果。

使用 display:none

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>動態隱藏和顯示導航菜單</title>
    <style>
      .menu {
        display: none;
      }
      .menu.active {
        display: block;
      }
    </style>
  </head>
  <body>
    <button onclick="toggleMenu()">切換菜單</button>
    <div id="menu" class="menu">
      <ul>
        <li>首頁</li>
        <li>關於我們</li>
        <li>聯絡我們</li>
      </ul>
    </div>
    <script>
      function toggleMenu() {
        const menu = document.getElementById('menu');
        menu.classList.toggle('active');
      }
    </script>
  </body>
</html>

使用 visibility:hidden

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>動態隱藏和顯示導航菜單</title>
    <style>
      .menu {
        visibility: hidden;
      }
      .menu.active {
        visibility: visible;
      }
    </style>
  </head>
  <body>
    <button onclick="toggleMenu()">切換菜單</button>
    <div id="menu" class="menu">
      <ul>
        <li>首頁</li>
        <li>關於我們</li>
        <li>聯絡我們</li>
      </ul>
    </div>
    <script>
      function toggleMenu() {
        const menu = document.getElementById('menu');
        menu.classList.toggle('active');
      }
    </script>
  </body>
</html>

5.2 Example: 表格中隱藏列

在處理表格時,我們可能需要隱藏某些列,但希望其他列的位置不變。在這種情況下,visibility:hidden 是一個更好的選擇。

使用 visibility:hidden 隱藏表格列

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>隱藏表格列</title>
    <style>
      .hidden {
        visibility: hidden;
      }
    </style>
  </head>
  <body>
    <table border="1">
      <tr>
        <th>Name</th>
        <th class="hidden">Age</th>
        <th>Gender</th>
      </tr>
      <tr>
        <td>Alice</td>
        <td class="hidden">28</td>
        <td>Female</td>
      </tr>
      <tr>
        <td>Bob</td>
        <td class="hidden">34</td>
        <td>Male</td>
      </tr>
    </table>
  </body>
</html>

六、總結

display:nonevisibility:hidden 是兩個強大的工具,它們各自有著不同的應用場景和優勢。在選擇使用哪一個屬性時,應該根據具體需求和性能考量來做出決定。