Ich hatte kürzlich einen Artikel zu netten Blogfeatures verlinkt, darunter waren auch kleine Icons für Links auf andere Seiten. Das gefiel mir besonders, als kleine informationsvermittelnde Spielerei die niemandem schaden dürfte. Ich habe hier im Blog das jetzt umgesetzt, rein mit CSS.
Wer hier im Feedreader mitliest oder fürs Archiv, so sieht es aus:
Oder im Darkmode:

Die Umsetzung 1: Mask-Image
Das Icon setzte ich so:
@media screen {
.serendipity_entry_body a[href^="http"]::after,
.serendipity_entry_body a[href^="https://"]::after {
content: "";
width: 11px;
height: 11px;
margin-left: 4px;
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E");
mask-size: cover;
background-color: black;
display: inline-block;
}
}
Mit dieser ersten Anweisung bekommt jeder Link ein Icon hintendrangestellt. Das Icon ist dabei ein SVG, was hier praktisch ist weil SVGs nur Text sind. Entnommen ist das Icon diesem Artikel, wie auch ein Teil des Ansatzes, stammt aber ursprünglich von Bootstrap.
Die erste Besonderheit ist das Setzen des Icons als mask-image
, eine erst seit kurzem breit unterstützte CSS-Anweisung. Ich wollte es erst als background-image
oder als content
setzen. Aber in beiden Fällen funktionierte in meinem Test die Anpassung der Farbe nicht, obwohl im SVG die Farbe als currentColor
definiert war. Mit mask-image
aber ging das, background-color
kontrolliert nun die Farbe des Icons und setzt sie in diesem Fall auf schwarz. Klar, alternativ hätte die Farbe ins SVG reingeschrieben und bei Bedarf das SVG ausgewechselt werden könne, aber das fand ich nicht elegant.
Die zweite Besonderheit ist das drumrumgestellte Medienquery @media screen {
. Dadurch taucht das Icon nicht im Printstylesheet auf. Dort hätte es keine Funktion erfüllt, wird in diesem doch das Linkziel bereits als Text hinter Links geschrieben, außerdem kollidierte unter anderem die Breitenangabe mit dem dafür gesetzten ::after-Element.
Im gleichen Medienquery ist als nächstes dieser Block:
@media screen {
…
.serendipity_entry_body a[href^="https://www.onli-blogging"]::after,
.serendipity_entry_body a:has(img)::after {
display: none !important;
}
}
Damit entferne ich das Icon wieder in den Fällen, in denen es nicht passt. Zuerst sind das interne Links. Die ebenfalls mit dem Icon zu kennzeichnen würde ja die ganze Idee nutzlos werden lassen. Der zweite Selektor wählt alle Bilder, denen ein img-Element folgt. Bei Bildern macht das Icon ja funktional keinen Sinn. Der dafür genutzte Pseudoselektor :has
ist relativ neu, wird aber ebenfalls seit Ende 2023 weitflächig von Browsern unterstützt.
Im dunklen Modus wäre das schwarze Icon kaum sichtbar, dann die Farbe zu ändern war der letzte Schritt und geht dank dem Setzen als mask-image
schnell:
@media (prefers-color-scheme: dark) {
.serendipity_entry_body a[href^="http"]::after,
.serendipity_entry_body a[href^="https://"]::after {
background-color: thistle;
}
}
Diese Variante hat einen Nachteil, den ich nicht aufgelöst bekommen habe: Der Zeilenumbruch kann zwischen Link und Linkicon platziert werden. Das vermeidet der zweite, weniger elegante Ansatz.
Die Umsetzung 2: Inline-Content
Die zweite und bis jetzt aktive Variante setzt das SVG-Icon direkt als Contentattribut des ::after-Elements:
@media screen {
.serendipity_entry_body a[href^="http"]::after,
.serendipity_entry_body a[href^="https://"]::after {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='0.7em' height='0.7em' fill='currentColor' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E");
margin-left: 4px;
white-space: nowrap;
}
}
Der Preis ist die Anpassbarkeit der Farbe, die funktioniert so nicht mehr, color
hat keinen Effekt. Dafür sorgt white-space: nowrap;
tatsächlich dafür, dass zwischen Link und Linkicon nicht umgebrochen wird.
Weniger schön ist auch die Größenanpassung. Denn auch die funktioniert nicht mehr. Als Inlineelement wird per CSS gesetztes height und width ignoriert, auch font-size hatte keinen Effekt. Deswegen die Größenangaben im SVG selbst, das width='0.7em' height='0.7em'
wo vorher jeweils 16 stand.
Der Code für die Bilder und für das Printdesign bleibt wie bei Methode 1, denn das Ausblenden funktioniert identisch. Aber Im dunklen Modus muss nun leider das SVG ganz ausgewechselt werden:
@media (prefers-color-scheme: dark) {
.serendipity_entry_body a[href^="http"]::after,
.serendipity_entry_body a[href^="https://"]::after {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='0.7em' height='0.7em' fill='rgb(135, 155, 234)' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E");
}
}
Das ist fast das gleiche SVG, nur dass mit fill='rgb(135, 155, 234)'
die Farbe hartkodiert wurde.
Weniger elegant, aber letzten Endes zählt das Ergebnis. Und den Umbruch an der falschen Stelle vermeiden macht diese Lösung zu der zu bevorzugenden.
Es dauerte ein bisschen, das passende CSS für dieses Designelement zu finden. Und natürlich hatte ich nicht im Voraus an den dunklen Modus oder das Printstylesheet gedacht. Aber das Rumschrauben am Blog machte mal wieder Freude und ich glaube, die entstandene Lösung sollte generell gut funktionieren. Rückmeldungen dazu sind immer willkommen.
artodeto's blog about coding, politics and the world am : Die KW 28/2024 im Link-Rückblick
Vorschau anzeigen
onli blogging am : Ein kurzer Blogrückblick auf 2024
Vorschau anzeigen