Eigener Suchtitel, Schriften lokal, Bilder in Anzeigegroesse
Getrennter Titel fuer Suchergebnisse je Seite und Beitrag (Migration 20260913000100): auf der Seite steht "Leistungen", im Suchergebnis darf der lange Titel stehen. Leer heisst weiterhin: der Titel der Seite. Schriften kommen jetzt vom eigenen Server. Ein Knopf im Designbereich oder cms:fonts:fetch holt die gewaehlten Google-Schnitte als WOFF2 nach public/assets/fonts. Das spart zwei fremde Verbindungen nacheinander (gemessen 820 ms) und die IP-Weitergabe an Google. Ohne Dateien bleibt es beim bisherigen Verweis - eine Seite ohne Schrift waere schlimmer. Ein Stylesheet statt vier, mit Pruefsumme im Namen und ohne Kommentare, dazu eine .htaccess mit Kompression, Cache und Schutz interner Dateien. Der Entwicklungsserver sendet dieselben Kopfzeilen, sonst misst man lokal etwas, das es im Betrieb nicht gibt. Bilder in der Groesse, in der sie erscheinen: ein nur fuer Desktop gesetztes Hintergrundbild gilt auf dem Telefon in Telefongroesse (189 KB -> 40 KB), img nennt seine feste Breite oder sizes="auto", und fetchpriority liegt auf dem ersten Bild des Inhalts statt auf dem Logo. Neu: npm run test:links prueft jeden internen Verweis auf seine Antwort. Lighthouse gegen den Nachbau: Barrierefreiheit, Best Practices und SEO 100 auf allen vier geprueften Adressen, Performance 100 ausser auf der bilderreichen Startseite (98 mobil, 96 Desktop). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
35d8270afd
commit
074ef0e7e5
34 files changed
+1223
-45
No files matched your search
@@ -10,7 +10,7 @@
|
||||
{% set tag = type == 'section' ? 'section' : 'div' %}
|
||||
<{{ tag }} id="{{ block.id }}" class="block-{{ type }} tone-{{ layout.tone|default('paper') }} width-{{ layout.width|default('normal') }}{{ designClasses }}">
|
||||
{% if type == 'section' %}<div class="shell section-inner">{% endif %}
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}{% endfor %}
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}{% endfor %}
|
||||
{% if type == 'section' %}</div>{% endif %}
|
||||
</{{ tag }}>
|
||||
{% elseif type == 'heading' %}
|
||||
@@ -26,7 +26,18 @@
|
||||
{% elseif type == 'button' %}
|
||||
<a id="{{ block.id }}" class="button{{ designClasses }}" href="{{ props.href }}">{{ props.text }} <span aria-hidden="true">↗</span></a>
|
||||
{% elseif type == 'image' %}
|
||||
<figure id="{{ block.id }}" class="block-image{{ designClasses }}">{% set eager = eagerImage|default(null) == block.id %}{% if props.href|default('') %}<a class="image-link" href="{{ props.href }}">{% endif %}<img src="{{ props.src }}" alt="{{ props.alt }}" width="{{ props.width }}" height="{{ props.height }}" loading="{{ eager ? 'eager' : 'lazy' }}"{{ eager ? ' fetchpriority="high"' : '' }} decoding="async"{% if props.sources|default([]) %} srcset="{% for source in props.sources %}{{ source.src }} {{ source.width }}w{% if not loop.last %}, {% endif %}{% endfor %}" sizes="(max-width: 650px) 100vw, (max-width: 1024px) 50vw, 800px"{% endif %}>{% if props.href|default('') %}</a>{% endif %}{% if props.caption|default('') %}<figcaption>{{ props.caption }}</figcaption>{% endif %}</figure>
|
||||
{# Wie breit das Bild tatsaechlich erscheint. Steht im Block eine feste Breite - ein Logo mit
|
||||
190px, ein Symbol mit 72px -, dann ist das die Antwort, und der Browser laedt die kleine
|
||||
Variante statt der grossen. Ohne feste Breite bleibt es bei der Annahme nach Spaltenbreite. #}
|
||||
{% set festeBreite = block.style.desktop.maxWidth|default('') %}
|
||||
{% set eager = eagerImage|default(null) == block.id %}
|
||||
{# „auto“ heißt: der Browser misst selbst nach, wie breit das Bild tatsächlich erscheint, und
|
||||
wählt genau dazu die Variante. Das geht nur bei verzögert geladenen Bildern - beim
|
||||
vorgezogenen Bild steht die Größe noch nicht fest. Die Angaben dahinter sind der Rückfall
|
||||
für Browser, die „auto“ noch nicht kennen (heute Safari). #}
|
||||
{% set annahme = '(max-width: 650px) 100vw, (max-width: 1024px) 50vw, 800px' %}
|
||||
{% set imageSizes = festeBreite ends with 'px' ? festeBreite : (eager or inHeader|default(false) ? annahme : 'auto, ' ~ annahme) %}
|
||||
<figure id="{{ block.id }}" class="block-image{{ designClasses }}">{% if props.href|default('') %}<a class="image-link" href="{{ props.href }}">{% endif %}<img src="{{ props.src }}" alt="{{ props.alt }}" width="{{ props.width }}" height="{{ props.height }}" loading="{{ eager or inHeader|default(false) ? 'eager' : 'lazy' }}"{{ eager ? ' fetchpriority="high"' : '' }} decoding="async"{% if props.sources|default([]) %} srcset="{% for source in props.sources %}{{ source.src }} {{ source.width }}w{% if not loop.last %}, {% endif %}{% endfor %}" sizes="{{ imageSizes }}"{% endif %}>{% if props.href|default('') %}</a>{% endif %}{% if props.caption|default('') %}<figcaption>{{ props.caption }}</figcaption>{% endif %}</figure>
|
||||
{% elseif type == 'iconcard' %}
|
||||
<div id="{{ block.id }}" class="block-iconcard{{ designClasses }}">
|
||||
{% include 'blocks/icon.html.twig' with {name: props.icon} only %}
|
||||
@@ -45,7 +56,7 @@
|
||||
</figure>
|
||||
{% elseif type == 'logos' %}
|
||||
<ul id="{{ block.id }}" class="block-logos{{ designClasses }}">
|
||||
{% for child in block.children|default([]) %}<li>{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}</li>{% endfor %}
|
||||
{% for child in block.children|default([]) %}<li>{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}</li>{% endfor %}
|
||||
</ul>
|
||||
{% elseif type == 'cta' %}
|
||||
<div id="{{ block.id }}" class="block-cta{{ designClasses }}">
|
||||
@@ -88,7 +99,7 @@
|
||||
{% set section = sections[props.partial]|default(null) %}
|
||||
{% if section %}
|
||||
<div id="{{ block.id }}" class="block-partialref{{ designClasses }}">
|
||||
{% for child in section.blocks %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}{% endfor %}
|
||||
{% for child in section.blocks %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}{% endfor %}
|
||||
</div>
|
||||
{% elseif editing|default(false) %}
|
||||
<p id="{{ block.id }}" class="block-unavailable" role="note">Die verknüpfte Sektion „{{ props.partial }}“ gibt es nicht mehr. Der Verweis bleibt gespeichert.</p>
|
||||
@@ -117,22 +128,22 @@
|
||||
<ul class="tabs-nav">
|
||||
{% for child in block.children|default([]) %}<li><a href="#{{ child.id }}">{{ child.props.title }}</a></li>{% endfor %}
|
||||
</ul>
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}{% endfor %}
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}{% endfor %}
|
||||
</div>
|
||||
{% elseif type == 'tabitem' %}
|
||||
<section id="{{ block.id }}" class="block-tabitem{{ designClasses }}">
|
||||
<h3 class="tabs-heading">{{ props.title }}</h3>
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}{% endfor %}
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}{% endfor %}
|
||||
</section>
|
||||
{% elseif type == 'accordion' %}
|
||||
<div id="{{ block.id }}" class="block-accordion{{ designClasses }}">
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}{% endfor %}
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}{% endfor %}
|
||||
</div>
|
||||
{% elseif type == 'accordionitem' %}
|
||||
<details id="{{ block.id }}" class="block-accordionitem{{ designClasses }}"{% if props.open|default(false) %} open{% endif %}>
|
||||
<summary>{{ props.title }}</summary>
|
||||
<div class="accordion-body">
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}{% endfor %}
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}{% endfor %}
|
||||
</div>
|
||||
</details>
|
||||
{% elseif type == 'icon' %}
|
||||
@@ -161,7 +172,7 @@
|
||||
<div id="{{ block.id }}" class="block-slider{{ designClasses }} slide-desktop-{{ props.desktopVisible }} slide-tablet-{{ props.tabletVisible }} slide-mobile-{{ props.mobileVisible }}{{ props.snap ? ' slider-snap' : '' }}{{ props.dots ?? false ? ' slider-dots' : '' }}"{% if props.autoplay|default(0) >= 3 %} data-autoplay="{{ props.autoplay }}"{% endif %}
|
||||
tabindex="0" role="group" aria-label="Zum Blättern seitwärts scrollen">
|
||||
{% for child in block.children|default([]) %}
|
||||
<div class="slider-slide">{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}</div>
|
||||
<div class="slider-slide">{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% elseif type == 'embed' %}
|
||||
@@ -204,7 +215,7 @@
|
||||
</div>
|
||||
{% elseif type == 'gallery' %}
|
||||
<div id="{{ block.id }}" class="block-gallery{{ designClasses }}" role="group" aria-label="Bildergalerie">
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null)} only %}{% endfor %}
|
||||
{% for child in block.children|default([]) %}{% include 'blocks/block.html.twig' with {block: child, editing: editing|default(false), postLists: postLists|default({}), forms: forms|default({}), breadcrumbs: breadcrumbs|default([]), navigation: navigation|default({}), sections: sections|default({}), richText: richText|default(false), richHeadings: richHeadings|default(false), neighbours: neighbours|default({}), eagerImage: eagerImage|default(null), inHeader: inHeader|default(false)} only %}{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{#
|
||||
|
||||
Reference in new issue
Block a user