Skip to content

PDF accesible

Crea PDFs accesibles que funcionen con lectores de pantalla y tecnologías de asistencia usando estructura etiquetada, texto alternativo y etiquetado de idioma.

¿Qué hace accesible a un PDF?

RequisitoPor qué importa
Tags de estructuraLos lectores de pantalla usan tags de encabezado/párrafo/lista para navegar
Texto alternativoDescribe imágenes a usuarios que no pueden verlas
Tag de idiomaIndica al lector cómo pronunciar el texto
Orden de lecturaOrden lógico independiente del layout visual
Encabezados de tablaAsocia celdas de datos con su contexto de columna/fila
MarcadoresNavegación por teclado para documentos largos

Estándares

EstándarAlcance
PDF/UA-2 (ISO 14289-2)Accesibilidad universal de PDF
WCAG 2.1Pautas de accesibilidad para contenido web
Section 508Accesibilidad federal de EE.UU.
EN 301 549Requisitos de accesibilidad de la UE

Ejemplo de código completo

php
<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use TcpdfNext\Document;
use TcpdfNext\Enums\Alignment;
use TcpdfNext\Accessibility\TagManager;

// ── 1. Habilitar tagged PDF ───────────────────────────────────────────────
$pdf = Document::create()
    ->setTitle('Accessibility Report 2026')
    ->setAuthor('Acme Corp')
    ->setLanguage('en-US')
    ->setTagged(true)
    ->setDisplayDocTitle(true)
    ->addPage();

$tag = $pdf->getTagManager();

// ── 2. Encabezado (H1) ───────────────────────────────────────────────────
$tag->beginTag('H1');
$pdf->setFont('helvetica', style: 'B', size: 24)
    ->cell(0, 14, 'Accessibility Report 2026', newLine: true);
$tag->endTag();

// ── 3. Párrafo ──────────────────────────────────────────────────────────
$tag->beginTag('P');
$pdf->setFont('times', size: 12)
    ->multiCell(0, 7, 'Acme Corp is committed to producing documents that '
        . 'meet PDF/UA and WCAG 2.1 AA standards, ensuring equal access '
        . 'for all users regardless of ability.');
$tag->endTag();

// ── 4. Sub-encabezado (H2) ──────────────────────────────────────────────
$tag->beginTag('H2');
$pdf->setFont('helvetica', style: 'B', size: 18)
    ->cell(0, 12, 'Key Metrics', newLine: true);
$tag->endTag();

// ── 5. Lista etiquetada ────────────────────────────────────────────────
$items = [
    'Documents audited: 1,240',
    'Compliance rate: 98.7%',
    'Issues resolved: 412',
];

$tag->beginTag('L');
foreach ($items as $item) {
    $tag->beginTag('LI');

    $tag->beginTag('Lbl');
    $pdf->setFont('helvetica', size: 11)
        ->cell(8, 7, "\u{2022}");
    $tag->endTag(); // Lbl

    $tag->beginTag('LBody');
    $pdf->cell(0, 7, $item, newLine: true);
    $tag->endTag(); // LBody

    $tag->endTag(); // LI
}
$tag->endTag(); // L

// ── 6. Imagen con texto alternativo ────────────────────────────────────
$tag->beginTag('Figure');
$pdf->image(
    file:    __DIR__ . '/assets/compliance-chart.png',
    x:       null,
    y:       null,
    width:   120,
    height:  null,
    altText: 'Bar chart showing compliance rate rising from 91% in 2023 '
           . 'to 98.7% in 2026 across four consecutive years.',
);
$tag->beginTag('Caption');
$pdf->setFont('helvetica', style: 'I', size: 9)
    ->cell(0, 6, 'Figure 1: Compliance trend 2023-2026', newLine: true);
$tag->endTag(); // Caption
$tag->endTag(); // Figure

// ── 7. Elemento decorativo como artefacto (ignorado por lectores de pantalla) ─────
$tag->beginArtifact('Layout');
$pdf->setDrawColor(200, 200, 200)
    ->line(15, $pdf->getY(), 195, $pdf->getY());
$tag->endArtifact();

// ── 8. Tabla etiquetada ───────────────────────────────────────────────
$tag->beginTag('H2');
$pdf->setFont('helvetica', style: 'B', size: 18)
    ->cell(0, 12, 'Quarterly Results', newLine: true);
$tag->endTag();

$tag->beginTag('Table');

// Fila de encabezado
$tag->beginTag('TR');
foreach (['Quarter', 'Audited', 'Passed', 'Rate'] as $header) {
    $tag->beginTag('TH', attributes: ['scope' => 'col']);
    $pdf->setFont('helvetica', style: 'B', size: 10)
        ->cell(45, 8, $header, border: 1);
    $tag->endTag();
}
$tag->endTag(); // TR

// Filas de datos
$rows = [
    ['Q1', '310', '305', '98.4%'],
    ['Q2', '320', '316', '98.8%'],
    ['Q3', '305', '302', '99.0%'],
    ['Q4', '305', '301', '98.7%'],
];
foreach ($rows as $row) {
    $tag->beginTag('TR');
    foreach ($row as $i => $cell) {
        $tagName = $i === 0 ? 'TH' : 'TD';
        $attrs   = $i === 0 ? ['scope' => 'row'] : [];
        $tag->beginTag($tagName, attributes: $attrs);
        $pdf->setFont('times', size: 10)
            ->cell(45, 8, $cell, border: 1);
        $tag->endTag();
    }
    $tag->endTag(); // TR
}
$tag->endTag(); // Table

// ── 9. Etiquetado de idioma para texto extranjero ──────────────────────
$tag->beginTag('P', attributes: ['lang' => 'de-DE']);
$pdf->setFont('times', size: 11)
    ->multiCell(0, 7, 'Barrierefreiheit ist ein grundlegendes Recht.');
$tag->endTag();

// ── 10. Guardar ──────────────────────────────────────────────────────────
$pdf->save(__DIR__ . '/accessible-report.pdf');

echo 'Accessible PDF created.' . PHP_EOL;

Auto-etiquetado HTML

TCPDF-Next puede generar tags de estructura automáticamente desde HTML semántico:

php
$pdf = Document::create()
    ->setTagged(true)
    ->setLanguage('en-US')
    ->addPage();

$pdf->setAutoTagging(true)
    ->writeHtml(<<<'HTML'
        <h1>Report</h1>
        <p>Summary paragraph.</p>
        <img src="chart.png" alt="Revenue chart showing 15% growth" />
        <table>
            <tr><th>Q</th><th>Revenue</th></tr>
            <tr><td>Q1</td><td>$548M</td></tr>
        </table>
    HTML);
Elemento HTMLTag PDF
<h1>--<h6>H1--H6
<p>P
<img alt="...">Figure
<table>Table
<th>TH
<td>TD
<ul>, <ol>L
<li>LI
<a>Link

Checklist de accesibilidad

  • [ ] setTitle() -- título del documento establecido
  • [ ] setDisplayDocTitle(true) -- el visor muestra el título, no el nombre de archivo
  • [ ] setLanguage('en-US') -- idioma del documento declarado
  • [ ] Todo el contenido envuelto en tags de estructura
  • [ ] Encabezados en orden secuencial (H1, H2, H3 -- sin saltos)
  • [ ] Todas las imágenes significativas tienen altText
  • [ ] Las imágenes decorativas marcadas como artefactos
  • [ ] Las tablas tienen celdas TH con atributo scope
  • [ ] El orden de lectura coincide con el orden lógico
  • [ ] Ratio de contraste de color al menos 4.5:1

Validación

bash
# Usa PAC (PDF Accessibility Checker) para validación PDF/UA
# https://pdfua.foundation/en/pac-download/

Lectura adicional

Distribuido bajo la licencia LGPL-3.0-or-later.