angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Verwendung von Icons auf Ihrer Flask Website und Reduzierung von 'First Contentful Paint'.

Verwenden Sie ein Ikonenmakro Jinja , um Ikonen auf Ihren Seiten zu platzieren, und verwenden Sie <symbol> , um Ikonen einmal zu definieren und mehrmals auf derselben Seite zu verwenden.

29 Mai 2020
post main image
https://unsplash.com/@codingtim

Es gibt viele Arten von Vektorsymbolen. In diesem Beitrag schaue ich mir nur SVG-icons an und beschränke mich auf Navigations-Icons, manchmal auch Interface-Icons genannt. Diese Icons sehen auf Websites nicht nur schön aus, sie sind auch farblich und skalierbar wie Schriftarten. Und sie sind sehr funktional. Stellen Sie sich eine Schaltfläche mit dem Text 'Bearbeiten' vor. Ersetzen Sie diesen Text durch ein Bleistift-Icon und Sie erhalten mehr Platz auf der Seite, während es immer noch sehr klar ist, was passiert, wenn Sie auf den Button klicken.

Ein weiteres Beispiel ist die Kontaktseite. Anstatt eine Telefonnummer, eine E-Mail-Adresse und eine Besuchsadresse nur als Text aufzuführen, können Sie Ikonen davor setzen, was die Lesbarkeit und Verwendung erleichtert.

Die wohl bekanntesten Symbole sind das Suchsymbol und das Symbol für Login/Account (Person). Auf dem Bildschirm Ihres Mobiltelefons ist nicht so viel Platz wie auf einem desktop -Computer. In vielen Fällen ändert sich die Menüleiste auf einem Telefon und die horizontalen Menüpunkte werden in einem Dropdown-Menü angeordnet, das durch Anklicken eines Hamburger-Icons aktiviert werden kann. Um die Such- und Login-/Kontopfunktionen immer zugänglich zu halten, wird oft das Suchfeld durch ein Such-Icon und die Login-/Kontotexte durch ein Personen-Icon ersetzt.

Möglichkeiten, Icons zu Ihrer Website hinzuzufügen

Der einfachste Weg ist das Hinzufügen von Icons als Schriftart. Sie laden die Schriftart herunter (aus Datenschutzgründen verwenden wir keine CDN ), fügen die Schriftfamilie hinzu und fertig. Als ich mit dieser Website begann, wählte ich Font Awesome. Warum? Ich suchte im Internet nach Bootstrap-Icons, und es gab viele Treffer, die Font Awesome erwähnten. Font Awesome hat wirklich einen sehr schönen Satz freier Icons. Sie zu Ihren Seiten hinzuzufügen ist einfach. Um zum Beispiel ein user-Icon hinzuzufügen, fügen Sie den Code hinzu:

	<i class="fas fa-user"></i>

Eine weitere Möglichkeit, Symbole hinzuzufügen, ist Inline. Anstatt Code zur Auswahl eines Icons aus der Schriftart Font Awesome hinzuzufügen, fügen wir den eigentlichen SVG-Icon-Code hinzu. Sie können den Code für das Symbol SVG von der Website Font Awesome herunterladen, den Code für das Symbol user:

	<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="user" class="svg-inline--fa fa-user  fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"></path></svg>

Es gibt mehr Möglichkeiten, aber bei den meisten von ihnen verliert man die Fähigkeit zu färben und zu skalieren. Einen schönen Überblick bietet der Artikel 'Using SVG', siehe Links unten.

Symbole und Seitenladezeit

Wenn Sie eine Website erstellen, ist einer der wichtigsten Aspekte die Zeit, die es dauert, bis eine Seite auf dem Bildschirm erscheint. Viele Suchmaschinen haben die Ladezeit Ihrer Website zu einem Ranking-Faktor gemacht. Chromium Developer Tools hat ein nettes Werkzeug zur Messung dieser Zeit, das 'Audits' genannt wird. Dies ist das Programm Lighthouse , das Ihnen Bewertungen für Leistung, Zugänglichkeit, beste Praktiken und SEO gibt. Für die Leistung ist 'First Contentful Paint' sehr wichtig.

Lighthouse hat mir gezeigt, dass das Laden und Rendern der Font Awesome -Dateien für fast eine Sekunde verantwortlich war! Wenn Sie sich die Website Font Awesome ansehen, sehen Sie, dass etwa 1500 freie Icons in der Schriftart enthalten sind. Sehr schön, aber ich verwende nur 25 davon.

Da ich die Ladezeit reduzieren wollte, habe ich erwogen, eine benutzerdefinierte Icon-Schriftart zu verwenden. Mit Icomoon, siehe Links unten, können Sie zum Beispiel eine Ikonen-Schriftart mit nur den von Ihnen verwendeten Ikonen erstellen. Sehr schön, aber ich habe mich für Inline-Ikonen entschieden, weil dadurch das Laden zusätzlicher Dateien entfällt. Der Nachteil ist, dass die Seitengröße zunimmt. Eine nette Diskussion über Leistungsaspekte findet sich in dem Artikel 'Inline SVG vs Icon Fonts [CAGEMATCH]', siehe Links unten.

Verwenden Sie ein Makro Jinja , um Symbole auf die Seite zu setzen

Wenn Sie über Ikonen nachdenken, ist es wahrscheinlich eine gute Idee, daran zu denken, dass Sie die Ikonen morgen ändern wollen. Oder sogar mehrere Icon-Sets pflegen wollen. Als Test habe ich die neuen Ikonen Bootstrap 5 als zweiten Ikonensatz ausgewählt. Um beide Ikonensätze zu unterstützen, habe ich das folgende Makro Jinja erstellt: Jinja

{%- macro icon(icon_name, fill=false, collection=none, inline=false) -%}

	{%- if not collection %}
		{%- set collection = 'fontawesome' -%}
	{%- endif %}

	{%- if collection == 'fontawesome' -%}

		{%- if icon_name in ['angle_up', 'chevron_up'] -%}
				
			{%- if inline -%}
				<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="angle-up" class="svg-inline--fa fa-angle-up fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"></path></svg>
			{%- else -%}
				<i class="fas fa-angle-up"></i>
			{%- endif -%}

		{%- elif icon_name in ['arrow_clockwise', 'redo'] -%}
		...

	{%- endif -%}


	{%- if collection == 'bootstrap5' -%}

		{%- if icon_name in ['angle_up', 'chevron_up'] -%}

			{%- if inline -%}
				<svg class="bi bi-chevron-up" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"/></svg>			{%- else -%}
			{%- else -%}

			{%- endif -%}

		{%- elif icon_name in ['arrow_clockwise', 'redo'] -%}
		...

	{%- endif -%}

{%- endmacro -%}

Ich kann dieses Makro sowohl mit den Ikonen Font Awesome als auch mit Bootstrap 5 verwenden. Darüber hinaus kann ich angeben, ob ich das Symbol für den Fülltyp und das Symbol SVG inline haben möchte. Durch Modifizierung des Makros kann ich auch sowohl das Symbol Font Awesome als auch das Symbol Bootstrap 5 zur visuellen Kontrolle ausgeben. Die Verwendung dieses Makros ist sehr einfach, in Ihrer Seite können Sie es verwenden:

	{{ icon('home') }} Hoogerheid, NL

Verhindern von identischen Inline- SVG-Icons

Ein schneller Test hat mir gezeigt, dass die Inline-Icons SVG tatsächlich 'First Contentful Paint' um fast eine Sekunde verkleinert haben. Großartig! Aber manchmal war eine Ikone mehrmals auf einer Seite. Bei einer durchschnittlichen Größe von 400 - 600 Zeichen pro SVG-Icon kann sich dies ernsthaft auf die Ladezeit der Seite auswirken. Ein Beispiel ist ein Kommentarbereich, in dem jeder Kommentar ein Kalendersymbol und ein @-Symbol hat und in dem es hundert Kommentare gibt.

Glücklicherweise gibt es eine Möglichkeit, einen Block von Ikonen auf einer Seite zu definieren und sie später zu verwenden. Wir tun dies mit den Tags <svg> und <symbol>:

<svg class="d-none">
	<symbol id="icon-angle-up" viewBox="0 0 16 16">
		<title>angle-up</title>
		<path fill-rule="evenodd" d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"/>
	</symbol>
	<symbol id="icon-arrow-clockwise" viewBox="0 0 16 16">
		<title>arrow-clockwise</title>
		<path fill-rule="evenodd" d="M3.17 6.706a5 5 0 0 1 7.103-3.16.5.5 0 1 0 .454-.892A6 6 0 1 0 13.455 5.5a.5.5 0 0 0-.91.417 5 5 0 1 1-9.375.789z"/><path fill-rule="evenodd" d="M8.147.146a.5.5 0 0 1 .707 0l2.5 2.5a.5.5 0 0 1 0 .708l-2.5 2.5a.5.5 0 1 1-.707-.708L10.293 3 8.147.854a.5.5 0 0 1 0-.708z"/>
	</symbol>
	...
</svg>

Weitere Informationen finden Sie im Artikel 'SVG 'symbol' a Good Choice for Icons', siehe Links unten. Wir setzen diesen Block direkt unter den <body>-Tag. Beachten Sie, dass wir nur die Pfade eines Icons in die Definition aufnehmen. Der Titel ist optional. Um die Ikone zu verwenden, müssen wir nur ihre Id angeben:

	<svg class="svg-icon"><use xlink:href="#icon-calendar"></use>

Wir können es auch in eine <Spanne> mit einer Klasse einpacken, z.B. um seine Größe zu ändern.

Umsetzung

Es gibt zwei Dinge, die beim Hinzufügen eines neuen Icons bearbeitet werden müssen:

  • der Symbol-Icon-Satz
  • das Ikonenmakro

Darüber hinaus möchte ich HTML-Code, den ich auf eine Seite zur schnellen visuellen Inspektion setzen kann. Sehr bald wurde ich des Editierens müde und beschloss, ein Skript zu schreiben, mit dem diese Daten generiert werden können. Ich entschied mich auch, mich nur für die Symbole Bootstrap 5 zu entscheiden, sie gefielen mir besser, sie sind MIT lizenziert und haben alle die gleiche ViewBox. Das Skript wurde sehr schnell geschrieben, also schießen Sie nicht auf mich:

import sys

class  SVGIcon():

    def __init__(self,
        icon_collection=None,
        icon_name=None,
        icon_id=None,
        svg_class=None,
        svg_fill=None,
        svg_view_box=None,
        svg_path=None,
        symbol_title=None
        ):

        self.icon_collection = icon_collection
        self.icon_name = icon_name
        self.icon_id = icon_id
        self.svg_class = svg_class
        self.svg_fill = svg_fill
        self.svg_view_box = svg_view_box
        self.svg_path = svg_path
        self.symbol_title = symbol_title


def doit():
    
    svg_icons = []

    icon_name2icon_details = {
        'angle_up': {
            'refs': ['angle_up', 'chevron_up'],
            'svg_path': '<path fill-rule="evenodd" d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"/>',
        },
        'arrow_clockwise': {
            'refs': ['arrow_clockwise', 'redo', 'resend_mail'],
            'svg_path': '<path fill-rule="evenodd" d="M3.17 6.706a5 5 0 0 1 7.103-3.16.5.5 0 1 0 .454-.892A6 6 0 1 0 13.455 5.5a.5.5 0 0 0-.91.417 5 5 0 1 1-9.375.789z"/><path fill-rule="evenodd" d="M8.147.146a.5.5 0 0 1 .707 0l2.5 2.5a.5.5 0 0 1 0 .708l-2.5 2.5a.5.5 0 1 1-.707-.708L10.293 3 8.147.854a.5.5 0 0 1 0-.708z"/>',
        },
        ...
    }

    icon_collection = 'bootstrap5'
    svg_view_box = "0 0 16 16"
    svg_fill = "currentColor"

    for icon_name in icon_name2icon_details:
        icon_details = icon_name2icon_details[icon_name]
        svg_path = icon_details['svg_path']

        svg_icons.append(SVGIcon(
            icon_collection = icon_collection,
            icon_name = icon_name,
            icon_id = 'icon-'  +  icon_name.replace('_', '-'),
            svg_fill = svg_fill,
            svg_view_box = svg_view_box,
            svg_path = svg_path,
            symbol_title = icon_name.replace('_', '-'),
        ))

    # generate svg symbols list
     symbols_list_lines = []
     symbols_list_lines.append( '<svg class="d-none">' )

    for svg_icon in svg_icons:
         symbols_list_lines.append( "\t"  +  '<symbol id="'  +  svg_icon.icon_id  +  '" viewBox="'  +  svg_icon.svg_view_box  +  '">' )
         symbols_list_lines.append( "\t\t"  +  '<title>'  +  svg_icon.symbol_title  +  '</title>' )
         symbols_list_lines.append( "\t\t"  +  svg_icon.svg_path )
         symbols_list_lines.append( "\t"  +  '</symbol>' )

     symbols_list_lines.append( '</svg>' )
     symbols_list  = "\n".join(symbols_list_lines)

    # generate svg symbols preview
    preview_lines = []
    for svg_icon in svg_icons:
        preview_lines.append( 'abc'  +  ' '  +  '<span class="font-size: 1em;"><svg class="svg-icon">'  +  '<use xlink:href="#'  +  svg_icon.icon_id  +  '"></use></svg>'  +  '</span>'  +  ' '  +  svg_icon.icon_name )

     preview_list  = '<p>'  +  "</p>\n<p>".join(preview_lines)  +  '</p>'

    # generate icon macro code
    icon_macro_lines = []
    first = True        
    for icon_name in icon_name2icon_details:
        icon_details = icon_name2icon_details[icon_name]
        if 'refs' not in icon_details:
            print('refs missing for {}'.format(icon_name))
            sys.exit()
        refs = icon_details['refs']
        # get icon
        found = False
        for svg_icon in svg_icons:
            if svg_icon.icon_name == icon_name:
                found = True
                break
        if not found:
            print('cannot find icon, icon_name = {}'.format(icon_name))
            sys.exit()
                
        if_start = 'elif'
        if first:
            if_start = 'if'
            first = False

        # expand refs
        ref_items = []
        for ref in refs:
            ref_items.append( "'"  +  ref  +  "'" )
            ref_list = '['  +  ', '.join(ref_items)  +  ']'

        icon_macro_lines.append( "\t"  +  '{%- '  +  if_start  +  ' icon_name in '  +  ref_list  +  ' -%}' )
        icon_macro_lines.append( '<span class="font-size: 1em;"><svg class="svg-icon">'  +  '<use xlink:href="#'  +  svg_icon.icon_id  +  '"></use></svg>'  +  '</span>' )

    icon_macro_lines.append( "\t"  +  '{%- endif -%}' )
     icon_macro_list  = "\n".join(icon_macro_lines)

    print('symbols_list:')
    print('{}'.format(symbols_list))
    print('preview_list:')
    print('{}'.format(preview_list))
    print('icon_macro_list:')
    print('{}'.format(icon_macro_list))

Danach kopiere und füge ich einfach die Teile symbols_list, preview_list und icon_macro_list in die Basisvorlage, die Vorschaudatei und die Makrodatei ein.

Einige Probleme

In meinen Listen-Tabellen hatten Spalten, die sortiert werden konnten, das Sortier-Icon am letzten Wort des Spaltennamens angehängt. Wenn eine Spalte kleiner wird, möchte ich, dass das Icon beim letzten Wort bleibt. Das funktioniert nicht mehr. Ich habe dafür noch keine Lösung gefunden, habe mich aber nicht im Detail damit befasst.

Eine andere Sache ist die vertikale Positionierung der Symbole. Hierfür gibt es Lösungen, eine ist in 'Align SVG Icons to Text and Say Goodbye to Font Icons' beschrieben, siehe Links unten. Nachdem Sie begonnen hatten, die Ikonen Bootstrap 5 wie oben beschrieben zu verwenden, stellte sich heraus, dass es nicht notwendig war, eine Positionierung vorzunehmen, aber Sie sollten sich das vielleicht ansehen.

Zusammenfassung

Durch die Verwendung von SVG-Icons sieht eine Website wirklich besser aus und lässt sich besser navigieren. Da ich nur 25 Icons verwende, habe ich mich entschieden, die SVG-Symbolmethode zu verwenden, um die Icons in die Seiten einzubinden, was zusätzliche 11,5 KB bedeutet. Verglichen mit der Lösung Font Awesome ging die 'First Contentful Paint' um fast eine Sekunde zurück! Und die Verwendung eines Jinja Makro-Icons() gibt mir die Flexibilität, die Icons an einer Stelle zu ändern, anstatt alle Seiten aktualisieren zu müssen. Im Moment werden alle Icons auf jeder Seite geladen. In Zukunft kann ich dies optimieren, indem ich nur die auf einer Seite verwendeten Ikonen einfüge.

Links / Impressum

Align SVG Icons to Text and Say Goodbye to Font Icons
https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4

Blog Optimization: Replacing Font Awesome with SVG
https://www.wouterbulten.nl/blog/tech/blog-optimization-replacing-font-awesome-with-svg/

Flask | JINJA 2: render_template_string() with macro imported in context
https://stackoverflow.com/questions/61338841/flask-jinja-2-render-template-string-with-macro-imported-in-context

Icomoon
https://icomoon.io

Inline SVG vs Icon Fonts [CAGEMATCH]
https://css-tricks.com/icon-fonts-vs-svg/

Insert image after each list item
https://stackoverflow.com/questions/946403/insert-image-after-each-list-item

Is there a way to use SVG as content in a pseudo element :before or :after
https://stackoverflow.com/questions/19255296/is-there-a-way-to-use-svg-as-content-in-a-pseudo-element-before-or-after

Lighthouse | Tools for Web Developers | Google Developers
https://developers.google.com/web/tools/lighthouse

SVG 'symbol' a Good Choice for Icons
https://css-tricks.com/svg-symbol-good-choice-icons/

Using SVG
https://css-tricks.com/using-svg/

Einen Kommentar hinterlassen

Kommentieren Sie anonym oder melden Sie sich zum Kommentieren an.

Kommentare

Eine Antwort hinterlassen

Antworten Sie anonym oder melden Sie sich an, um zu antworten.