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]), // 或選擇特定條件
);
相關資源¶
- 串流排版引擎 — 生成無障礙文件的最佳實踐
- 進階表單 — 確保表單無障礙
- 案例研究:政府表單數位化
- WcagChecker API 參考
- W3C WCAG 2.2
- PDF Association PDF/UA Technical Implementation Guide