Mit Accelerated Mobile Pages hat eine inzwischen nur noch lose an Google angekoppelte Stiftung einen Standard verabschiedet, der das Internet deutlich schneller machen soll – vor allen Dingen im mobilen Bereich. Die Einschränkungen im Bereich Layout (u.a. in Bezug auf CSS) sind für Entwickler aber eine gewisse Herausforderung.

Zum Glück gibt es SASS – damit können wir ein bestehendes Layouts für eine „konventionelle“ Site pragmatisch für AMP übernehmen und anpassen, ohne ein komplett eigenständiges AMP-Layout bauen zu müssen.

Dazu muss man wissen, wie AMP dafür sorgt, dass die in AMP geschriebenen Seiten schnell werden:

  • AMP verbietet bestimmte HTML-Tags, die ansonsten Entwickler und Site-Betreiber dazu verleiten, die Seite mit nicht-performanten Code zuzupflastern (u.a. <script>, <iframe>).
  • AMP liefert neue HTML-Tags (in Form von Web Compoments), die immer wiederkehrende HTML-Konstrukte performant und responsiv umsetzen.
  • Nicht zuletzt setzt AMP Größenbeschränkungen durch – unter anderem die Beschränkung von CSS auf 75kB.

Für die Verwendung von AMP gibt es zwei Strategien:

  1. Die eigene Website wird nur noch als AMP-Seiten ausgegeben, oder…
  2. …die reguläre Website erhält ein AMP-Duplikat, d.h. die Inhalte werden gedoppelt, aber einmal in regulärem HTML und einmal in AMP-HTML erzeugt. Beide Varianten verweisen auf einander, so dass Suchmaschinen oder ggf. der Browser entscheiden kann, welche von beiden Varianten angezeigt wird.

Wenn wir uns für die Strategie „AMP-Duplikat“ entscheiden, haben wir auf einmal zwei Template-Sets (reguläres HTML und AMP), und deswegen auch zwei verschiedene Layouts. Natürlich können wir versuchen, auf beiden Seiten auch das selbe Layout zu verwenden – aber wie schaffen wir es, die Größenbeschränkung von AMP einzuhalten, und für die eigenen AMP-Tags eigene Styles zu schreiben, ohne zwei verschiedene CSS-Dateien schreiben zu müssen?

SASS wird uns alle retten

Hier kommt SASS ins Spiel: Mit diesem CSS-Preprocessor können wir nicht nur eine CSS-Datei erzeugen – wir können auch zwei CSS-Dateien erzeugen. Dabei machen wir uns zu nutze, dass SASS jede .scss-Datei ohne _ am Anfang des Dateinamens in eine CSS-Datei kompiliert.

Unser Setup ist also:

  • styles.scss enthält das Layout für die regulären HTML-Seiten, erzeugt styles.css
  • amp.scss enthält das Layout für die AMP-Seiten, erzeugt amp.css

SASS bietet darüber hinaus an, mittels @import den Inhalt anderer SASS-Dateien zu inkludieren. Das machen wir uns im Falle der amp.scss zu nutze:

// amp.scss

@import "styles";

Jetzt wird SASS die amp.scss zu einer amp.css kompilieren, die das selbe Ergebnis hat wie styles.scss bzw. styles.css.

Media Queries für AMP?

Ein Konzept, mit dem jeder CSS-Entwickler vertraut ist, sind Media Queries: Als CSS-Entwickler sperren wir CSS-Regeln in diese Queries ein, um je nach Ausgabegerät bzw. -kanal ein unterschiedliches Layout zu erzwingen.

Genau so denken wir nun AMP-CSS: Wir klammern in unserer SASS-Datei styles.scss nun Blöcke ein, die nicht (oder nur) in der amp.css auftauchen sollen. Dazu schreiben wir uns zwei kleine Mixins:

// styles.scss

$amp: false !default;

// Only output this block in AMP pages.
@mixin amp() {
  @if($amp) {
    @content;
  }
}

// Only output this block in non-AMP pages.
@mixin no-amp() {
  @if(not($amp)) {
    @content;
  }
}

Diese beiden Mixins reagieren auf eine Variable namens $amp. Im oberen Mixin wird der an das Mixin übergebene Inhalt nur ausgegeben, wenn $amp: true ist – im unteren Beispiel wird er nur ausgeben, wenn $amp: false ist.

Davor definieren wir die Variable $amp. Wichtig ist hier die Verwendung von !default. Damit verraten wir SASS, dass der Wert dieser Variable nur false sein soll, wenn $amp nicht bereits vorher gesetzt wurde.

Übrigens können wir die Mixins auch in eine eigene Datei auslagern (zum Beispiel _mixins.scss), das Prinzip bleibt aber das gleiche.

Unsere styles.scss soll nun alle AMP-Regeln nicht ausgeben, und alle Nicht-AMP-Regeln ausgeben. Dementsprechend setzen wir $amp zu false.

Derweil in der amp.scss:

// amp.scss

$amp: true;
@import "styles";

Hier setzen wir also $amp auf true und holen uns danach die Inhalte von styles.scss – hier wird das dort definierte $amp überschrieben, und danach die styles.scss von SASS ganz normal weiter kompiliert. Damit haben wir die selben Inhalte, aber die Mixins werden sich nun genau umgekehrt verhalten.

Media Queries für AMP!

Damit können wir nun alle CSS-Regeln für unsere regulären HTML-Seiten und AMP-Seiten in der style.scss schreiben. An den Stellen, wo eine Unterscheidung zwischen regulären und AMP-CSS notwendig wird, verwenden wir die Mixins:

// styles.scss

// AMP & regular CSS
nav  {
  a {
    color: red;
  }
}

// Hide rule for AMP CSS
@include no-amp() {
  header {
    background-color: black;
    color: white;
  }
}

footer {
  background-color: black;
  color: white;
  // Hide partial rule for AMP CSS
  @include no-amp() {
    font-size: 0.6em;
  }
}

// Hide rule for non-AMP CSS
@include amp() {
  amp-img {
    border: 1px solid red;
  }
}

Damit müssen viele CSS-Regeln nur einmal definiert werden, und werden in beiden Layouts identisch ausgegeben. Dieser Artikel zum Beispiel verwendet im regulären HTML und AMP-HTML weitestgehend identisches CSS, und kann trotzdem auf die Besonderheiten und Kompressionswünsche von AMP eingehen.

Letzter Schritt: amp.css montieren

Das so produzierte amp.css dürft ihr gemäß den Vorschriften von AMP für die Integration von CSS nicht als separates Stylesheet laden. Stattdessen erreicht AMP seine hohe Geschwindigkeit durch die Tatsache, dass das gesamte AMP-CSS in die HTML-Seite eingebunden werden muss. Hier müssen wir also nur eine kleine Template-Anpassung in den AMP-Templates durchführen, die den Inhalt der amp.css im AMP-Tag <style amp-custom> am Beginn einer jeden AMP-Seite montiert.

<!doctype html>
<head>
  …
  <style amp-custom>
    /* Content of amp.css goes here. */
  </style>
  …
</head>

Übrigens empfiehlt es sich spätestens hier, alle überflüssigen Leerzeichen aus der amp.css zu entfernen, um weiter Platz zu sparen. Eine Ersetzung mit einem regulären Ausdruck (wie z.B. /\n\s+/) lässt hier weiter die Luft raus, oder ihr setzt für den SASS-Compiler den Schalter compressed.