Allgemeine Einordnung
Permalink "Allgemeine Einordnung"Bei jsPDF handelt es sich um eine freie JavaScript-Bibliothek zur Erzeugung von PDF-Dokumenten. Sie läuft sowohl in modernen Browsern als auch in Node.js und unterstützt die gängigen Modulformate (UMD, ES-Module, CommonJS). jsPDF wird von MrRio und der yWorks GmbH als Open-Source-Projekt gepflegt und kommt typischerweise dort zum Einsatz, wo PDF-Dokumente direkt im Client – also ohne serverseitigen Zwischenschritt – erzeugt werden sollen. Typische Anwendungsfälle sind dynamisch generierte Berichte, Formulare, Rechnungen oder Export-Funktionen in Web-Anwendungen.
Der hier beschriebene Entwicklungsstrang jsPDF-UA ist kein Bestandteil des offiziellen jsPDF-Projekts, sondern ein eigenständiger Fork auf Basis von jsPDF. Er ergänzt die Bibliothek um eine Implementierung des Standards PDF/UA-1 (ISO 14289-1). Damit lassen sich programmatisch Strukturbaum, Alternativtexte, ausgezeichnete Sprache, eingebettete Schriften, Artefakt-Markierungen sowie zahlreiche weitere Merkmale erzeugen, die für die Barrierefreiheit eines PDF-Dokuments erforderlich sind.
Solange der Pull Request mit den Änderungen des Forks nicht in das jsPDF-Kernprojekt integriert ist, müssen Anwenderinnen und Anwender, die PDF/UA-Erzeugung mit jsPDF nutzen möchten, direkt den Fork verwenden:
- Fork-Repository (jsPDF-UA): https://github.com/heikofolkerts/jsPDF-UA
- Upstream-Repository (jsPDF): https://github.com/parallax/jsPDF
Für jsPDF-UA ist die Installation direkt aus dem Fork-Repository erforderlich (z. B. per npm install github:heikofolkerts/jsPDF-UA).
Aktualisierungen des jsPDF-Kernprojekts werden kontinuierlich in den Entwicklungsstrang jsPDF-UA integriert.
Anwendungsfälle
Permalink "Anwendungsfälle"Der Einsatz von jsPDF-UA ist insbesondere dann empfehlenswert, wenn
- PDF-Dokumente programmatisch und reproduzierbar aus strukturierten Daten (z. B. JSON, Datenbank-Auszügen oder XML) erzeugt werden sollen,
- die Erzeugung direkt im Browser erfolgen soll, ohne dass personenbezogene Daten den Client verlassen müssen, oder
- eine bestehende jsPDF-Codebasis um Barrierefreiheit erweitert werden soll.
Im Unterschied zu XSL-FO-basierten Werkzeugen wie Apache-FOP wird die Dokumentstruktur bei jsPDF-UA nicht deklarativ aus einer Markup-Datei abgeleitet, sondern programmatisch mittels API-Aufrufen erzeugt. Das bedeutet: Sie bestimmen explizit, welches Strukturelement gerade geöffnet ist und welcher Textaufruf dazugehört. Dies erfordert Sorgfalt, bietet aber zugleich maximale Kontrolle über den Strukturbaum.
Eine vollständige Referenz der API finden Sie in der Projektdokumentation des Forks unter docs/pdfua/.
Ein vollständig ausgestattetes Beispieldokument steht mit showcase-pdfua-complete.js zur Verfügung und dient auch als Grundlage der folgenden Code-Auszüge.
Hinweise zur Erstellung von barrierefreien PDF-Dokumenten mit jsPDF-UA
Permalink "Hinweise zur Erstellung von barrierefreien PDF-Dokumenten mit jsPDF-UA"Dokumenttitel
Permalink "Dokumenttitel"Der Dokumenttitel ist in PDF/UA zwingend vorgeschrieben und wird im XMP-Metadaten-Strom sowie in der Titelleiste des PDF-Betrachters angezeigt. Die Methode setDocumentTitle schreibt den Titel zusammen mit den erforderlichen XMP-Kennungen für PDF/UA-1:
1doc.setDocumentTitle("PDF/UA Complete Feature Showcase - jsPDF Implementation");
Anmerkungen
Permalink "Anmerkungen"setDocumentTitle aktiviert implizit den Viewer-Eintrag DisplayDocTitle mit dem Wert „true“. Dadurch zeigt der PDF-Betrachter den vergebenen Titel statt des Dateinamens an.
Die alternativ ebenfalls verfügbare Methode setProperties({ title: "..." }) setzt lediglich den Info-Dictionary-Eintrag. Für einen PDF/UA-konformen Titel ist stets setDocumentTitle zu verwenden.
Sprache (global)
Permalink "Sprache (global)"Die primäre Dokumentsprache wird über die Methode setLanguage auf dem „Catalog“ gesetzt und zusätzlich in die XMP-Metadaten übernommen. Erwartet wird ein BCP-47-Sprachcode:
1doc.setLanguage("en-US"); // alternativ z. B. "de-DE" oder "de-AT"
Anmerkungen
Permalink "Anmerkungen"jsPDF-UA schreibt den Sprachcode zusätzlich in jeden Marked-Content-Operator (/Lang-Eintrag innerhalb der BDC-Property-List). Dies ist notwendig, damit sowohl Adobe Acrobat Reader als auch Screenreader wie NVDA die Sprachauszeichnung zuverlässig auswerten. Firefox ist an dieser Stelle toleranter, deckt aber nicht alle Hilfsmittel ab.
Sprache (einzelne Teilbereiche)
Permalink "Sprache (einzelne Teilbereiche)"Für Passagen in abweichender Sprache innerhalb eines Absatzes steht ein Span-Element mit eigenem lang-Attribut zur Verfügung (siehe auch unten unter Span-Tag).
Alternativtexte
Permalink "Alternativtexte"Alternativtexte werden in jsPDF-UA über das alt-Attribut der jeweiligen Strukturelement-Methoden übergeben. Zwingend erforderlich sind sie insbesondere für Figure-, Formula- und Annot-Elemente:
1doc.beginFigure({
2 alt:
3 "A bar chart showing quarterly sales data with Q1 at 25%, " +
4 "Q2 at 30%, Q3 at 20%, and Q4 at 25%",
5 bbox: [20, 640, 90, 70]
6});
7doc.addImage(imageData, "PNG", 20, 120, 90, 60);
8doc.beginCaption();
9doc.text("Figure 1: Quarterly Sales Distribution", 20, 188);
10doc.endCaption();
11doc.endFigure();
Anmerkungen
Permalink "Anmerkungen"Alternativtexte dürfen weder aus dem reinen Dateinamen einer Grafik noch aus generischen Platzhaltern („Bild 1“) bestehen. Bei Diagrammen sollten die wesentlichen Aussagen textlich beschrieben werden.
Das bbox-Attribut (Bounding Box) in PDF-Koordinaten ist für das Figure-Element optional, wird vom Prüftool PAC jedoch empfohlen, da es die Grafik in alternativen Darstellungsformen verortbar macht.
Für rein dekorative Grafiken soll kein Figure-Element verwendet werden – dafür ist die Kennzeichnung als Artefakt vorgesehen (siehe auch unten unter Kopf- und Fußzeilen). Vergleiche dazu auch den Abschnitt Hinweise zur Erstellung von Alternativtexten.
Der Alternativtext für Links wird über die Methode doc.textWithLink übergeben (siehe auch unten unter Link-Tag).
Aktivierung des PDF/UA-Modus
Permalink "Aktivierung des PDF/UA-Modus"Der PDF/UA-Modus wird bereits beim Anlegen der Instanz aktiviert. Mit dieser einen Option werden intern zahlreiche Voreinstellungen vorgenommen, die für einen gültigen PDF/UA-Output zwingend erforderlich sind – insbesondere MarkInfo/Marked true, ViewerPreferences/DisplayDocTitle true sowie der Aufbau des Strukturbaums mit StructTreeRoot:
1const { jsPDF } = require("jspdf");
2const doc = new jsPDF({ pdfUA: true });
Anmerkungen
Permalink "Anmerkungen"Ohne die Option pdfUA: true werden keine Strukturbaum- und Marked-Content-Operatoren erzeugt; auch die automatische Einbettung der barrierearmen Schrift Atkinson Hyperlegible unterbleibt. Die Aktivierung des Modus sollte daher am Anfang stehen, noch bevor Inhalte hinzugefügt werden.
Dokumentstruktur
Permalink "Dokumentstruktur"Die Strukturelemente des PDF-Dokuments werden mit beginStructureElement geöffnet und mit endStructureElement geschlossen. Zwischen diesen Aufrufen werden die Textausgaben (doc.text(...)) automatisch mit passenden BDC/EMC-Operatoren und eindeutigen Marked-Content-IDs (MCIDs) versehen. Das wird in jsPDF-UA im Abschnitt Marked Content (Auto) als automatisches Tagging bezeichnet.
1doc.beginStructureElement("Document");
2
3doc.beginStructureElement("H1");
4doc.setFontSize(22);
5doc.text("PDF/UA Complete Feature Showcase", 20, 25);
6doc.endStructureElement();
7
8doc.beginStructureElement("P");
9doc.setFontSize(11);
10doc.text(
11 "This document demonstrates all PDF/UA accessibility features " +
12 "implemented in jsPDF.",
13 20,
14 52
15);
16doc.endStructureElement();
17
18doc.endStructureElement(); // Document
Anmerkungen
Permalink "Anmerkungen"Die oberste Ebene des Strukturbaums wird stets mit „Document“ geöffnet. Erst dann folgen Überschriften (H1 bis H6), Absätze (P) und alle weiteren Tags.
beginStructureElement und endStructureElement müssen paarweise geschachtelt sein. Wird ein Element nicht geschlossen, entsteht ein defekter Strukturbaum, der von Prüftools beanstandet wird.
Die Textposition (x, y) hat keinen Einfluss auf die logische Lesereihenfolge. Maßgeblich für Screenreader ist die Reihenfolge der Aufrufe – sie sollte der gewünschten Lesereihenfolge entsprechen, unabhängig vom visuellen Layout.
Lesezeichen
Permalink "Lesezeichen"Lesezeichen (Outlines) werden über die „outline“-API erzeugt. Sie sind für die Navigation in Screenreadern, aber auch für Menschen mit Sehvermögen wichtig:
1doc.outline.add(null, "1. Text Elements", { pageNumber: 1 });
2const listsBookmark = doc.outline.add(null, "2. Lists", { pageNumber: 2 });
3doc.outline.add(listsBookmark, "2.1 Unordered List", { pageNumber: 2 });
4doc.outline.add(listsBookmark, "2.2 Ordered List", { pageNumber: 2 });
Anmerkungen
Permalink "Anmerkungen"Der erste Parameter ist das Eltern-Lesezeichen oder „null“ für eine oberste Ebene. Lesezeichen und Überschriften des Strukturbaums sollten dieselbe Hierarchie abbilden. Andernfalls wirken sie für Personen, die einen Screenreader nutzen, inkonsistent.
Inhaltsverzeichnis
Permalink "Inhaltsverzeichnis"Für ein semantisch korrektes, maschinenlesbares Inhaltsverzeichnis stellt jsPDF-UA die Methoden beginTOC, addTOCEntry und endTOC bereit. Intern entstehen dabei die Strukturelemente TOC und TOCI (Table Of Contents Item), jeweils mit Sprung-Link auf die Zielseite:
1doc.beginTOC();
2const tocItems = [
3 { title: "1. Text Elements", page: 1, level: 1 },
4 { title: "2. Lists", page: 2, level: 1 },
5 { title: "2.1 Unordered List", page: 2, level: 2 }
6 // ...
7];
8let tocY = 88;
9tocItems.forEach(item => {
10 doc.addTOCEntry({
11 title: item.title,
12 page: item.page,
13 y: tocY,
14 level: item.level,
15 indent: 25,
16 subIndent: 5,
17 rightMargin: 190
18 });
19 tocY += 5;
20});
21doc.endTOC();
Kopf- und Fußzeilen
Permalink "Kopf- und Fußzeilen"Kopf- und Fußzeilen sowie rein dekorative Elemente dürfen nicht im Strukturbaum erscheinen. jsPDF-UA stellt für solche Inhalte das Methodenpaar beginArtifact/endArtifact bereit:
1doc.beginArtifact({ type: "Pagination", subtype: "Header" });
2doc.setFontSize(8);
3doc.setTextColor(89, 89, 89);
4doc.text("PDF/UA Complete Showcase", 20, 10);
5doc.text("Page 1", 180, 10);
6doc.setTextColor(0, 0, 0);
7doc.endArtifact();
Anmerkungen
Permalink "Anmerkungen"type kann die Werte „Pagination“ (Kopf-/Fußzeilen), „Layout“ (Trennlinien, Hintergründe) oder „Page“ (Seitenzahlen, Hintergrund-Bilder) annehmen. „Pagination“ nutzt zusätzlich subtype: "Header" oder subtype: "Footer".
Artefakte sind auch dann zu setzen, wenn das betreffende Element scheinbar „Text“ enthält. Andernfalls wird der Screenreader den Inhalt doppelt vorlesen (einmal pro Seite) und der Strukturbaum enthält semantisch irrelevante Zweige.
Erzeugung von PDF-Dokumenten mit jsPDF-UA
Permalink "Erzeugung von PDF-Dokumenten mit jsPDF-UA"Die Erzeugung des eigentlichen PDF-Dokuments erfolgt wahlweise im Browser oder in einer Node.js-Umgebung. Im Browser wird typischerweise doc.save("out.pdf") aufgerufen, das über den FileSaver einen Download auslöst. Unter Node.js wird das PDF als ArrayBuffer ausgegeben und mit fs.writeFileSync gespeichert:
1const fs = require("fs");
2const arrayBuffer = doc.output("arraybuffer");
3fs.writeFileSync("out.pdf", Buffer.from(arrayBuffer));
Anmerkungen
Permalink "Anmerkungen"Der Node-Build von jsPDF bindet keinen FileSaver ein; doc.save ist dort nicht verfügbar.
Die Node-basierte Erzeugung eignet sich insbesondere für CI/CD-Pipelines, in denen PDF-Dokumente gemeinsam mit veraPDF automatisiert geprüft werden sollen.
Prüfung der Barrierefreiheit
Permalink "Prüfung der Barrierefreiheit"Für die Prüfung der Barrierefreiheit haben sich in jsPDF-UA die folgenden zwei Werkzeuge bewährt:
- PDF Accessibility Checker (PAC) prüft stärker auf semantische Korrektheit und ist besonders streng bei Platzierungs-Attributen (
/Placement) und der korrekten Verwendung von Inline- vs. Block-Elementen. - veraPDF liefert die technische Prüfung gegen ISO 14289-1 und ist automatisierbar.
Der Aufruf von veraPDF über Docker:
1docker run --rm -v "$(pwd)/examples/temp:/data" verapdf/cli \ --flavour ua1 /data/pdfua-complete-showcase.pdf
Ergänzend empfiehlt sich der Test mit Adobe Acrobat Reader in Kombination mit einem Screenreader (NVDA unter Windows, VoiceOver unter macOS). Firefox ist für Screenreader-Tests ungeeignet, da sein PDF-Renderer Strukturfehler häufig verdeckt. Vergleiche dazu auch den Abschnitt Hinweise zu Tools zur Überprüfung der Barrierefreiheit.
Anmerkungen
Permalink "Anmerkungen"Das Beispieldokument des Projekts (showcase-pdfua-complete.js) besteht die veraPDF-Prüfung mit dem Flavour „ua1“ ohne Befund. In PAC sind für einzelne Strukturelemente die Platzierungs-Attribute zu beachten, die jsPDF-UA über die jeweiligen begin*-Methoden als Parameter entgegennimmt (siehe auch unten unter Platzierungs-Attribute).
Schriften und Font-Embedding
Permalink "Schriften und Font-Embedding"PDF/UA verlangt, dass alle verwendeten Schriften vollständig im Dokument eingebettet sind. Bei aktivem PDF/UA-Modus bindet jsPDF-UA die Schriftfamilie Atkinson Hyperlegible (Regular, Bold, Italic und BoldItalic) automatisch ein und verwendet sie als Standardschrift. Diese Schrift ist gezielt für Menschen mit Sehbeeinträchtigung entworfen worden und deckt den lateinischen Zeichenvorrat inklusive deutscher Umlaute ab.
Sollen eigene TrueType-Schriften verwendet werden, lassen sich diese manuell einbetten:
1doc.addFileToVFS("MyFont.ttf", base64EncodedFont);
2doc.addFont("MyFont.ttf", "MyFont", "normal");
3doc.setFont("MyFont");
Anmerkungen
Permalink "Anmerkungen"jsPDF-UA blendet die 14 PDF-Standardschriften (Helvetica, Times usw.) im aktiven PDF/UA-Modus aus und ersetzt Aufrufe wie setFont("Helvetica") durch die Atkinson-Variante.
Spezialfälle
Permalink "Spezialfälle"Automatisches Tagging vs. manueller Eingriff
Permalink "Automatisches Tagging vs. manueller Eingriff"Solange Textausgaben (doc.text(...)) innerhalb eines geöffneten Strukturelements erfolgen, werden Marked-Content-IDs und BDC/EMC-Operatoren vollautomatisch erzeugt. Ein manuelles Setzen von MCIDs ist nicht erforderlich und auch nicht vorgesehen.
Soll ein Text ausdrücklich kein Strukturelement erhalten (z. B. weil er dekorativ ist), ist die Ausgabe in das Methodenpaar beginArtifact/endArtifact zu klammern.
Compat- vs. Advanced-API
Permalink "Compat- vs. Advanced-API"jsPDF kennt zwei Betriebsmodi: den kompatiblen („compat“) und den erweiterten („advanced“). Der Advanced-Modus stellt u. a. Transformationsmatrizen, Muster (Patterns) und Form-Objects zur Verfügung. Für die Erzeugung von PDF/UA-Inhalten genügt der Standardmodus „compat“. Wird „advanced“ benötigt, sollten strukturrelevante Aufrufe gezielt in doc.compatAPI(...)-Blöcken erfolgen, damit die Marked-Content-Logik erwartungsgemäß greift.
Platzierungs-Attribute
Permalink "Platzierungs-Attribute"Das Prüftool PAC verlangt für bestimmte Elemente die explizite Angabe des Platzierungs-Attributs /Placement /Block, sobald sie als Block-Element – also nicht innerhalb eines P-Elements – verwendet werden. Die jsPDF-UA-API setzt dafür sinnvolle Voreinstellungen:
| Element | Voreinstellung | Bemerkung |
|---|---|---|
Figure | Block | Standardwert für Grafiken |
Note | Block | Voreinstellung bei addFootnote |
BibEntry | Block | Voreinstellung bei beginBibEntry |
Annot | Block | Voreinstellung bei beginAnnot |
Form | Block | Voreinstellung für Formularfelder |
Code | inline | Block-Platzierung bei Bedarf explizit angeben |
Link | inline | Block-Platzierung bei allein stehenden Links explizit |
Einzelne Strukturelemente
Permalink "Einzelne Strukturelemente"Überschriften und Abschnitte
Permalink "Überschriften und Abschnitte"jsPDF-UA unterstützt die Überschriftenebenen H1 bis H6. Zusätzlich existieren gruppierende Elemente wie Sect, Art, Div und Part, mit denen semantische Abschnitte gekennzeichnet werden:
1doc.beginSect();
2
3doc.beginStructureElement("H2");
4doc.setFontSize(14);
5doc.setFont(undefined, "bold");
6doc.text("1. Text Elements", 20, 200);
7doc.endStructureElement();
8
9doc.beginStructureElement("P");
10doc.setFontSize(11);
11doc.setFont(undefined, "normal");
12doc.text("This section demonstrates various text formatting options:", 20, 213);
13doc.endStructureElement();
14
15doc.endSect();
Anmerkungen
Permalink "Anmerkungen"Überschriftenebenen sind streng hierarchisch anzuwenden: Eine Ebene darf nicht übersprungen werden.
beginSect und beginArt eignen sich zum logischen Gruppieren. Art ist semantisch für eigenständige, publizierbare Abschnitte gedacht (z. B. Zeitschriftenartikel), Sect für beliebige Abschnitte wie Kapitel oder nummerierte Bereiche.
Listen
Permalink "Listen"Listen werden aus den Elementen L (Liste), LI (Listenpunkt), Lbl (Aufzählungszeichen bzw. Nummerierung) und LBody (eigentlicher Inhalt) aufgebaut:
1doc.beginStructureElement("L");
2const items = ["First item", "Second item", "Third item"];
3let y = 50;
4items.forEach(item => {
5 doc.beginStructureElement("LI");
6 doc.beginStructureElement("Lbl");
7 doc.text("•", 25, y);
8 doc.endStructureElement();
9 doc.beginStructureElement("LBody");
10 doc.text(item, 32, y);
11 doc.endStructureElement();
12 doc.endStructureElement();
13 y += 10;
14});
15doc.endStructureElement();
Anmerkungen
Permalink "Anmerkungen"Bei nummerierten Listen wird in Lbl die Nummerierung ausgegeben (z. B. „1.“, „2.“), in LBody der Text.
Tabellen
Permalink "Tabellen"Tabellen werden mit Table, THead, TBody, TR, TH und TD aufgebaut. Für jede Kopfzelle muss ein scope-Attribut gesetzt werden, damit die Zuordnung zu Spalten- bzw. Zeilen-Daten für Screenreader erkennbar ist:
1doc.beginStructureElement("Table");
2
3doc.beginTableHead();
4doc.beginStructureElement("TR");
5doc.beginStructureElement("TH", { scope: "Column" });
6doc.setFont(undefined, "bold");
7doc.text("Product", 25, 175);
8doc.endStructureElement();
9doc.beginStructureElement("TH", { scope: "Column" });
10doc.text("Price", 80, 175);
11doc.endStructureElement();
12// weitere Spaltenköpfe …
13doc.endStructureElement();
14doc.endTableHead();
15
16doc.beginTableBody();
17doc.beginStructureElement("TR");
18doc.beginStructureElement("TH", { scope: "Row" });
19doc.setFont(undefined, "bold");
20doc.text("Widget A", 25, 188);
21doc.endStructureElement();
22doc.setFont(undefined, "normal");
23doc.beginStructureElement("TD");
24doc.text("$10.00", 80, 188);
25doc.endStructureElement();
26// weitere Datenzellen …
27doc.endStructureElement();
28doc.endTableBody();
29
30doc.endStructureElement(); // Table
Anmerkungen
Permalink "Anmerkungen"scope kennt die Werte „Column“, „Row“ und „Both“.
Bei Tabellen mit gleichzeitigem Zeilen- und Spaltenkopf (z. B. Pivot-Tabellen) ist „Both“ zu verwenden.
Die erste Spalte eines Datensatzes kann bei Bedarf als TH mit scope: "Row" ausgezeichnet werden, um Bezeichnungen wie Produktnamen oder Kalenderwochen als Zeilenkopf zu markieren (so im Beispiel oben).
Tabellen-Trennlinien werden in jsPDF-UA derzeit nicht automatisch als Artefakt gekennzeichnet. Falls Sie dekorative Linien zeichnen, klammern Sie diese im Methodenpaar beginArtifact({ type: "Layout" })/endArtifact() ein, damit sie nicht im Strukturbaum auftauchen.
Link-Tag
Permalink "Link-Tag"Links werden im Strukturbaum mit dem Link-Element ausgezeichnet und technisch über die jsPDF-Methode textWithLink umgesetzt. Gemäß PDF/UA ist ein Link inline innerhalb eines P-Elements zu platzieren:
1doc.beginStructureElement("P");
2doc.setFontSize(11);
3doc.text("External link: ", 20, 253);
4doc.beginLink();
5doc.setTextColor(0, 0, 255);
6doc.textWithLink("jsPDF on GitHub", 52, 253, { url: "https://github.com/parallax/jsPDF" });
7doc.setTextColor(0, 0, 0);
8doc.endLink();
9doc.endStructureElement();
Anmerkungen
Permalink "Anmerkungen"Für einen alleinstehenden (block-artigen) Link – also außerhalb eines Fließtextabsatzes – erwartet das Prüftool PAC eine Platzierungs-Angabe „/Placement /Block“. Diese wird mit doc.beginLink({ placement: "Block" }) gesetzt.
Interne Links auf eine andere Seite werden über die gleiche Methode umgesetzt, mit { pageNumber: 6 } statt { url: ... }.
Strong- und Em-Tag
Permalink "Strong- und Em-Tag"Für semantisch gewichtete Hervorhebungen stellt jsPDF-UA die Methodenpaare beginStrong/endStrong sowie beginEmphasis/endEmphasis bereit. Sie setzen die PDF/UA-Elemente „Strong“ (wichtig) bzw. „Em“ (betont):
1doc.beginStructureElement("P");
2doc.text("Here is some ", 20, 226);
3doc.beginStrong();
4doc.setFont(undefined, "bold");
5doc.text("strongly emphasized", 51, 226);
6doc.endStrong();
7doc.setFont(undefined, "normal");
8doc.text(" text that is important.", 97, 226);
9doc.endStructureElement();
Anmerkungen
Permalink "Anmerkungen"„Strong“ und „Em“ bilden semantische Hervorhebungen ab und sollten der rein visuellen Auszeichnung (Fettdruck, Kursive ohne Bedeutung) vorgezogen werden, wann immer eine inhaltliche Betonung gemeint ist.
Abbreviation-Tag (Abkürzungen)
Permalink "Abbreviation-Tag (Abkürzungen)"Abkürzungen werden mit beginAbbreviation(expansion) ausgezeichnet. Die ausgeschriebene Form wird als Attribut E (Expansion) in die Strukturbaum-Eigenschaften übernommen:
1doc.beginStructureElement("P");
2doc.text("The ", 20, 250);
3doc.beginAbbreviation("World Wide Web");
4doc.text("WWW", 32, 250);
5doc.endAbbreviation();
6doc.text(" and ", 46, 250);
7doc.beginAbbreviation("Hypertext Markup Language");
8doc.text("HTML", 58, 250);
9doc.endAbbreviation();
10doc.text(" are fundamental web technologies.", 73, 250);
11doc.endStructureElement();
Umsetzung im Screenreader
Permalink "Umsetzung im Screenreader"NVDA liest anstelle der Kurzform die ausgeschriebene Variante, sofern im Screenreader die Abkürzungserkennung aktiviert ist. VoiceOver gibt die Abkürzung als Text aus und ergänzt bei Bedarf eine Beschreibung aus dem E-Attribut.
Span-Tag
Permalink "Span-Tag"Für Inline-Container (z. B. zur Auszeichnung abweichender Sprache) steht das Methodenpaar beginSpan/endSpan zur Verfügung:
1doc.beginStructureElement("P");
2doc.text("English text with ", 20, 262);
3doc.beginSpan({ lang: "de-DE" });
4doc.text("deutscher Text eingebettet", 61, 262);
5doc.endSpan();
6doc.text(" and back to English.", 130, 262);
7doc.endStructureElement();
Anmerkungen
Permalink "Anmerkungen"Der Sprachcode wird sowohl am Span-Strukturelement als auch in den zugehörigen BDC-Properties (/Lang) gesetzt. Ohne diese doppelte Auszeichnung wechseln Acrobat Reader und NVDA die Sprache nicht zuverlässig.
Quote- und BlockQuote-Tag
Permalink "Quote- und BlockQuote-Tag"Kurze, in den Fließtext eingebettete Zitate werden mit dem Methodenpaar beginQuote/endQuote ausgezeichnet, längere, eigenständige Zitate mit beginBlockQuote/endBlockQuote:
1// Inline-Zitat
2doc.beginStructureElement("P");
3doc.text("Shakespeare wrote: ", 20, 145);
4doc.beginQuote();
5doc.setFont(undefined, "italic");
6doc.text('"To be or not to be, that is the question."', 63, 145);
7doc.setFont(undefined, "normal");
8doc.endQuote();
9doc.endStructureElement();
10
11// Blockzitat
12doc.beginBlockQuote();
13doc.beginStructureElement("P");
14doc.setFont(undefined, "italic");
15doc.text('"The only way to do great work is to love what you do."', 30, 175);
16doc.setFont(undefined, "normal");
17doc.text("- Steve Jobs", 30, 195);
18doc.endStructureElement();
19doc.endBlockQuote();
Code-Tag
Permalink "Code-Tag"Für Quellcode steht das Methodenpaar beginCode/endCode bereit. Für inline eingefügten Code genügt die Standardform; für größere Code-Blöcke ist die Platzierung als Block-Element vorzugeben:
1// Inline-Code
2doc.beginStructureElement("P");
3doc.text("Inline code: ", 20, 228);
4doc.beginCode();
5doc.text("const x = 42;", 52, 228);
6doc.endCode();
7doc.endStructureElement();
8
9// Block-Code
10doc.beginCode({ placement: "Block" });
11doc.text("function greet(name) {", 25, 255);
12doc.text(" return `Hello, ${name}!`;", 25, 263);
13doc.text("}", 25, 271);
14doc.endCode();
Annotation-Tag
Permalink "Annotation-Tag"Kommentar-Annotationen (gelbe Klebezettel, Freitext) werden über ein Annot-Strukturelement eingebunden.
Die Annotation selbst wird mit createAnnotation erzeugt und über addAnnotationRef an die Struktur angebunden:
1doc.beginAnnot({ alt: "Reviewer comment about quarterly sales figure" });
2const annotId = doc.createAnnotation({
3 type: "text",
4 title: "Reviewer",
5 contents: "Comment: This figure shows quarterly sales distribution.",
6 bounds: { x: 90, y: 180, w: 20, h: 20 },
7 open: false
8});
9if (annotId) doc.addAnnotationRef(annotId);
10doc.endAnnot();
Anmerkungen
Permalink "Anmerkungen"Technisch hängt ein Annot-Strukturelement nicht am Contentstrom, sondern an der Seite. Screenreader greifen daher häufig erst nach den umgebenden Absätzen auf Annotations zu – unabhängig von deren Position im Strukturbaum.
Wenn eine bestimmte Lesereihenfolge erzwungen werden muss, kann statt einer Annot-Annotation ein Note-Element verwendt werden. Note ist eine echte Inline-Struktur mit eigenem Text, die vom Screenreader exakt an der im Strukturbaum festgelegten Stelle vorgelesen wird.
Darstellung in der Screenreader-Vorschau von PAC
Permalink "Darstellung in der Screenreader-Vorschau von PAC"In der Screenreader-Vorschau von PAC erscheint ein Annot-Element als Inline-Span innerhalb des umgebenden Absatzes. Angezeigt wird sowohl der sichtbare Text, als auch der Alternativtext.
Formula-Tag
Permalink "Formula-Tag"Mathematische Formeln werden als Formula-Element getaggt und benötigen einen Alternativtext:
1doc.beginStructureElement("P");
2doc.text("Famous equation: ", 20, 274);
3doc.beginFormula(
4 alt:
5 "E equals m times c squared, where E is energy, " +
6 "m is mass, and c is speed of light"
7);
8doc.text("E = mc²", 62, 274);
9doc.endFormula();
10doc.endStructureElement();
Umsetzung im Screenreader
Permalink "Umsetzung im Screenreader"VoiceOver erkennt ein Formula-Element als Grafik und liest den Alternativtext vor. NVDA gibt wahlweise den angezeigten Text oder den Alternativtext aus.
Darstellung in der Screenreader-Vorschau von PAC
Permalink "Darstellung in der Screenreader-Vorschau von PAC"In der Screenreader-Vorschau von PAC erscheint ein Formula-Element als (leeres) Form-Tag mit zugehörigem Alternativtext.
Note-Tag
Permalink "Note-Tag"Für Fußnoten stellt jsPDF-UA die Hilfsmethoden addFootnoteRef (Referenz im Fließtext) und addFootnote (Fußnoten-Eintrag) zur Verfügung. Im Strukturbaum entstehen daraus das Reference- und das Note-Element. Beide werden intern über eine id miteinander verknüpft und als Link mit sichtbarer Sprungmarke abgebildet:
1// Fließtext mit Fußnoten-Referenz
2doc.beginStructureElement("P");
3let fnX = 20;
4doc.text("PDF/UA (Universal Accessibility) is an ISO standard", fnX, 40);
5fnX += doc.getTextWidth("PDF/UA (Universal Accessibility) is an ISO standard");
6doc.addFootnoteRef("¹", fnX, 40, { noteId: "fn1" });
7doc.text(" that ensures", fnX + doc.getTextWidth("¹") * 0.7 + 1, 40);
8doc.text("PDFs can be read by assistive technologies.", 20, 50);
9doc.endStructureElement();
10
11// Fußnoten-Eintrag am Seitenfuß
12doc.setFontSize(9);
13doc.addFootnote({
14 id: "fn1",
15 label: "¹",
16 text: "ISO 14289-1:2014, Document management — Electronic document file format enhancement for accessibility",
17 x: 25,
18 y: 265,
19 labelX: 20
20});
Anmerkungen
Permalink "Anmerkungen"Für eine saubere Trennung zwischen Fließtext und Fußnotenblock empfiehlt sich eine dekorative Trennlinie. Diese ist als Artefakt zu markieren (beginArtifact({ type: "Layout" })).
addFootnote setzt intern placement: "Block", weil eine allein stehende Fußnote in PAC als Block-Element erwartet wird.
Wird eine Fußnote nicht mithilfe der Convenience-API, sondern über das Methodenpaar beginNote/endNote manuell erzeugt, muss die id explizit gesetzt werden – andernfalls fehlt die Verknüpfung zwischen Referenz und Fußnotentext.
Form-Tag (barrierefreie Formularfelder)
Permalink "Form-Tag (barrierefreie Formularfelder)"Interaktive Formularfelder werden nicht über die generischen beginStructureElement-Aufrufe erzeugt, sondern über spezialisierte Convenience-Methoden, die sowohl das AcroForm-Widget als auch das Form-Strukturelement anlegen:
1doc.addAccessibleTextField({
2 name: "name",
3 label: "Name:",
4 tooltip: "Enter your full name.",
5 x: 20,
6 y: 55,
7 width: 80,
8 height: 12,
9 required: true
10});
11
12doc.addAccessibleCheckBox({
13 name: "subscribe",
14 label: "Subscribe to newsletter.",
15 tooltip: "Check to receive our newsletter.",
16 x: 20,
17 y: 71,
18 width: 7,
19 height: 7
20});
21
22doc.addAccessibleComboBox({
23 name: "country",
24 label: "Country:",
25 tooltip: "Select your country from the list.",
26 x: 20,
27 y: 88,
28 width: 60,
29 height: 12,
30 options: ["USA", "Germany", "France", "UK", "Japan"]
31});
Anmerkungen
Permalink "Anmerkungen"Der sichtbare Label-Text (label) muss mit dem barrierefreien Namen übereinstimmen, damit Screenreader und visuelle Darstellung konsistent bleiben.
Der tooltip wird als TU-Eintrag (Alternativer Name) in das Widget geschrieben.
Pflichtfelder sind über required: true zu kennzeichnen. Der Wert landet im /Ff-Flag des Widgets.
Vergleiche dazu auch den Abschnitt PDF-Formular.
BibEntry- und Index-Tag
Permalink "BibEntry- und Index-Tag"Für Bibliografie-Einträge steht das Methodenpaar beginBibEntry/endBibEntry zur Verfügung, für Indexeinträge beginIndex/endIndex.
Beide Elemente werden im Regelfall als Block-Elemente (placement: "Block") eingesetzt und sind für ein semantisch korrektes Literatur- bzw. Stichwortverzeichnis erforderlich:
1doc.beginBibEntry();
2doc.setFontSize(10);
3doc.text(
4 "[1] ISO 14289-1:2014. Document management — Electronic document file format",
5 25,
6 40
7);
8doc.text(
9 " enhancement for accessibility — Part 1: Use of ISO 32000-1 (PDF/UA-1).",
10 25,
11 48
12);
13doc.endBibEntry();
Verweise
Permalink "Verweise"Interne Links zu anderen Beiträgen
Permalink "Interne Links zu anderen Beiträgen"- Hinweise zur Erstellung von Alternativtexten
- Hinweise zu Tools zur Überprüfung der Barrierefreiheit
- PDF-Formular
Externe Links zu diesem Artikel
Permalink "Externe Links zu diesem Artikel"- jsPDF auf GitHub (Upstream, ohne PDF/UA-Unterstützung) (Parallax)
- PDF/UA-1 (ISO 14289-1) (PDF Association)
- jsPDF-UA auf GitHub (Fork mit PDF/UA-Implementierung) (Heiko Folkerts)
- API-Referenz der PDF/UA-Erweiterung (Heiko Folkerts)
- Vollständiges Beispieldokument (Showcase) (Heiko Folkerts)
- Screenreader NVDA (NV Access)
- PDF Accessibility Checker (PAC) (axes4)
- Atkinson Hyperlegible Font (Braille Institute of America)
- veraPDF (Open Preservation Foundation)
Weiterführende Links
Permalink "Weiterführende Links"- Dokumentation zur PDF/UA-Implementierung im Fork (Heiko Folkerts)
- Verfügbare Strukturelemente (Heiko Folkerts)
- Bekannte Einschränkungen (Heiko Folkerts)
- PDF/UA in a Nutshell (PDF Association)
- Matterhorn Protocol 1.1 (PDF Association)
- ISO 14289-1:2014 (International Organization for Standardization)
- BITi Prüfschritte (BITi-Wiki)
- Testvorgehen für PDF-Dokumente gemäß BITV 2.0 und BFSG (BIT inklusiv)
Informationen zu diesem Artikel
Gerne können Sie uns Feedback per E-Mail zu unserer Handreichung senden!