AMP cache adding an external CSS style sheet?

I dug into the AMP Toolbox Optimizer a bit and realized it replaces the boilerplate CSS with an externally referenced file called v0.css and was like 🤔 hmmm, why is that? Here’s a real world example, check for the 2nd request v0.css. So I tried to understand what was going on, if you care, read on.


Initially, the browser doesn’t know what AMP components like <amp-something> are. It only knows after the AMP runtime (and each components’ libraries) is loaded. The problem is, browsers are forgiving, so they just assume unknown tags are there on error, and ignore them:




Note the error? I wrote <dif>, and by that created an unknown tag. The browser will still display my Yeah!, and ignore everything else.

It gets worse when you add AMP, as some AMP components alter the box model of things. You can see the effect in this example file (view source):

​The fake <amp-karussell> I have created simulates this issue. You can’t visually differentiate the two side by side AMP images from my fake carousel.

Adding AMP

The AMP boilerplate essentially makes sure that for a grace period nothing is shown (white screen). You can simulate this by request-blocking the AMP runtime on a real AMP page and you will notice that after the grace period of 8 seconds is over, the layout is messed up, the <div>s form the last example show up as block element, as HTML’s creators wanted them to appear:

Toolbox Optimizations

Now to the actual question, why the CSS file? It’s not the boilerplate, but sort of an AMP CSS Normalizer (more to that in the next section). With the AMP Toolbox, you can simply on your own site already apply the optimizations that the cache would apply on the CDN. I’m quoting directly from the documentation:

“In order to avoid Flash of Unstyled Content (FOUC) and reflows resulting from to the usage of web-components, AMP requires websites to add the amp-boilerplate in the header.

The amp-boilerplate renders the page invisible by changing it’s opacity, while the fonts and the AMP Runtime load. Once the AMP runtime is loaded, it is able to correctly set the sizes of the custom elements and once that happens, the runtimes makes the page visible again.

As a consequence, the first render of the page doesn’t happen until the AMP Runtime is loaded.

To improve this, AMP server-side rendering applies the same rules as the AMP Runtime on the server. This ensures that the reflow will not happen and the AMP boilerplate is no longer needed. The first render no longer depends on the AMP Runtime being loaded, which improves load times.

Caveats: it’s important to note that, even though the text content and layout will show faster, content that depends on the custom AMP elements (eg: any element in the page that starts with ’amp-’) will only be visible after the AMP Runtime is loaded.”

Looking into the CSS File

So now what does the CSS file that I called AMP CSS Normalizer do? If we look at the beautified source code here, we can see this beauty:

.i-amphtml-layout-container,.i-amphtml-layout-fixed-height,.i-amphtml-layout-responsive,[layout=container],[layout=fixed-height][height],[layout=responsive][width][height]:not(.i-amphtml-layout-responsive),[width][height][sizes]:not(.i-amphtml-layout-responsive) {

  display: block;

  position: relative


The toolbox optimizes…

<amp-img width=360 height=200 layout=responsive src=image.png></amp-img>


<amp-img width="360" height="200" layout="responsive" src="image.png" class="i-amphtml-layout-responsive i-amphtml-layout-size-defined" i-amphtml-layout="responsive"></amp-img>

What this means is that when we have a responsive <amp-img> and even if the browser has no clue what an <amp-img> is, it would still display it as a block element.

Styling actually (and maybe surprisingly) still works, even if the browser apart from that ignores the unknown tag:


  beer {

    display: block;

    border: solid red 1px;



Wooohoo, <beer>beer!</beer> Cheers!

This makes sure that the <beer> tag does what I told it to do:


Hope this was helpful.