— Artikel — № 015

015 —Frontend

Inline CSS en embedded fonts: oude gewoontes die werken

Elf jaar later doet in een WordPress-theme uit 2014 nog precies dat nuttig werk wat we ooit bespotten: inline CSS, self-hosted fonts, kale JavaScript.

Gesloten bordeauxrood leren logboek op donker eiken bureau, rood lint, messing penpunt op verzegelde kaart.
Hero · gestileerd stilleven№ 015

De site is uit 2014. Het bureau dat hem bouwde is jaren geleden opgedoekt. De nieuwe eigenaar betaalt €40 per maand hosting, heeft een principiële hekel aan Webflow, en vroeg ons een cookiebanner toe te voegen zonder iets stuk te maken. Open style.css in het theme en daar staat het: een stylesheet van 2.100 regels, met de hand geschreven, zonder preprocessor, zonder build-stap. Open de header-template en het lettertype komt van /wp-content/themes/dockside/fonts/inter-v3/ met vijf gewichten en een net font-display: swap. Elf jaar later, op een schone Lighthouse-run, scoort deze site 98 op performance.

Niemand heeft dit zo gepland. De developer die het schreef deed gewoon wat in 2014 normaal was. En toch zijn de stukken die slecht verouderd zijn in deze codebase niet de inline CSS of de embedded fonts. Het zijn de jQuery-slider-plugin, de externe CDN die niet meer resolved, en de Google Maps-embed die nu een API-key eist. De saaie onderdelen, de stukken waar we ons toen voor verontschuldigden, doen het zware werk.

De inline-CSS-vuistregel die overleefde

Wie tussen 2008 en 2016 CSS schreef, leerde het buiten HTML te houden. Specificity-oorlogen, separation of concerns, de cascade. Rond 2018 begon een ander argument te winnen: kritieke CSS hoort in <style>-tags in de head, want de browser kan niets renderen voordat die stylesheet binnen is. Tailwind maakte inline classes weer respectabel. Next.js leverde een tijd lang standaard CSS-in-JS. De slinger sloeg door.

Wat niet is veranderd, is de onderliggende fysica. Een round trip om style.css op te halen kost je nog steeds een paint. Een site uit 2014 die zijn layout-kritieke inline CSS in de head zette, al was het per ongeluk, presteert beter dan een site uit 2024 die een Tailwind-bundle van 60 KB van een CDN trekt zonder Cache-Control-header. De developer uit 2014 was niet aan het optimaliseren voor Largest Contentful Paint. Die wist het simpelweg niet beter en had geen zin in Sass. Het resultaat is hetzelfde.

De MDN-referentie voor <style> waarschuwt er nog steeds tegen om de tag voor iets anders te gebruiken dan scoped kritieke CSS. Die waarschuwing is in vijftien jaar niet veranderd. Het advies klopte toen en klopt nu, en de developers die het in de rommelige richting negeerden (alles inline, niets extern) bleken per ongeluk dichter bij de huidige best practice te zitten dan de developers die uitgebreide Sass-pipelines bouwden en daarna lieten verstoffen.

Self-hosted fonts voordat het cool werd

Een lange periode, grofweg 2012 tot 2020, was de standaardzet om fonts vanaf Google Fonts te laden. Eén regel in de head, geen gedoe. Toen kwam de AVG. De uitspraak van het Landgericht München in januari 2022 maakte het expliciet: een Google-gehoste font in de browser van een Duitse bezoeker stuurt zijn IP-adres zonder toestemming naar Google, en dat is een gegevensoverdracht onder artikel 44. Elk Duits bureau ging plots haastig self-hosten.

De verouderde sites waar wij mee werken hadden dat al gedaan. Niet uit privacybewustzijn, maar omdat veel developers in 2014 externe CDN's niet vertrouwden en de fontbestanden gewoon downloadden. Het stukje .htaccess dat ze schreven zag er zo uit:

<FilesMatch "\.(woff|woff2|ttf|eot|otf)$">
    Header set Cache-Control "max-age=31536000, public, immutable"
    Header set Access-Control-Allow-Origin "*"
</FilesMatch>

Dat is in 2026 nog steeds een correcte configuratie. De immutable-directive is uit 2017, dus stond er oorspronkelijk meestal niet, maar de rest is geldig sinds Apache 2.2. De fontbestanden zelf, in /wp-content/themes/<theme>/fonts/, draaien nog steeds zonder privacy-footprint, zonder externe DNS-lookup, en zonder verrassende uitval als Google besluit een gewicht te hernoemen.

Vanilla JS als forward-compatibility-strategie

De andere jaren-2010-gewoonte die goed verouderd is, is kale JavaScript zonder framework. Niet uit deugd, maar bij toeval. Een site die in 2014 jQuery 1.11 gebruikte werkt in 2026 grotendeels nog, omdat de DOM-API opvallend stabiel is gebleven. Een site die in 2014 Angular 1.x, Backbone of Ember draaide is nu onhoudbaar zonder volledige rewrite. Het verschil tussen platform en framework telt hier. Browsers houden zich aan hun oude contracten. Frameworks niet.

Dat zie je het sterkst terug in de kleine interactielaagjes: een mobiele menutoggle, een tab-switcher, een formuliervalidator. Vijf regels addEventListener uit 2015 zijn in 2026 nog steeds vijf regels addEventListener. Vijf regels Backbone-View.extend zijn een archeologische opgraving.

De les is niet "gebruik nooit een framework". De les is dat elke abstractie met een releasecyclus korter dan het hostingcontract van je klant een toekomstig migratieproject is. Het browser-API-oppervlak draait op een andere releasecyclus. Het heeft in tien jaar geen betekenisvolle breaking change gehad.

Wat de jaren-2020-gewoontes verkeerd doen

De standaard-frontend in 2026 ziet er grofweg zo uit: Next.js, Tailwind, een componentenbibliotheek, een headless CMS, Vercel. Een productieve stack voor greenfield werk. Ook een stack met acht bewegende onderdelen, waarvan er zes in de komende 24 maanden een breaking change uitbrengen. Geen van die onderdelen is op zichzelf verkeerd. Het geheel is op een manier fragiel die een WordPress-theme uit 2014 met handgeschreven CSS niet is.

Dit is geen nostalgie. De site uit 2014 heeft zijn eigen problemen: geen strategie voor responsive images, een XSS-gevoelig commentaarformulier, geen CSP-header. Het punt is smaller. De specifieke gewoontes die we destijds bespotten, inline CSS, embedded fonts, kale JS, blijken de lagen die het langst overleefden, omdat ze de onderdelen van het platform raken die het traagst veranderen.

Sta je op het punt zo'n site te herbouwen, dan is de nuttigste vraag niet "welk framework gebruiken we" maar "welke huidige gewoontes van dit ding zijn per ongeluk toekomstvast, en welke braken het eerst". Het antwoord is meestal het tegenovergestelde van wat de oorspronkelijke developer had voorspeld.

Wat dat betekent voor de audit

Toen we Pier bouwden liepen we precies tegen dit patroon aan: bureaus dockten met een WordPress-installatie uit 2014, rekenden op twee dagen CSS-ontwarren, en vonden dat de CSS het schoonste onderdeel van de codebase was. We hebben het uiteindelijk zo opgelost dat elke bestandsbewerking omkeerbaar is via version history, met de MySQL-editor naast de bestandsboom zodat je aan de inline CSS kunt prikken zonder je vast te leggen op een refactor.

Het kleinste wat je vandaag kunt doen: open één verouderde site die je beheert, grep het theme op fonts.gstatic.com, en als je een verwijzing vindt, besluit binnen tien minuten of die blijft staan. De fontbestanden staan vrijwel zeker al op schijf.

— Vragen —

Moet ik inline CSS in een verouderde site principieel refactoren?

Meestal niet. Als het snel rendert en werkt, laat het staan. Refactor als je een concrete reden hebt zoals een redesign of een toegankelijkheidsaudit, niet omdat het patroon oud oogt.

Is self-hosten van fonts in 2026 nog steeds beter dan Google Fonts?

Voor Europees verkeer wel. Self-hosten scheelt een DNS-lookup, geeft je volledige Cache-Control-headers, en houdt je weg bij AVG-risico's. Browsers delen font-caches sowieso niet meer over origins.

Wat is de snelste manier om een verouderd theme te checken op externe calls?

Grep de theme-directory op 'https://' en '//'. De meeste uitgaande calls zijn font-CDN's, analytics en verlaten plugins. Elk daarvan is een toekomstige uitval die staat te wachten.