跳轉到

WCAG / PDF-UA 無障礙合規檢查器

無障礙(Accessibility)不再是選項,而是法律要求。歐盟《歐洲無障礙法》(EAA,2025 年 6 月生效)、美國 Section 508、台灣《身心障礙者數位落差改善行動計畫》均要求公共機關及特定企業提供無障礙數位文件。

NextPDF Pro 的 WcagChecker 在文件生成流程中自動驗證合規性,在問題到達使用者之前即發現並修正。


支援的合規標準

標準 版本 說明
WCAG 2.2(2023) W3C Web Content Accessibility Guidelines
PDF/UA-1 ISO 14289-1:2014 PDF Universal Accessibility(基於 WCAG 2.0)
PDF/UA-2 ISO 14289-2:2024 基於 WCAG 2.1,與 PDF 2.0 對齊
PDFUA Matterhorn 1.1 31 個 Matterhorn Protocol 檢查項目

快速開始

use NextPDF\Pro\Accessibility\WcagChecker;
use NextPDF\Pro\Accessibility\ComplianceTarget;
use NextPDF\Pro\Accessibility\AccessibilityReport;

$pdf = file_get_contents('/documents/annual-report.pdf');

$checker = new WcagChecker(
    target: ComplianceTarget::PdfUa1,  // PdfUa1 | PdfUa2 | Wcag22AA | Wcag22AAA
);

/** @var AccessibilityReport $report */
$report = $checker->check($pdf);

if ($report->isCompliant()) {
    echo 'Document is PDF/UA-1 compliant.';
} else {
    echo 'Compliance failures: ' . $report->getErrorCount();
    echo 'Warnings: ' . $report->getWarningCount();

    foreach ($report->getErrors() as $error) {
        printf(
            "[%s] Page %d: %s (Rule: %s)\n",
            $error->getSeverity()->value,   // 'error' | 'warning' | 'info'
            $error->getPageNumber(),
            $error->getMessage(),
            $error->getRuleId(),            // 如 'PDF/UA-1 §7.1'
        );
    }
}

完整檢查規則集

結構合規(Tag 結構)

use NextPDF\Pro\Accessibility\WcagChecker;
use NextPDF\Pro\Accessibility\CheckerOptions;

$checker = new WcagChecker(
    target: ComplianceTarget::PdfUa1,
    options: CheckerOptions::create()
        ->checkDocumentStructure(true)       // 標籤樹完整性
        ->checkReadingOrder(true)            // 閱讀順序與視覺順序一致性
        ->checkLanguage(true)                // 文件語言設定
        ->checkHeadingHierarchy(true)        // 標題層級連貫性(H1→H2→H3)
        ->checkListStructure(true)           // 清單 LI/Lbl/LBody 結構
        ->checkTableStructure(true)          // 表格 TH/TD/scope 屬性
        ->checkArtifacts(true)               // 裝飾性元素的 Artifact 標記
);

影像與媒體

$options = CheckerOptions::create()
    ->checkAltText(true)               // 所有 Figure 元素必須有 Alt 文字
    ->checkAltTextQuality(true)        // 偵測空白或佔位 Alt 文字(如 "image")
    ->checkComplexImages(true)         // 複雜圖表需有詳細描述(LongDesc)
    ->checkDecorativeImages(true)      // 裝飾性圖片應標記為 Artifact
    ->checkEmbeddedMedia(true);        // 影片/音頻需有字幕或轉錄

文字與字型

$options = CheckerOptions::create()
    ->checkColorContrast(true)         // WCAG 2.2 SC 1.4.3:文字對比度 ≥ 4.5:1
    ->checkLargeTextContrast(true)     // 大型文字 ≥ 3:1
    ->checkFontEncoding(true)          // 字型須有 ToUnicode CMap(確保複製/搜尋)
    ->checkSymbolFonts(true)           // 符號字型需要等效 Unicode 映射
    ->checkTextAsGlyph(true);          // 偵測以圖形呈現的文字

表單無障礙

$options = CheckerOptions::create()
    ->checkFormFieldLabels(true)       // 所有表單欄位需有對應標籤
    ->checkFormFieldTooltips(true)     // 建議:欄位提示文字
    ->checkFormTabOrder(true)          // Tab 鍵順序與視覺順序一致
    ->checkRequiredFieldIndicators(true); // 必填欄位需有文字說明(不僅顏色)

整合至生成流程

最佳實踐是將合規檢查整合進文件生成管線,而非事後稽核:

use NextPDF\Pro\Document\ProDocument;
use NextPDF\Pro\Accessibility\WcagChecker;
use NextPDF\Pro\Accessibility\ComplianceTarget;
use NextPDF\Pro\Accessibility\ComplianceException;

final class AccessibleDocumentFactory
{
    public function __construct(
        private readonly WcagChecker $checker,
    ) {}

    /**
     * @throws ComplianceException if the document fails PDF/UA-1 checks
     */
    public function createCompliant(callable $buildFn): string
    {
        $doc = ProDocument::createStandalone();

        // 設定文件語言(PDF/UA 必要條件)
        $doc->setLanguage('zh-TW');
        $doc->setTitle('文件標題');
        $doc->setSubject('文件主題');

        // 執行建立函式
        $buildFn($doc);

        $pdfBytes = $doc->render();

        // 驗證合規性
        $report = $this->checker->check($pdfBytes);

        if (!$report->isCompliant()) {
            throw ComplianceException::fromReport(
                $report,
                message: 'Document failed PDF/UA-1 compliance check',
            );
        }

        return $pdfBytes;
    }
}

合規報告格式

JSON 格式

$json = $report->toJson(pretty: true);
// {
//   "target": "PDF/UA-1",
//   "is_compliant": false,
//   "error_count": 3,
//   "warning_count": 8,
//   "checked_at": "2026-03-04T10:23:45+08:00",
//   "issues": [
//     {
//       "rule_id": "PDF/UA-1 §7.1",
//       "severity": "error",
//       "page": 3,
//       "message": "Figure element missing required Alt attribute",
//       "element_path": "/Document/Sect[2]/Figure[1]",
//       "wcag_criterion": "1.1.1 Non-text Content"
//     }
//   ]
// }

HTML 報告

$html = $report->toHtml(
    includePassedChecks: false,
    groupByRule: true,
    includeRemediation: true, // 附帶修正建議
);

file_put_contents('/reports/accessibility-audit.html', $html);

PDF 報告

// 生成可列印的 PDF 合規報告
$reportPdf = $report->toPdfReport(
    includeSummary: true,
    includeDetailedIssues: true,
    includePassedChecks: false,
    includeScreenshots: true, // 問題頁面截圖
);

file_put_contents('/reports/accessibility-report.pdf', $reportPdf);

常見問題與修正建議

缺少替代文字(WCAG 1.1.1)

// 問題:圖片沒有 Alt 文字
$doc->image('/charts/revenue.png', x: 72, y: 200, width: 400);

// 修正:加入 Alt 文字
$doc->image('/charts/revenue.png', x: 72, y: 200, width: 400,
    alt: 'Bar chart showing quarterly revenue growth from NT$12.5M in Q1 to NT$16.2M in Q4 2025'
);

色彩對比度不足(WCAG 1.4.3)

// 問題:淺灰色文字在白色背景上(對比度 2.4:1,不達標)
$doc->text('次要說明文字', x: 72, y: 300, color: '#9CA3AF');

// 修正:使用足夠對比度的顏色(≥ 4.5:1)
$doc->text('次要說明文字', x: 72, y: 300, color: '#6B7280'); // 對比度 4.6:1

標題層級跳過(PDF/UA §7.1)

// 問題:H1 → H3(跳過 H2)
$doc->heading('文件標題', level: 1);
$doc->heading('子章節', level: 3); // 不允許

// 修正:層級連貫
$doc->heading('文件標題', level: 1);
$doc->heading('章節', level: 2);
$doc->heading('子章節', level: 3); // 正確

對比度計算工具

use NextPDF\Pro\Accessibility\Color\ContrastCalculator;
use NextPDF\Pro\Accessibility\Color\RgbColor;

$calculator = new ContrastCalculator();

$ratio = $calculator->getContrastRatio(
    foreground: RgbColor::fromHex('#374151'),
    background: RgbColor::fromHex('#FFFFFF'),
);

printf("Contrast ratio: %.2f:1\n", $ratio); // 10.85:1

echo 'AA Normal: ' . ($ratio >= 4.5 ? 'Pass' : 'Fail') . "\n";
echo 'AA Large:  ' . ($ratio >= 3.0 ? 'Pass' : 'Fail') . "\n";
echo 'AAA Normal:' . ($ratio >= 7.0 ? 'Pass' : 'Fail') . "\n";

Matterhorn Protocol 合規

Matterhorn Protocol 是 PDF Association 基於 PDF/UA 的 136 個可測試條件,Pro 實作所有自動可驗證的項目:

$checker = new WcagChecker(
    target: ComplianceTarget::PdfUa1,
    options: CheckerOptions::create()
        ->enableMatterhornProtocol(true)   // 啟用完整 Matterhorn 1.1 檢查集
        ->matterhornCheckSet([1, 6, 7, 9, 13, 28, 30, 31]), // 或選擇特定條件
);

相關資源