Banner-Hintergründe CSP-fest: <img> statt Inline-Variable

Beim ersten Deploy blieben die Slides des Banner-Sliders schwarz. Ursache war
kein fehlendes Bild, sondern die CSP: public/.htaccess setzt
default-src 'self' ohne style-src, der Browser verwirft damit jedes
style-Attribut — und die Komponente lieferte Bild und Akzentfarbe genau so
(style="--banner-bg: url(…); --banner-accent: #6cbbbc"). Lokal war das
unsichtbar, weil php -S keine .htaccess liest.

Der Hintergrund ist jetzt ein <img class="ad-banner__bg"> über die bestehende
img-Komponente (CSP erlaubt img-src) und bringt srcset mit: das Handy lädt die
640er statt der 1600er, die erste Slide lädt eager mit fetchpriority. Der
dunkle Leseverlauf liegt auf ::before statt im background-image.

Die Akzentfarbe kann als beliebiger Hex-Wert nicht ohne Inline-Style in die
Seite. Sie steht deshalb als Token in tokens.css (wo Farben laut CLAUDE.md
hingehören), components.css bildet den Namen darauf ab, und banners.json nennt
nur noch "accent": "breadcrumb".

bin/preflight.php bricht ab, wenn unter app/ wieder ein style-Attribut
auftaucht — der Fehler wäre sonst erneut erst in Produktion sichtbar. Beim
Bauen dieser Wache zweimal selbst hineingetappt: ein Muster mit [^>]* bricht an
jedem schließenden PHP-Tag ab, und die Zeichenfolge dieses Tags beendet den
PHP-Modus auch in einem //-Kommentar (preflight gab ab dort seinen eigenen
Quelltext aus, php -l meldete nichts).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
This commit is contained in:
2026-07-31 16:50:43 +02:00
parent e8296a465b
commit a3cfd4941d
8 changed files with 169 additions and 33 deletions

View File

@@ -2110,21 +2110,49 @@
}
/* Optionaler Hintergrund pro Banner (data: "background").
Dunkler Verlauf über dem Bild hält Text & CTA links lesbar. */
Das Bild ist ein <img class="ad-banner__bg">, KEIN CSS-Hintergrund: die CSP
(default-src 'self', kein style-src) verwirft style-Attribute, eine Inline-Variable
--banner-bg kam auf echtem Apache nie an (31.07.2026, Slides blieben schwarz).
Der dunkle Verlauf, der Text und CTA links lesbar hält, liegt deshalb auf ::before. */
.ad-banner__slide--bg {
background-image:
linear-gradient(to right, rgb(0 0 0 / 0.82), rgb(0 0 0 / 0.45) 60%, rgb(0 0 0 / 0.3)),
var(--banner-bg);
background-size: cover;
background-position: center;
/* Bild an der Innenkante kappen, nicht unter den 1px-Rahmen malen
(sonst schimmert es an der transparenten Rahmenkante durch). */
background-clip: padding-box;
position: relative;
/* Eigener Stapelkontext: das Bild darf hinter den Inhalt, aber nicht hinter
die Slide-Fläche selbst rutschen. */
isolation: isolate;
border-color: transparent;
}
.ad-banner__bg,
.ad-banner__slide--bg::before {
position: absolute;
/* inset bezieht sich auf die Padding-Box — das Bild endet an der Innenkante und
malt nicht unter den 1px-Rahmen (dort schimmerte es sonst durch). */
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.ad-banner__bg {
z-index: -2;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
}
.ad-banner__slide--bg::before {
content: '';
z-index: -1;
background-image: linear-gradient(to right, rgb(0 0 0 / 0.82), rgb(0 0 0 / 0.45) 60%, rgb(0 0 0 / 0.3));
}
/* Pro-Slide-Akzentfarbe (data: "accent") — z. B. Sponsor-CI statt Vereins-Rot.
--banner-accent kommt als Inline-Variable von der Komponente. */
Der Name kommt aus der JSON, die Farbe aus tokens.css: ein Hex-Wert aus der JSON
käme nur per Inline-Style in die Seite, und den verwirft die CSP (siehe oben). */
.ad-banner__slide--accent-breadcrumb {
--banner-accent: var(--clr-banner-accent-breadcrumb);
}
.ad-banner__slide--accent {
--clr-accent: var(--banner-accent);
--clr-accent-dark: color-mix(in srgb, var(--banner-accent) 82%, #000);
@@ -2153,10 +2181,8 @@
@media (max-width: 768px) {
/* Auf Mobil läuft der Verlauf nach unten, damit der gestapelte Text lesbar bleibt. */
.ad-banner__slide--bg {
background-image:
linear-gradient(to bottom, rgb(0 0 0 / 0.82), rgb(0 0 0 / 0.5)),
var(--banner-bg);
.ad-banner__slide--bg::before {
background-image: linear-gradient(to bottom, rgb(0 0 0 / 0.82), rgb(0 0 0 / 0.5));
}
}