Avatar

Nǐ hǎo, I'm Julia.

Using AMP Images in NextJS

#nextjs #react

4 min read

AMP - Accelerated Mobile Page

First things first, what is AMP? It stands for Accelerated Mobile Page and is a web component framework that allows us to easily create user-first experiences for the web. It’s an open-source project by Google and Twitter, and was designed to create really fast mobile pages. If you want to read more about it, check out the official website.

How NextJS integrates AMP

NextJS makes it easy to integrate AMP components in your app, with an advanced feature that’s easily configurable. You can set the configuration on a page by page basis, deciding whether you want each particular page to be an AMP-only page (if the page has no NextJS or React client-side runtime) or a hybrid page (where the page will be rendered as traditional HTML by default, but where you can render AMP HTML by adding ?amp=1 to the URL).

If you’re coding up a hybrid page, NextJS provides a nice useAmp hook to allow us to differentiate between the two modes. This allows us to create conditional JSX for instance, whereby if useAmp returns true, we render an AMP component, and a normal HTML element if otherwise. Read more about how to set this up in NextJS here.

amp-img component

The AMP component I want to focus on today is the amp-img component. Images can really add to the feel and messaging of a web page...but at the cost of potentially slowing load times. The other potentially annoying thing is cumulative layout shift as images are loaded and rendered, which Google heavily penalises. AMP images can really help on both of these counts, as it smartly manages image resources during runtime, and additionally, places images in their rightful place to limit layout shift, due to the fact that we need to pass in an image’s explicit size.

If you want to make a hybrid AMP image component in NextJS, it could look something like this.

import React from 'react'
import Image from 'next/image'
import { useAmp } from 'next/amp'

export const ImageWithAmp = ({ src, alt, width, height }) => {
  const isAmp = useAmp()
  return isAmp ? (
    <amp-img src={src} alt={alt} width={width} height={height} layout="responsive" />
  ) : (
    <Image src={src} alt={alt} width={width} height={height} />
  )
}

For the amp-img component, layout="responsive" means that the image will be resized based on the aspect ratio set by the weight and height, in response to the size of the viewport. The height and width figures set here don’t actually determine the size of the image that’s rendered - it’s solely used to determine the aspect ratio when layout="responsive".

Note that amp-img is a block element (vs. a standard HTML img element which is inline), so if you want to set a maximum height (or width) for your image, you’ll need to wrap your amp-img in a container, and set the max-height on that container. Alternatively, you can set display: inline-block directly on your amp-image instead. There are lots of other options, so be sure to read the official docs to see how you might best use this component for your needs.

For the NextJS Image component, the default layout is intrinsic if no value is provided. This setting scales the dimensions of the image down for smaller viewports (where the viewport is smaller than one of the dimensions of your image), but maintains the original dimensions for larger viewports. The official docs has some really nice examples for the different options you have, so be sure to check them out.

Thinking of utilising AMP components? Tell me about what components you’re using it on!

© 2016-2024 Julia Tan · Powered by Next JS.