Skip to content

無障礙 PDF

無障礙 PDF(又稱 Tagged PDF)是一種具備結構標記的 PDF 文件,讓視障或其他身心障礙使用者能夠透過螢幕閱讀器等輔助技術理解文件內容。TCPDF-Next 支援建立符合 PDF/UA (ISO 14289) 標準的無障礙文件。

什麼是無障礙 PDF?

一份合格的無障礙 PDF 必須包含以下要素:

  1. 結構標記(Structure Tree) -- 用語義標籤(標題、段落、表格、圖片)建立文件的邏輯結構樹
  2. 替代文字(Alt Text) -- 為所有非文字內容(圖片、圖表)提供文字描述
  3. 語言標記 -- 標記文件語言與內容語言
  4. 閱讀順序 -- 定義與視覺排版無關的邏輯閱讀順序
  5. 表格結構 -- 表格需有正確的表頭與資料儲存格標記
  6. 書籤導覽 -- 長文件需提供書籤供導覽使用
  7. 色彩對比 -- 文字與背景的對比度需符合 WCAG 標準
  8. 字型資訊 -- 字型需有 Unicode 對應表(ToUnicode CMap)以支援文字擷取

相關標準

標準範圍
PDF/UA-2 (ISO 14289-2:2024)PDF 通用無障礙標準
WCAG 2.1 (W3C)網頁內容無障礙指引
Section 508(美國)美國聯邦無障礙要求
EN 301 549(歐盟)歐盟無障礙要求
PDF 2.0 Annex L (ISO 32000-2)Tagged PDF 技術規格

基本無障礙 PDF

文件設定

php
use YeeeFang\TcpdfNext\Document\PdfDocument;
use YeeeFang\TcpdfNext\Document\PageFormat;
use YeeeFang\TcpdfNext\Accessibility\TagManager;

$pdf = PdfDocument::create()
    ->setPageFormat(PageFormat::A4)
    ->setTitle('無障礙文件範例')
    ->setAuthor('TCPDF-Next')
    ->setLanguage('zh-TW')           // 設定文件語言
    ->setTagged(true)                 // 啟用標記式 PDF
    ->setDisplayDocTitle(true)        // 閱讀器標題列顯示文件標題而非檔名
    ->build();

$tag = $pdf->getTagManager();
$page = $pdf->addPage();

標題標記

標題必須按照層級順序使用,不可跳級(例如不能從 H1 直接跳到 H3):

php
use YeeeFang\TcpdfNext\Content\FontStyle;

// H1 標題
$tag->beginTag('H1');
$page->addText('年度報告 2026')
    ->setPosition(20, 25)
    ->setFont('Helvetica', size: 24, style: FontStyle::BOLD);
$tag->endTag();

// H2 標題
$tag->beginTag('H2');
$page->addText('執行摘要')
    ->setPosition(20, 50)
    ->setFont('Helvetica', size: 18, style: FontStyle::BOLD);
$tag->endTag();

// H3 標題
$tag->beginTag('H3');
$page->addText('財務亮點')
    ->setPosition(20, 75)
    ->setFont('Helvetica', size: 14, style: FontStyle::BOLD);
$tag->endTag();

標題層級

螢幕閱讀器會根據標題層級建立文件大綱供使用者導覽。跳過層級會讓使用者無法正確理解文件結構。

段落標記

php
$tag->beginTag('P');
$page->addParagraph(
    '公司在 2026 年交出亮眼成績,營收較去年成長 15%,'
    . '達到新台幣 24 億元。營業利潤率提升了 200 個基點,'
    . '反映出我們在營運效率上的持續改善。'
)
    ->setPosition(20, 95)
    ->setWidth(170)
    ->setFont('Times', size: 12)
    ->setLineHeight(1.5);
$tag->endTag();

圖片替代文字

圖片分為兩類:資訊性圖片需要替代文字,裝飾性圖片則標記為 Artifact 讓螢幕閱讀器跳過:

php
use YeeeFang\TcpdfNext\Graphics\Color;

// 資訊性圖片:需要描述性替代文字
$tag->beginTag('Figure');
$page->addImage('/assets/revenue-chart.png')
    ->setPosition(20, 130)
    ->setSize(170, 80)
    ->setAltText('長條圖顯示公司 2022 至 2026 年營收,從 15 億元穩定成長至 24 億元');

$tag->beginTag('Caption');
$page->addText('圖一:2022-2026 年營收趨勢(單位:億元)')
    ->setPosition(20, 212)
    ->setFont('Helvetica', size: 9)
    ->setColor(Color::rgb(100, 100, 100));
$tag->endTag(); // Caption
$tag->endTag(); // Figure

// 裝飾性圖片:標記為 Artifact,螢幕閱讀器會忽略
$page->addImage('/assets/decorative-line.png')
    ->setPosition(20, 220)
    ->setSize(170, 2)
    ->setArtifact(true);

替代文字撰寫要點

  • 資訊性圖片:描述圖片傳達的資訊,而非圖片的外觀。例如圖表要說明趨勢與數據,而非「一張長條圖」
  • 裝飾性圖片:標記為 Artifact,不需要替代文字
  • 複雜圖表:在替代文字中提供摘要,並在正文中補充詳細說明

表格結構

表格需要正確的表頭標記,螢幕閱讀器才能將資料儲存格與對應的欄位標題關聯起來:

php
$tag->beginTag('Table');

// 表格標題
$tag->beginTag('Caption');
$page->addText('表一:季度營收一覽表(單位:萬元)')
    ->setFont('Helvetica', size: 10, style: FontStyle::BOLD);
$tag->endTag();

// 表頭列
$tag->beginTag('TR');
$headers = ['季度', '營收', '成長率', '利潤率'];
foreach ($headers as $header) {
    $tag->beginTag('TH', attributes: ['scope' => 'col']);
    $page->addText($header)
        ->setFont('Helvetica', size: 10, style: FontStyle::BOLD);
    $tag->endTag();
}
$tag->endTag(); // TR

// 資料列
$rows = [
    ['第一季', '5,480', '+12%', '21%'],
    ['第二季', '5,920', '+14%', '22%'],
    ['第三季', '6,180', '+16%', '23%'],
    ['第四季', '6,420', '+18%', '22%'],
];

foreach ($rows as $row) {
    $tag->beginTag('TR');
    foreach ($row as $i => $cell) {
        if ($i === 0) {
            $tag->beginTag('TH', attributes: ['scope' => 'row']);
        } else {
            $tag->beginTag('TD');
        }
        $page->addText($cell)->setFont('Times', size: 10);
        $tag->endTag();
    }
    $tag->endTag(); // TR
}

$tag->endTag(); // Table

Artifact 標記

頁首、頁尾、頁碼、浮水印等不屬於文件邏輯內容的元素,應標記為 Artifact:

php
use YeeeFang\TcpdfNext\Content\Alignment;

$pdf->onPageFooter(function (Page $page, int $pageNumber, int $totalPages) use ($tag) {
    $tag->beginArtifact('Pagination');
    $page->addText("第 {$pageNumber} 頁,共 {$totalPages} 頁")
        ->setPosition(105, 285)
        ->setFont('Helvetica', size: 8)
        ->setAlignment(Alignment::CENTER);
    $tag->endArtifact();
});

使用 HTML 自動產生標記

TCPDF-Next 的 HTML 渲染器可以從語義化 HTML 自動產生對應的 PDF 結構標記,大幅簡化無障礙文件的建立流程:

php
use YeeeFang\TcpdfNext\Html\HtmlRenderer;

$pdf = PdfDocument::create()
    ->setTagged(true)
    ->setLanguage('zh-TW')
    ->build();

$renderer = new HtmlRenderer($pdf);
$renderer->setAutoTagging(true);

$html = <<<'HTML'
<h1>年度報告 2026</h1>
<h2>執行摘要</h2>
<p>公司在 2026 年交出亮眼成績,營收較去年成長 15%。</p>

<figure>
    <img src="/assets/chart.png" alt="營收成長折線圖,顯示每季穩定攀升" width="200" />
    <figcaption>圖一:2022-2026 年營收趨勢</figcaption>
</figure>

<h2>財務數據</h2>
<table>
    <caption>季度營收</caption>
    <thead>
        <tr>
            <th scope="col">季度</th>
            <th scope="col">營收(萬元)</th>
        </tr>
    </thead>
    <tbody>
        <tr><td>第一季</td><td>5,480</td></tr>
        <tr><td>第二季</td><td>5,920</td></tr>
        <tr><td>第三季</td><td>6,180</td></tr>
        <tr><td>第四季</td><td>6,420</td></tr>
    </tbody>
</table>

<ul>
    <li>客戶滿意度:92%</li>
    <li>員工留任率:88%</li>
</ul>
HTML;

$renderer->writeHtml($html);

自動標記器會將 HTML 元素對應到 PDF 結構類型:

HTML 元素PDF 結構類型
<h1> - <h6>H1 - H6
<p>P
<table>Table
<th>TH
<td>TD
<ul>, <ol>L
<li>LI
<figure>Figure
<figcaption>Caption
<img> (含 alt)Figure + Alt Text
<a>Link
<blockquote>BlockQuote

內建無障礙檢查器

在輸出前使用內建檢查器驗證無障礙合規性:

php
use YeeeFang\TcpdfNext\Accessibility\AccessibilityChecker;

$checker = new AccessibilityChecker($pdf);
$result = $checker->validate();

if (!$result->isAccessible()) {
    foreach ($result->getIssues() as $issue) {
        echo sprintf(
            "[%s] %s -- %s (WCAG %s)\n",
            $issue->getSeverity()->name,
            $issue->getElement(),
            $issue->getMessage(),
            $issue->getWcagCriterion()
        );
    }
}

// 輸出範例:
// [ERROR] 第 3 頁圖片 -- 缺少替代文字 (WCAG 1.1.1)
// [WARNING] 第 5 頁表格 -- 缺少表頭標記 (WCAG 1.3.1)

外部驗證工具

使用 PAC (PDF Accessibility Checker) 進行完整的 PDF/UA 驗證。PAC 是免費的 Windows 應用程式,會根據 ISO 14289 標準執行 107 項檢查。

無障礙檢查清單

在發布文件前,請確認以下項目:

  • [ ] 設定了文件標題(setTitle()
  • [ ] 啟用標題列顯示文件標題(setDisplayDocTitle(true)
  • [ ] 設定了文件語言(setLanguage('zh-TW')
  • [ ] 所有內容都有結構標記
  • [ ] 標題層級依序使用,沒有跳級
  • [ ] 所有資訊性圖片都有替代文字
  • [ ] 裝飾性元素標記為 Artifact
  • [ ] 表格有正確的表頭(TH)與 scope 屬性
  • [ ] 閱讀順序符合邏輯
  • [ ] 連結文字具有描述性
  • [ ] 文字對比度至少 4.5:1(一般文字)或 3:1(大型文字)
  • [ ] 字型包含 Unicode 對應表
  • [ ] 超過 5 頁的文件有書籤導覽

延伸閱讀

以 LGPL-3.0-or-later 授權釋出。