Mit Textfragmenten können Sie ein Text-Snippet im URL-Fragment angeben. Wenn ein Nutzer eine URL mit einem solchen Textfragment aufruft, kann der Browser das Fragment hervorheben und/oder die Aufmerksamkeit des Nutzers darauf lenken.
Fragment-IDs
Chrome 80 war ein großes Release. Sie enthielt eine Reihe von mit Spannung erwarteten Funktionen wie ECMAScript-Module in Web Workers, Nullish Coalescing und Optional Chaining. Die Veröffentlichung wurde wie gewohnt in einem Blogpost im Chromium-Blog angekündigt. Unten sehen Sie einen Auszug aus dem Blogbeitrag.

id
.Sie fragen sich wahrscheinlich, was die roten Kästchen bedeuten. Sie sind das Ergebnis der Ausführung des folgenden Snippets in den Entwicklertools. Es werden alle Elemente hervorgehoben, die ein id
-Attribut haben.
document.querySelectorAll('[id]').forEach((el) => {
el.style.border = 'solid 2px red';
});
Ich kann einen Deeplink zu jedem Element setzen, das mit einem roten Rahmen hervorgehoben ist. Dazu verwende ich die Fragmentkennung, die ich dann im Hash der URL der Seite verwende. Angenommen, ich möchte einen Deeplink zum Feld Feedback in unseren Produktforen geben in der Seitenleiste erstellen, kann ich das tun, indem ich die URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1
manuell erstelle.
Wie Sie im Bereich „Elemente“ der Entwicklertools sehen können, hat das betreffende Element ein id
-Attribut mit dem Wert HTML1
.

id
eines ElementsWenn ich diese URL mit dem URL()
-Konstruktor von JavaScript parse, werden die verschiedenen Komponenten angezeigt.
Beachten Sie das Attribut hash
mit dem Wert #HTML1
.
new URL('https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1');
/* Creates a new `URL` object
URL {
hash: "#HTML1"
host: "blog.chromium.org"
hostname: "blog.chromium.org"
href: "https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1"
origin: "https://blog.chromium.org"
password: ""
pathname: "/2019/12/chrome-80-content-indexing-es-modules.html"
port: ""
protocol: "https:"
search: ""
searchParams: URLSearchParams {}
username: ""
}
*/
Die Tatsache, dass ich die Entwicklertools öffnen musste, um die id
eines Elements zu finden, spricht Bände über die Wahrscheinlichkeit, dass dieser bestimmte Abschnitt der Seite vom Autor des Blogposts verlinkt werden sollte.
Was ist, wenn ich auf etwas verlinken möchte, das kein id
hat? Angenommen, ich möchte einen Link zur Überschrift ECMAScript Modules in Web Workers erstellen. Wie Sie im Screenshot unten sehen, hat die betreffende <h1>
kein id
-Attribut. Daher kann ich nicht auf diese Überschrift verlinken. Das ist das Problem, das mit Textfragmenten gelöst wird.

id
Textfragmente
Mit dem Vorschlag Textfragmente wird die Möglichkeit eingeführt, ein Text-Snippet im URL-Hash anzugeben. Wenn ein Nutzer zu einer URL mit einem solchen Textfragment navigiert, kann der User-Agent das Fragment hervorheben und/oder dem Nutzer präsentieren.
Browserkompatibilität
Aus Sicherheitsgründen müssen Links in einem noopener
-Kontext geöffnet werden.
Fügen Sie daher rel="noopener"
in Ihr <a>
-Ankermarkup ein oder fügen Sie noopener
in Ihre Window.open()
-Liste der Fensterfunktionen ein.
start
In der einfachsten Form sieht die Syntax von Textfragmenten so aus: Das Rautensymbol #
gefolgt von :~:text=
und schließlich start
, das den prozentual codierten Text darstellt, auf den ich verlinken möchte.
#:~:text=start
Angenommen, ich möchte auf die Überschrift ECMAScript Modules in Web Workers im Blogbeitrag zur Ankündigung von Funktionen in Chrome 80 verweisen. Die URL wäre in diesem Fall:
Das Textfragment wird so hervorgehoben. Wenn Sie in einem unterstützten Browser wie Chrome auf den Link klicken, wird das Textfragment hervorgehoben und in den sichtbaren Bereich gescrollt:

start
und end
Was ist, wenn ich nicht nur die Überschrift, sondern den gesamten Abschnitt mit dem Titel ECMAScript Modules in Web Workers verlinken möchte? Wenn der gesamte Text des Abschnitts prozentual codiert würde, wäre die resultierende URL unpraktisch lang.
Glücklicherweise gibt es eine bessere Lösung. Anstatt des gesamten Texts kann ich den gewünschten Text mit der Syntax start,end
eingrenzen. Daher gebe ich einige prozentcodierte Wörter am Anfang des gewünschten Textes und einige prozentcodierte Wörter am Ende des gewünschten Textes an, die durch ein Komma ,
getrennt sind.
Das sieht so aus:
Für start
habe ich ECMAScript%20Modules%20in%20Web%20Workers
, dann ein Komma ,
gefolgt von ES%20Modules%20in%20Web%20Workers.
als end
. Wenn Sie in einem unterstützten Browser wie Chrome auf den Link klicken, wird der gesamte Abschnitt markiert und in den sichtbaren Bereich gescrollt:

Sie fragen sich jetzt vielleicht, warum ich start
und end
gewählt habe. Eigentlich hätte auch die etwas kürzere URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers.
mit nur zwei Wörtern auf jeder Seite funktioniert. Vergleichen Sie start
und end
mit den vorherigen Werten.
Wenn ich noch einen Schritt weitergehe und jetzt nur ein Wort für start
und end
verwende, wird es schwierig. Die URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers.
ist jetzt noch kürzer, aber das hervorgehobene Textfragment ist nicht mehr das ursprünglich gewünschte. Die Hervorhebung endet beim ersten Vorkommen des Wortes Workers.
. Das ist zwar korrekt, aber nicht das, was ich hervorheben wollte. Das Problem besteht darin, dass der gewünschte Abschnitt nicht eindeutig durch die aktuellen einwortigen start
- und end
-Werte identifiziert wird:

prefix-
und -suffix
Eine Lösung für einen eindeutigen Link besteht darin, lange genug Werte für start
und end
zu verwenden.
In einigen Fällen ist das jedoch nicht möglich. Warum habe ich den Blogbeitrag zur Veröffentlichung von Chrome 80 als Beispiel ausgewählt? In dieser Version wurden Textfragmente eingeführt:

Im Screenshot oben sehen Sie, dass das Wort „Text“ viermal vorkommt. Das vierte Vorkommen wird in einer grünen Schriftart für Code geschrieben. Wenn ich auf dieses bestimmte Wort verlinken möchte, würde ich start
auf text
setzen. Da das Wort „Text“ nur ein Wort ist, kann es keine end
geben. Was kann ich tun? Die URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text
stimmt bereits beim ersten Vorkommen des Wortes „Text“ in der Überschrift überein:

Zum Glück gibt es eine Lösung. In solchen Fällen kann ich eine prefix-
und eine -suffix
angeben. Das Wort vor der grünen Code-Schriftart „text“ ist „the“ und das Wort danach „parameter“. Keines der anderen drei Vorkommen des Wortes „Text“ hat dieselben umgebenden Wörter. Mit diesem Wissen kann ich die vorherige URL anpassen und prefix-
und -suffix
hinzufügen. Wie die anderen Parameter müssen auch sie prozentual codiert werden und können mehr als ein Wort enthalten.
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter
.
Damit der Parser die prefix-
und die -suffix
eindeutig identifizieren kann, müssen sie durch einen Bindestrich -
von der start
und der optionalen end
getrennt werden.

Die vollständige Syntax
Die vollständige Syntax von Textfragmenten finden Sie unten. (Eckige Klammern kennzeichnen einen optionalen Parameter.)
Die Werte für alle Parameter müssen prozentual codiert sein. Das ist besonders wichtig für die Zeichen Bindestrich -
, kaufmännisches Und &
und Komma ,
, damit sie nicht als Teil der Syntax der Textanweisung interpretiert werden.
#:~:text=[prefix-,]start[,end][,-suffix]
Die einzelnen Elemente prefix-
, start
, end
und -suffix
stimmen nur mit Text innerhalb eines einzelnen Elements auf Blockebene überein. Vollständige start,end
-Bereiche können sich jedoch über mehrere Blöcke erstrecken. :~:text=The quick,lazy dog
kann im folgenden Beispiel nicht abgeglichen werden, da der Startstring „The quick“ nicht in einem einzelnen, ununterbrochenen Blockelement enthalten ist:
<div>
The
<div></div>
quick brown fox
</div>
<div>jumped over the lazy dog</div>
In diesem Beispiel stimmt sie jedoch überein:
<div>The quick brown fox</div>
<div>jumped over the lazy dog</div>
URLs für Textfragmente mit einer Browsererweiterung erstellen
Das manuelle Erstellen von Textfragment-URLs ist mühsam, insbesondere wenn es darum geht, dass sie eindeutig sind. Wenn Sie es wirklich möchten, finden Sie in der Spezifikation einige Tipps und eine genaue Anleitung zum Generieren von Textfragment-URLs. Wir bieten eine Open-Source-Browsererweiterung namens Link to Text Fragment an, mit der Sie einen Link zu einem beliebigen Text erstellen können, indem Sie ihn auswählen und dann im Kontextmenü auf „Copy Link to Selected Text“ (Link zum ausgewählten Text kopieren) klicken. Diese Erweiterung ist für die folgenden Browser verfügbar:
- Link zu Textfragment für Google Chrome
- Link zu Textfragmenten für Microsoft Edge
- Link zu Textfragment für Mozilla Firefox
- Link zum Textfragment für Apple Safari

Mehrere Textfragmente in einer URL
Beachten Sie, dass in einer URL mehrere Textfragmente enthalten sein können. Die einzelnen Textfragmente müssen durch ein Und-Zeichen &
getrennt werden. Hier ein Beispiel für einen Link mit drei Textfragmenten:
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=Text%20URL%20Fragments&text=text,-parameter&text=:~:text=On%20islands,%20birds%20can%20contribute%20as%20much%20as%2060%25%20of%20a%20cat's%20diet
.

Element- und Textfragmente mischen
Herkömmliche Elementfragmente können mit Textfragmenten kombiniert werden. Es ist durchaus sinnvoll, beide in derselben URL zu verwenden, um beispielsweise einen aussagekräftigen Fallback zu bieten, falls sich der Originaltext auf der Seite ändert und das Textfragment nicht mehr übereinstimmt. Die URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums.
, die auf den Abschnitt Feedback in unseren Produktforen verweisen, enthält sowohl ein Elementfragment (HTML1
) als auch ein Textfragment (text=Give%20us%20feedback%20in%20our%20Product%20Forums.
):

Die Fragmentanweisung
Ein Element der Syntax habe ich noch nicht erklärt: die Fragmentanweisung :~:
. Um die oben gezeigten Kompatibilitätsprobleme mit vorhandenen URL-Elementfragmenten zu vermeiden, wird in der Text Fragments-Spezifikation die Fragmentanweisung eingeführt. Die Fragmentanweisung ist ein Teil des URL-Fragments, der durch die Zeichenfolge :~:
begrenzt wird. Sie ist für User-Agent-Anweisungen wie text=
reserviert und wird beim Laden aus der URL entfernt, damit Autorenskripts nicht direkt damit interagieren können. User-Agent-Anweisungen werden auch als Anweisungen bezeichnet. Im konkreten Fall wird text=
daher als Textanweisung bezeichnet.
Funktionserkennung
Um die Unterstützung zu erkennen, testen Sie die schreibgeschützte Property fragmentDirective
für document
. Die Fragmentanweisung ist ein Mechanismus, mit dem in URLs Anweisungen für den Browser und nicht für das Dokument angegeben werden können. Dadurch soll eine direkte Interaktion mit dem Autorenskript vermieden werden, damit zukünftige User-Agent-Anweisungen hinzugefügt werden können, ohne dass bestehende Inhalte geändert werden müssen. Ein potenzielles Beispiel für solche zukünftigen Ergänzungen könnten Übersetzungshinweise sein.
if ('fragmentDirective' in document) {
// Text Fragments is supported.
}
Die Funktionserkennung ist hauptsächlich für Fälle vorgesehen, in denen Links dynamisch generiert werden (z. B. von Suchmaschinen), um zu vermeiden, dass Textfragmentlinks an Browser gesendet werden, die sie nicht unterstützen.
Textfragmente formatieren
Standardmäßig formatieren Browser Textfragmente auf dieselbe Weise wie mark
(in der Regel schwarz auf gelb, die CSS-Systemfarben für mark
). Das User-Agent-Stylesheet enthält CSS, das so aussieht:
:root::target-text {
color: MarkText;
background: Mark;
}
Wie Sie sehen, stellt der Browser einen Pseudoselektor ::target-text
zur Verfügung, mit dem Sie die angewendete Hervorhebung anpassen können. Sie könnten beispielsweise schwarze Textfragmente auf rotem Hintergrund gestalten. Achten Sie wie immer auf den Farbkontrast, damit die überschriebenen Formatierungen keine Barrierefreiheitsprobleme verursachen, und darauf, dass die Hervorhebung sich tatsächlich visuell vom Rest des Inhalts abhebt.
:root::target-text {
color: black;
background-color: red;
}
Polyfillability
Die Funktion „Textfragmente“ kann bis zu einem gewissen Grad polyfilled werden. Wir stellen ein Polyfill bereit, das intern von der Erweiterung für Browser verwendet wird, die keine integrierte Unterstützung für Textfragmente bieten, wenn die Funktion in JavaScript implementiert ist.
Programmatische Linkgenerierung für Textfragmente
Das Polyfill enthält die Datei fragment-generation-utils.js
, die Sie importieren und zum Generieren von Textfragmentlinks verwenden können. Dies wird im folgenden Codebeispiel veranschaulicht:
const { generateFragment } = await import('https://unpkg.com/text-fragments-polyfill/dist/fragment-generation-utils.js');
const result = generateFragment(window.getSelection());
if (result.status === 0) {
let url = `${location.origin}${location.pathname}${location.search}`;
const fragment = result.fragment;
const prefix = fragment.prefix ?
`${encodeURIComponent(fragment.prefix)}-,` :
'';
const suffix = fragment.suffix ?
`,-${encodeURIComponent(fragment.suffix)}` :
'';
const start = encodeURIComponent(fragment.textStart);
const end = fragment.textEnd ?
`,${encodeURIComponent(fragment.textEnd)}` :
'';
url += `#:~:text=${prefix}${start}${end}${suffix}`;
console.log(url);
}
Textfragmente für Analysezwecke abrufen
Viele Websites verwenden das Fragment für das Routing. Daher entfernen Browser Textfragmente, um diese Seiten nicht zu beschädigen. Es besteht ein anerkannter Bedarf, Textfragment-Links zu Seiten verfügbar zu machen, z. B. für Analysezwecke. Die vorgeschlagene Lösung ist jedoch noch nicht implementiert. Als vorübergehende Problemumgehung können Sie den folgenden Code verwenden, um die gewünschten Informationen zu extrahieren.
new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;
Sicherheit
Textfragment-Anweisungen werden nur bei vollständigen (nicht auf derselben Seite) Navigationen aufgerufen, die auf eine Nutzeraktivierung zurückzuführen sind.
Außerdem muss bei Navigationsvorgängen, die von einem anderen Ursprung als dem Ziel ausgehen, die Navigation in einem noopener
-Kontext erfolgen, damit die Zielseite ausreichend isoliert ist. Textfragment-Direktiven werden nur auf den Hauptframe angewendet. Das bedeutet, dass in iFrames nicht nach Text gesucht wird und die Navigation in iFrames kein Textfragment aufruft.
Datenschutz
Es ist wichtig, dass Implementierungen der Textfragment-Spezifikation nicht preisgeben, ob ein Textfragment auf einer Seite gefunden wurde oder nicht. Elementfragmente unterliegen der vollständigen Kontrolle des ursprünglichen Seitenautors, Textfragmente können jedoch von jedem erstellt werden. Erinnern Sie sich daran, dass es in meinem Beispiel oben keine Möglichkeit gab, einen Link zur Überschrift ECMAScript Modules in Web Workers zu erstellen, da <h1>
kein id
hatte. Jeder, auch ich, konnte jedoch einen Link zu einer beliebigen Stelle erstellen, indem er das Textfragment sorgfältig formuliert hat.
Stellen Sie sich vor, ich würde ein böswilliges Werbenetzwerk evil-ads.example.com
betreiben. Stellen Sie sich außerdem vor, dass ich in einem meiner Anzeigen-iFrames dynamisch ein verborgenes ursprungsübergreifendes iFrame für dating.example.com
mit einer Textfragment-URL dating.example.com#:~:text=Log%20Out
erstellt habe, sobald der Nutzer mit der Anzeige interagiert. Wenn der Text „Abmelden“ angezeigt wird, weiß ich, dass das Opfer derzeit bei dating.example.com
angemeldet ist. Diese Information könnte ich für die Erstellung eines Nutzerprofils verwenden. Da bei einer einfachen Implementierung von Textfragmenten entschieden werden könnte, dass eine erfolgreiche Übereinstimmung einen Fokuswechsel verursachen sollte, könnte ich auf evil-ads.example.com
auf das blur
-Ereignis warten und so erfahren, wann eine Übereinstimmung aufgetreten ist. In Chrome haben wir Textfragmente so implementiert, dass das oben beschriebene Szenario nicht eintreten kann.
Eine weitere Angriffsmöglichkeit besteht darin, den Netzwerkverkehr basierend auf der Scrollposition auszunutzen. Angenommen, ich hätte als Administrator eines Unternehmensintranets Zugriff auf die Netzwerkverkehrsprotokolle meines Opfers. Stellen Sie sich vor, es gäbe ein langes HR-Dokument mit dem Titel Was tun, wenn Sie unter… leiden und dann eine Liste mit Erkrankungen wie Burn-out, Angst usw. Ich könnte neben jedem Element in der Liste ein Tracking-Pixel platzieren. Wenn ich dann feststelle, dass das Laden des Dokuments zeitgleich mit dem Laden des Tracking-Pixels neben dem Element Burn-out erfolgt, kann ich als Intranetadministrator feststellen, dass ein Mitarbeiter auf einen Textfragmentlink mit :~:text=burn%20out
geklickt hat, von dem der Mitarbeiter möglicherweise angenommen hat, dass er vertraulich und für niemanden sichtbar ist. Da dieses Beispiel von vornherein etwas konstruiert ist und seine Ausnutzung sehr spezifische Voraussetzungen erfordert, die erfüllt sein müssen, hat das Chrome-Sicherheitsteam das Risiko der Implementierung von Scrollen bei der Navigation als überschaubar eingestuft.
Andere User-Agents zeigen möglicherweise stattdessen ein UI-Element für manuelles Scrollen an.
Für Websites, die die Funktion deaktivieren möchten, unterstützt Chromium einen Document Policy-Headerwert, den sie senden können, damit User-Agents keine Textfragment-URLs verarbeiten.
Document-Policy: force-load-at-top
Textfragmente deaktivieren
Die einfachste Möglichkeit, das Feature zu deaktivieren, ist die Verwendung einer Erweiterung, mit der HTTP-Antwortheader eingefügt werden können, z. B. ModHeader (kein Google-Produkt). Damit können Sie einen Antwortheader (nicht Anfrageheader) wie folgt einfügen:
Document-Policy: force-load-at-top
Eine weitere, aufwendigere Möglichkeit zum Deaktivieren ist die Verwendung der Unternehmenseinstellung ScrollToTextFragmentEnabled
.
Fügen Sie dazu unter macOS den folgenden Befehl in das Terminal ein.
defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false
Unter Windows folgen Sie der Dokumentation auf der Supportwebsite der Chrome Enterprise-Hilfe.
Textfragmente in der Websuche
Auf manche Suchanfragen liefert die Suchmaschine Google eine kurze Antwort oder Zusammenfassung mit einem Content-Snippet von einer relevanten Website. Solche hervorgehobenen Snippets erscheinen insbesondere bei Suchanfragen, die als Frage formuliert sind. Durch Klicken auf ein hervorgehobenes Snippet gelangt der Nutzer direkt zum Text des hervorgehobenen Snippets auf der Quellwebseite. Das funktioniert dank automatisch erstellter URLs für Textfragmente.


Fazit
Mit Textfragment-URLs können Sie auf beliebigen Text auf Webseiten verweisen. Die wissenschaftliche Community kann damit hochpräzise Zitations- oder Referenzlinks erstellen. Suchmaschinen können damit Deeplinks zu Text-Suchergebnissen auf Seiten erstellen. Soziale Netzwerke können damit Nutzern ermöglichen, bestimmte Abschnitte einer Webseite anstelle von nicht zugänglichen Screenshots zu teilen. Ich hoffe, Sie werden Textfragment-URLs verwenden und sie genauso nützlich finden wie ich. Installieren Sie unbedingt die Browsererweiterung Link to Text Fragment.
Weitere Informationen
- Spezifikationsentwurf
- TAG-Überprüfung
- Chrome-Plattformstatuseintrag
- Chrome-Tracking-Fehler
- Intent to Ship-Thread
- WebKit-Dev-Thread
- Mozilla-Thread zur Positionierung von Standards
Danksagungen
Textfragmente wurden von Nick Burris und David Bokan implementiert und spezifiziert. Grant Wang hat ebenfalls dazu beigetragen. Vielen Dank an Joe Medley für die gründliche Überprüfung dieses Artikels. Hero-Image von Greg Rakozy auf Unsplash.