---
# System prepended metadata

title: Bootstrap modal 搭配 手刻按鈕觸發警示訊息狀態

---

# 前提:當使用 modal 元件卻自己手刻按鈕來執行關閉 modal 時，觸發"焦點"警告訊息

首先是警告訊息碼:

```
Blocked aria-hidden on an element because its descendant retained focus. 
The focus must not be hidden from assistive technology users.
Avoid using aria-hidden on a focused element or its ancestor.
Consider using the inert attribute instead, which will also prevent focus.
For more details, see the aria-hiddensection of the WAI-ARIA specification
at https://w3c.github.io/aria/#aria-hidden.
Element with focus: <div.modal fade#exampleModal>
Ancestor with aria-hidden: <div.modal fade#exampleModal> <div class=​"modal fade" 
id=​"exampleModal" tabindex=​"-1" aria-labelledby=​"exampleModalLabel"
style=​"display:​ block;​" aria-hidden=​"true">​…​</div>​

解釋:

1. 你看到這個警告的原因是：目前被聚焦（focus）的元素（在這裡是 modal）位於一個設定了
   aria-hidden="true" 的元素之中。
2. 當一個元素被標記為 aria-hidden="true" 時，輔助技術（例如螢幕閱讀器）會忽略這個元素
   以及它所有的子元素。
3. 但此時焦點仍然停留在這個被隱藏的區域中，就會造成無障礙（Accessibility）衝突。


```

**QA: 為什麼會觸發此警告訊息碼呢?**

🔍 當關閉按鈕是自己手刻並在 `<label>` 自行加入 data-bs-dismiss="modal" 屬性後 ;
導致**焦點 (focus) 與 aria-hidden 屬性之間的時序問題**造成的。


```
html.

<div class="modal fade" id="exampleModal" tabindex="-1"
     aria-labelledby="exampleModalLabel"
     style="display: block;"
     aria-hidden="true">
  ...
  
   <div class="modal-footer modal-footer-padding">
     <label for="update-password"
            class="btn border printPadding rounded-16 m-0 text-bg-dark"
            data-bs-dismiss="modal" @click.prevent="updatePwd($event)">
        更新密碼
       <span class="material-icons-outlined align-bottom ms-1">
         chevron_right
       </span>
     </label>
     <input type="text" id="update-password" name="update-password"
            class="d-none">
   </div> 
</div>
```
---

**QA: 那如果將 aria-hidden 這個屬性直接移除可行嗎??**

👉 在 Web3 或現代 Web 規範中，即使是 Web3 應用（或任何前端框架:例如使用 React、Next.js、dApp 前端等），仍然是建立在 HTML5 + WAI-ARIA 規範之上，所以仍然會遵守 WAI-ARIA 標準。但`aria-hidden="true"`在特定情境下並不是「一定要有」的屬性，它是一個可選的輔助屬性。

--

**QA: 那 aria-hidden="true" 到底該在哪裡用、何時該避免用??**

🧭 1. 首先來看 `aria-hidden="true"` 的核心用途

**目的：**
* 讓螢幕閱讀器（Screen Reader）忽略某個元素和它的所有子元素 ;
它不會影響畫面顯示，只影響「輔助技術」的可見性。

**換句話說：**

* 視覺上 → 元素仍然存在。
* 螢幕閱讀器 → 當作不存在。

🎯 2. 實際使用場景分類

| 使用情境                                  | 是否應使用 `aria-hidden="true"` | 原因說明                                                              |
| ------------------------------------- | -------------------------- | ----------------------------------------------------------------- |
| **裝飾性元素**（例如純 icon、SVG、背景圖案）          | ✅ 是                        | 讓螢幕閱讀器略過這些沒有語意的圖像。                                                |
| **用來輔助顯示但非資訊重點的元素**（例如重複顯示的標題、陰影層）    | ✅ 是                        | 避免螢幕閱讀器重複讀出內容。                                                    |
| **顯示動畫、載入中轉圈圈 (spinner)**             | ✅ 是                        | 通常不需要被朗讀。                                                         |
| **顯示狀態切換時隱藏某區塊（非使用 `display:none`）**  | ✅ 可用                       | 例如透過 `visibility: hidden` 隱藏時，補上 `aria-hidden="true"` 讓螢幕閱讀器同步忽略。 |
| **背景被 modal 蓋住時**                     | ✅ 是                        | 當 modal 開啟時，把背景主內容標記為 `aria-hidden="true"`，避免螢幕閱讀器「穿透」去讀背景。       |
| **Modal、Dialog、Alert 本身**             | ❌ 否                        | 它應該可被螢幕閱讀器讀取與操作。                                                  |
| **互動元素（按鈕、輸入框、選單）**                   | ❌ 否                        | 否則會讓使用者無法透過輔助技術使用該元件。                                             |
| **被 `display:none` 或 `hidden` 隱藏的元素** | ❌ 否                        | 因為它們已經自動被螢幕閱讀器忽略，不需重複設定。                                          |


--

🧩 3. 典型範例

```
✅ 正確使用：純裝飾圖示
<button>
  <span class="icon" aria-hidden="true">⭐</span>
  收藏
</button>
```
* 螢幕閱讀器只會讀出「收藏」，不會念出「星星」這個符號。

--
```
✅ 正確使用：開啟 modal 時隱藏背景
<main id="page-content" aria-hidden="true">
  <!-- 背景內容 -->
</main>

<div role="dialog" aria-modal="true">
  <!-- modal 內容 -->
</div>
```
* 這樣可以讓螢幕閱讀器專注在對話框（modal）內，不會「跳出去」讀取背景。

--
```
❌ 錯誤使用：把互動內容藏起來
<div aria-hidden="true">
  <button>提交</button>
</div>
```
* 這會讓輔助技術無法找到「提交」按鈕，也無法操作它。

---
**QA: 那能怎麼解決 "焦點出錯" 這樣的警告訊息呢??**

* 首先我們先來看 **"焦點管理的流程"** 如下:

```
[初始狀態]
Modal 元素：
  - aria-hidden="true"
  - display: none
  - 無焦點

使用者操作：
  點擊「開啟 modal 按鈕」 (Bootstrap 提供或自己手刻)

  │
  ▼
[Bootstrap 開啟 modal]
  - 移除 aria-hidden
  - 加上 .show
  - 聚焦到 modal 的第一個可聚焦元素
  - modal 內容被螢幕閱讀器讀取
  - 焦點現在在 modal 內

  │
  ▼
[使用者操作]
  點擊「手刻關閉按鈕」 (data-bs-dismiss="modal" + updatePwd)
  
  │
  ▼
[你的程式執行]
  - document.activeElement.blur()
    → 將焦點移出 modal 內的元素，避免焦點留在被隱藏元素上
  - 執行業務邏輯，例如更新密碼

  │
  ▼
[Bootstrap JS 處理關閉]
  - 移除 .show
  - 加回 aria-hidden="true"
  - 將焦點移回觸發 modal 的按鈕 (或上一次聚焦元素)
  - modal 完全隱藏，焦點安全轉移
  - 不會觸發「Blocked aria-hidden」警告

  │
  ▼
[結束]
  - modal 隱藏
  - 焦點安全在頁面上
  - 輔助技術（螢幕閱讀器）正常讀取
```
####  按照上述的流程圖來看，可以知道 Bootstrap 的 modal 在 初始狀態會設定： 
`<div class="modal fade" id="exampleModal" tabindex="-1" aria-hidden="true">`

#### 所以一開始 modal 是隱藏的，螢幕閱讀器不會讀它
* 當開啟 modal 時，Bootstrap JS 會自動：
1. 移除 aria-hidden="true"
2. 加上 .show
3. 聚焦到 modal

* 關閉 modal 時，Bootstrap JS 會自動：

1. 移除 .show
2. 加回 aria-hidden="true"
3. 將焦點移回觸發 modal 的按鈕

所以依照上述來看 Bootstrap JS 已經管理了 aria-hidden，不需要手動刪掉或加上。

--
**❌ 那為什麼你現在會跳警告??**

**你自己手刻的 `<label>` 當作關閉按鈕，按下時：**

* Bootstrap 會觸發 modal 關閉
* 但是你的程式裡有 焦點還在 modal 元素內

--

#### 💡 所以我們只需保留 Bootstrap 預設 `aria-hidden="true"`，並透過 JS 來消除 "焦點" 的警告訊息即可 

```
js.
updatePwd(e){

  // 先讓焦點移到文件主體，避免焦點留在 modal 裡
  document.activeElement.blur();
  
}

```
✅原理:

* 焦點移出 modal 內的元素
* Bootstrap 自己會在動畫結束時自動加回 aria-hidden="true"

✅效果:

* 不會有警告
* modal 正常開關
* 輔助技術可以正常讀取焦點轉移
