AMP & CSS

Since AMP pages are just web pages, styling AMP pages is very similar to normal HTML pages: we need to use CSS! However, AMP imposes certain restrictions on CSS usage. Among them:

  • Only inline styles can be used on AMP pages (i.e. no external stylesheets): generally speaking, custom styles may be added to a document using a single <style amp-custom> tag in the head of the document. 
  • The only exception to inline-only styles is custom fonts 
  • The amount of custom CSS allowed is up to a maximum of 75KBs of CSS per page. 
  • AMP components come with default styles to make authoring responsive pages reasonably easy. These styles are defined in the amp.css.
  • AMP only allows transitions and animations of properties that can be GPU accelerated in common browsers. Currently, these include: opacity, transform and -vendorPrefix-transform
  • The !important qualifier is not allowed because it interferes with AMP static layout system

These restrictions exist for performance and usability:

  • Way too often web pages include one or more external stylesheets, which means that additional HTTP requests are needed to load them with a consequent impact on performance, especially in high-latency scenarios. With AMP, only one request (plus fonts) is needed to load the whole page
  • Way too often sites have huge and complicated CSS stylesheets, causing performance degradation due to CSS processing and execution times

Although AMP restrictions on CSS appear at first as very limiting and difficult to deal with, following good CSS hygiene and best practices gives us enough space to have all CSS we need on a per-page basis.

One of the main challenges we have observed in efforts transitioning sites to full AMP compatibility is dealing with a very large, legacy-ridden, scary CSS burden. Part of the reason for this is that CSS programming often is more an art than programming. Styling is often done via experimentation, as described by Nick Mertens

Try a few things to see the interactions between surrounding elements: change the display type, add/remove some margin, play around with flex, etc. Then you can start honing in on the changes required to get to the end result. Add a class here, create a modifier there, clean up, check again and done.

This makes it easier to add new rules, or change existing ones than to delete them. With time, CSS bloating proliferates.  Also, as sites change, and re-styling efforts happen under pressure, again it is easier to expand the CSS codebase than to maintain only the CSS that is needed. Independently of using AMP or not, we need to get our CSS house in order. If we use AMP, we are forced to maintain CSS tidiness, and that is a good thing. If we don’t use AMP, we need to be self-disciplined (i.e. use performance budgets), and can take a look at AMP CSS practices and restrictions to shed light on areas we need to pay attention to make CSS more efficient in our sites.

The official AMP plugin for WordPress provides a great deal of support for AMP content publishing, and of the main such areas is CSS processing.

Styles Processing #

The AMP plugin functionality related to CSS is integrated into the standard WordPress CSS handling workflows (e.g. enqueuing stylesheets via wp_enqueue_style), and makes it easy to coalesce all the CSS used on a page in the way that is expected by the AMP runtime. In general terms, the AMP plugin does the following tasks:

TaskDescription
GatherCollect all stylesheets from <link> elements, <style> elements, and [style] attributes
Parse– Update CSS selectors pointing to converted elements: e.g. img to amp-img
– Transform !important qualifiers into rules with high-specificity selectors
– Remove disallowed @-rules and CSS properties (e.g. -moz-binding)
– Gather CSS selectors from rules to pass them to tree shaking functionality
Tree-shakeIf the resulting CSS is larger than AMP’s 75KB limit, as CSS tree-shaking algorithm is applied
TruncateIf after tree-shaking there is still more than 75KB, then any stylesheet that takes the total over 75KB will be omitted.
PrioritizeTo mitigate the possible consequences of leaving critical CSS out, the plugin prioritizes the order of styles eligible for removal:

– Parent theme (non-print) stylesheets
– Child theme (non-print) stylesheets
– Core stylesheets used by themes (for blocks)
– Plugin (non-print) stylesheets
– Stylesheets from wp-includes
– Additional CSS from Customizer
– Styles added by blocks and widgets
– Dashicons
– Print stylesheets
– Admin bar CSS
Transient storingParsed styles are minified, serialized, and stored in a transient, which are a simple and standardized way in WordPress for storing cached data in the database, temporarily by giving it a custom name and a timeframe after which it will expire and be deleted
AMP CSSConstruct the style[custom] element to be added to the head

All this functionality allows WordPress developers to use CSS in the standard way they are used to, get a little bit of a break while they get their CSS house in order, and stay on the CSS fast lane once they get there.

CSS Tree-shaking #

One of the challenges developers face when trying to put their CSS house in order is finding out which CSS rules are actually used on any given page. Recent versions of Chrome’s DevTools provide support for assessing CSS code coverage, which is very useful for getting a read of dead CSS rules. The AMP plugin provides support in this are via Tree Shaking functionality: a set of checks and heuristics to eliminate as many CSS rules not used in a given generated AMP page as possible. Some of these checks and heuristics are:

The AMP plugin provides functionality to make it easier to render AMP pages without violating the AMP CSS budget of max 75KB per page.

  • Remove selectors that mention non-existent class names, IDs, elements, or attributes
  • Account for class names from amp-bind expressions in [class] attributes.
  • Account for class names dynamically added by AMP (e.g. amp-viewer, amp-hidden, etc.).
  • Account for selectors for component-specific class names if the corresponding component is present on the document (e.g. amp-carousel-slide).
  • Limit evaluation of selectors to keep runtime performance in check
  • Remove all declaration blocks for which all associated selectors have been removed
  • Remove all @-rule elements for which all of its declaration blocks have been removed

Animations #

In addition to the CSS that can be included in <style amp-custom>, we can also add the <style amp-keyframes> tag, which is allowed specifically for keyframes animations. The CSS in amp-keyframes counts separately from the 50KB limit for amp-custom CSS, and it has a limit of up to Keyframes allows 500KB.

This is great because keyframes rules are often bulky even for moderately complicated animation, and are often the reason why the size limit imposed on <style amp-custom> is exceeded. Putting the keyframes declarations at the bottom of the document in the <style amp-keyframes> makes it possible to exceed size limitations,  and since keyframes are not render-blocking, it also avoids blocking the first contentful paint to parse them.

For more details on CSS animations in AMP check Triggering CSS animations & transitions.

Responsiveness #

AMP provides enhanced responsive design capabilities by introducing features such as placeholders & fallbacks, advanced art direction via srcset and the layout attribute for better control over how page elements display. These capabilities make it very easy to make elements responsive—you just need to add a layout=”responsive” attribute.

Tooling #

As part of the developer tools provided by the plugin (e.g. Validated URL dashboard), you can also get the detailed information regarding the CSS state of any AMP URL.

First, the overall summary of the CSS processing is presented, including:

  • Total CSS before tree-shaking and minification
  • Total CSS after tree-shaking and minification
  • Percentage of the CSS budget consumed
  • Amount of excluded CSS

And then a detailed dissection of the CSS is included on the page and the corresponding attribution to the components responsible for each part of the CSS.

Adding CSS to your AMP URLs #

There are various methods of applying CSS rules to your AMP site. See below instructions based on the mode you have active:

Reader mode (with the legacy reader mode template)

If you’re using the plugin in Reader mode, with the default legacy theme you can apply any CSS changes using your active WordPress themes functions.php file, or preferably using a custom plugin or custom functions plugin. This is to mitigate any theme updates overwriting your Reader mode CSS additions.  

Below is an example of a code snippet containing CSS, which will turn the typical blue header into a green header while changing all h1 tags to green in color.

add_action( 'amp_post_template_css', function() {
      ?>
      /* Put Custom CSS below */
      .amp-wp-title { color:#008000; }
      .amp-wp-header { background-color: #008000; }
      <?php
 } );Code language: PHP (php)

Reader mode (with a selected Reader mode theme)

If you’ve selected one of the additional Reader mode themes other than the legacy theme, you can make any CSS changes using the default WordPress customizer. To ensure you’re making changes to your selected Reader mode theme only, you can click on the “Customize Reader Theme” option from within the AMP plugin settings page, see below:

From there you can apply any CSS changes using the default WordPress customizer. 

Transitional mode 

If you’re using the plugin in Transitional mode great, you’re using your active WordPress themes stylesheets and templates. Any CSS changes made to your theme, via your style.css file, the WordPress customizer, or any other methods also apply to your AMP URLs. 

If you’re looking to apply CSS rules only to your AMP URLs when using transitional mode you can use the [amp] selector. An example is below:

html[amp] h1 { color:#008000; }Code language: CSS (css)

The above ensures all your h1 elements are applied a green color in your AMP URLs only. Your non-AMP h1 elements will not be modified. Another note AMP doesn’t allow CSS style rules that target class names that begin with i-amphtml-.

Standard mode 

As with Transitional mode, when you’re using the plugin in Standard mode your active WordPress themes stylesheets and templates are used for your AMP URLs. You can apply any CSS modifications to your theme as you would normally, via your style.css file, your WordPress customizer, or theme configurations options.