Converting Your Primary Theme to AMPHtml

Last updated on
3 March 2021

If you want AMP pages to look like your regular pages, you need to convert a “normal” theme to an AMP theme. A new feature in the 8.3 branch is that your AMP theme does not have to be a sub theme of AMPTheme, it can be a sub theme of your primary theme instead.

Valid AMP requires removing all non-AMP javascript, which means you can’t do this with a javascript-based theme like Bootstrap. This only works if you have a theme that relies on CSS rather than javascript for page enhancements. Flex box and CSS grid are great foundations for an AMP theme.

By subclassing your regular theme and only making changes in the AMP subtheme, you can minimize the differences between a page using your normal theme and the AMP page. The AMPTheme module includes an example of this, Bartik AMP, which is a sub theme of the core Bartik theme.

Refer to the Bartik AMP theme as you read through this guide, which describes the steps involved in creating it. You can then replicate the steps to create a custom sub theme of your own theme.

Info file: bartik_amp.info.yml

Create a new empty theme, call it bartik_amp, and make it a subtheme of your primary theme.

Make the following addition to bartik_amp.info.yml to ensure the theme loads the AMP runtime javascript on every page. This step is required for any AMP theme that doesn't extend another theme that does this.

libraries:
  - amp/runtime

Use libraries-override to remove things we don't want in an AMP theme, all javascript libraries, and as many css files as possible to reduce the overall size of the css. In the Bartik AMP theme you'll see a very very long list of removed libraries and css.

Some of the javascript libraries include both javascript and css. Since the css is related to the javascript that won't be there, it should be safe to remove the whole library.

Removing css is harder when you don't want to remove a whole library. In that case you can identify the individual css files you want to remove by listing them under the name of the library they were added in, and following the file name with : false

A handy way to identify the css files to remove is to use the debug functionality of an AMP page. Go to any AMP page and append &debug#development=1 to the url. That will display a list of the css that has been aggregated into the page, with the size of each file, as well as the total css file size. The goal is to remove any css you won't need on AMP pages to get the total size down to 50,000 bytes or less. Good candidates are css files related to removed javascript, and css that isn't needed on every page and which won't be used on your AMP pages.

Check the bartik_amp.info  file in the Bartik AMP theme for the latest code, but will look something like this:

# Remove unnecessary css files to reduce css size. Css must be <= 50kb.
# Also remove css and js libraries added by contrib modules.
libraries-override:
  # Remove some Bartik css.
  bartik/global-styling:
    css:
      component:
        css/components/form.css: false
        css/components/ui.widget.css: false
        css/components/ui.dialog.css: false
        css/components/ui-dialog.css: false
        css/components/forum.css: false
  # Remove some Classy css.
  classy/base:
    css:
      component:
        css/components/form.css: false
        css/components/tabledrag.css: false
        css/components/tablesort.css: false
        css/components/tableselect.css: false
        css/components/ui-dialog.css: false
  # Remove some system css.
  system/base:
    css:
      component:
        /core/themes/stable/css/system/components/autocomplete-loading.module.css: false
        /core/themes/stable/css/system/components/tabledrag.module.css: false
        /core/themes/stable/css/system/components/tablesort.module.css: false
        /core/themes/stable/css/toolbar/toolbar.module.css: false;
  # Remove all the core libraries that add javascript.
  core/backbone: false
  core/classList: false
  core/ckeditor: false
  core/domready: false
  core/drupal: false
  tracker/history: false
  user/drupal.user: false
  user/drupal.user.permissions: false
  views/views.ajax: false
  views_ui/views_ui.admin: false
  views_ui/views_ui.listing: false
  ...

HTML markup: html.html.twig

Copy your theme's original html.html.twig into the new theme, and make the following changes:

In the head of the template, add amp to the html tag:<html{{ html_attributes }}> becomes <html amp{{ html_attributes }}>

Remove <js-bottom-placeholder token="{{ placeholder_token }}"> from the footer, no footer javascript will be allowed.

Add the following boilerplate code to the head section of the template:

<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>

Theme file: bartik_amp.theme

Create bartik_amp.theme, and add hooks as needed:

We cleaned up most of the libraries in the info file, but there is one javascript file that is added very late that won't be removed. Fix it in the theme. If you have any other stubborn javascript or css files, you can remove them this way.

/**
 * Implements hook_library_info_alter().
 */
function bartik_amp_library_info_alter(&$libraries, $extension) {
  // This library persists even if listed in libraries-override.
  // This code will pull it out for good.
  if ($extension == 'core' && isset($libraries['html5shiv'])) {
    unset($libraries['html5shiv']);
  }

}

If script tags are still present in the document, that means some module is adding them with a different mechanism than normal Drupal libraries, like html_head attachments. In that case, you may want to manually remove those tags:

function my_theme_preprocess_html(&$variables) {
  foreach ($variables['page']['#attached']['html_head'] as $key => $value) {
    // Remove any other scripts that are being attached to the page.
    if ($value[0]['#tag'] == 'script' && (!isset($value[0]['#attributes']['type']) || $value[0]['#attributes']['type'] != 'application/ld+json')) {
      unset($variables['page']['#attached']['html_head'][$key]);
    }
  }
}

Warning: this is not part of bartik_amp, hence the "my_theme" prefix in the code sample; it must be adapted to your particular theme machine name. Also, if using the snippet for adjusting AMP Toolbar classes (see below), make sure to put it all under a single "my_theme_preprocess_html" function.

If you use the core Toolbar module, you should enable the AMP Toolbar module as well. That will move the toolbar into an amp-sidebar and display it vertically. The core module adds classes to the page that assume the toolbar is horizontal, so you can adjust those classes in the theme:

/**
* Implements hook_preprocess_html().
*
* Reset toolbar classes and add sidebar toggle button to the header.
*/
function bartik_amp_preprocess_html(&$variables) {
  // AMP Toolbar wrapped the toolbar in amp-sidebar, which is always
  // vertical. Change the page classes to reflect that.
  // @see toolbar.html.twig.
  if (!empty($variables['page_top']['toolbar'])) {
    if (!empty($variables['attributes']) && $variables['attributes'] instanceof Attribute) {
      $variables['attributes']->removeClass('toolbar-horizontal');
      $variables['attributes']->addClass('toolbar-vertical');
    }
    else {
      $variables['attributes'] = new Attribute($variables['attributes']);
      $variables['attributes']->addClass(['toolbar-tray-open', 'toolbar-vertical', 'toolbar-fixed', 'toolbar-loading']);
    }
  }
}

Templates

There are several core twig templates you'll want to override. The most important is image.html.twig since it will convert all images to use <amp-image></amp-image> instead. Copy templates from AMPTheme or Bartik AMP into your custom theme. If your theme includes any other templates that have invalid markup, create a copy and fix the markup.

If your theme has twig files that attach javascript, create a copy of the template that leaves the javascript out.

System Branding Block

This step is true for all AMP themes. There is a special system branding block that should be used on AMP pages. When configuring the blocks for your AMP theme, be sure to omit the standard system branding block and instead use the special AMP system branding block. The AMP block requires that you identify the width and height of the logo image. Note that AMP logo images should be no wider than 600px and no taller than 60px. The standard system branding block creates invalid AMP markup and you'll see validation errors until you switch it out.

Validate the markup

Enable the new theme in Chrome, and using Chrome developer tools check inspect > console. You should see Powered by AMP ⚡ HTML. That means that Google now knows this is intended to be an AMP page. That does NOT mean that it is valid AMP.

If your page is invalid, you'll see a series of warnings in the console that describe the problems that need to be fixed. There might still be javascript on the page, or the css might be too big, or the page might include invalid elements because you didn't use the AMP formatters. You'll have to step through the problems and fix them until you achieve valid AMP.

Help improve this page

Page status: No known problems

You can: