AMP

AMPHTML 布局系统

概述

布局系统的主要目标是确保 AMP 元素可以合理表达其布局,从而使运行时可以在完成任何远程资源(例如 JavaScript 和数据调用)之前推断元素的大小。这一点很重要,因为这样可以显著减少无意义的呈现和滚动操作。

基于这一点,AMP 布局系统仅支持少量灵活的布局,以确保良好的性能。此系统依赖于一组属性(例如,layoutwidthheightsizesheights)来表达元素对布局和大小的需求。

行为

非容器 AMP 元素(即 layout != container)在未解析/未构建模式下启动,此时,除了占位符外,该元素的所有子级均处于隐藏状态(请参阅 placeholder 属性)。完全构造该元素所需的 JavaScript 和数据负载仍可下载和初始化,但 AMP 运行时已经知道如何仅根据 CSS 类和 layoutwidthheightmedia 属性来确定元素大小和布局。大多数情况下,如果指定了 placeholder,将会调整该属性的大小和位置以占用元素的所有空间。

只要构建元素并完成元素的第一个布局,placeholder 就会处于隐藏状态。此时,元素应当正常构建并定位其所有子级,并且随时可以显示和接受用户输入。这是默认行为。每个元素均可进行重写,以便更快地隐藏 placeholder 或者延长该属性的显示时间。

运行时根据 layoutwidthheightmedia 属性来确定元素大小和显示元素。所有布局规则均通过 CSS 在内部实现。如果元素的大小可以通过 CSS 样式进行推断并且不会随子元素而更改,我们说该元素可“定义大小”,也就是说,该元素立即可供使用或动态插入。但是,这并不意味着该元素的大小无法更改。布局可以完全自适应,就像 responsivefixed-heightfillflex-item 布局一样。简单来说,就是在呈现或滚动期间或者在下载后,如果用户没有给出明确的操作,元素大小不会更改。

如果元素配置错误,则在生产模式下不会对元素进行任何呈现,而在开发模式下,运行时将在错误状态下呈现元素。可能出现的错误包括:layoutwidthheight 属性的值无效或者不受支持。

布局属性

widthheight

根据 layout 属性的值,AMP 组件元素必须具有 widthheight 属性,这两个属性包含整型像素值。布局的实际行为取决于 layout 属性,如下所述。

在少数情况下,如果未指定 widthheight,AMP 运行时可按以下方式为这两个属性设置默认值:

  • amp-pixelwidthheight 的默认值均为 0。
  • amp-audio:根据浏览器推断 widthheight 的默认值。

layout

AMP 提供了一组布局,用于指定 AMP 组件在文档布局中的行为。您可以添加 layout属性并为其指定下表中列出的其中一个值,从而为组件指定布局。

示例:简单的自适应图片,其中宽度和高度用于确定宽高比。

<amp-img
  src="/img/amp.jpg"
  width="1080"
  height="610"
  layout="responsive"
  alt="an image"
></amp-img>

layout 属性支持的值如下所示:

行为和要求
不存在 如果未指定值,则按以下方式推断组件的布局:
  • 如果存在 height,但 width 不存在或者设为 auto,则假定为 fixed-height 布局。
  • 如果 widthheight 均存在,并且还有 sizesheights 属性,则假定为 responsive 布局。
  • 如果 widthheight 均存在,则假定为 fixed 布局。
  • 如果 widthheight 均不存在,则假定为 container 布局。
container 元素允许其子级定义大小,这与常规的 HTML div 非常像。假定组件自身没有特定的布局,而仅仅充当容器;子级会被立即呈现。
fill 元素占用可供自身使用的空间,即宽度和高度。换句话说,fill 元素的布局和大小与其父项一致。对于要填充父容器的元素,可指定“fill”布局,并确保父容器指定 position:relativeposition:absolute
fixed 元素具有固定宽度和高度,不支持自适应。widthheight 属性必须存在。唯一的例外是 amp-pixelamp-audio 组件。
fixed-height 元素占用可供自身使用的空间,但保持高度不变。此布局特别适合 amp-carousel 等元素,这些元素包含水平放置的内容。height 属性必须存在。width 属性不必存在,或者必须设为 auto
flex-item 如果父项为弹性容器(即 display: flex),则元素与其父项中布局类型为 flex-item 的其他元素占用父容器的剩余空间。widthheight 属性不是必需属性。
intrinsic 元素占用可供自身使用的空间,并根据 widthheight 属性给出的宽高比自动重新调整其高度,直到该元素达到传递给 amp-imgwidthheight 属性所定义的元素大小,或者达到 CSS 约束(例如 max-width)。width 和 height 属性必须存在。此布局特别适合大部分 AMP 元素,其中包括 amp-imgamp-carousel 等。可用空间取决于父元素,也可以使用 max-width CSS 进行自定义。此布局与 responsive 布局的不同之处在于,它的高度和宽度是固有的。这在浮动元素内部最为明显,此时,responsive 布局按 0x0 进行呈现,intrinsic 布局将扩展到其自然大小或任何 CSS 约束的较小者。
nodisplay 元素不显示,不占用屏幕上的空间,就像其显示样式设为 none 一样。此布局可应用于所有 AMP 元素。假定元素自身可以在用户操作时显示(例如 amp-lightbox)。widthheight 属性不是必需属性。
responsive 元素占用可供自身使用的空间,并根据 widthheight 属性给出的宽高比自动重新调整其高度。此布局非常适合大部分 AMP 元素,包括 amp-imgamp-video 等。可用空间取决于父元素,也可以使用 max-width CSS 进行自定义。widthheight 属性必须存在。

"layout=responsive" 的元素没有固有大小。元素的大小取决于其容器元素。为了确保 AMP 元素显示,必须为所含元素指定宽度和高度。不要在所含元素上指定 "display:table",因为这会重写 AMP 元素的显示,将 AMP 元素呈现为不可见。

sizes

所有支持 responsive 布局的 AMP 元素均支持 sizes 属性。此属性的值为 img sizes 中所述的 sizes 表达式,但延伸到所有元素,而不仅仅是图片。简而言之,sizes 属性描述的是如何根据媒体条件计算元素的宽度。

如果在指定 sizes 属性的同时也指定了 widthheight,则 layout 将默认为 responsive

示例:使用 sizes 属性

在以下示例中,如果视口比 320px 宽,则图片宽度将为 320px,否则,图片宽度为 100vw(即整个视口宽度)。

<amp-img
  src="https://acme.org/image1.png"
  width="400"
  height="300"
  layout="responsive"
  sizes="(min-width: 320px) 320px, 100vw"
>
</amp-img>

disable-inline-width

sizes 属性本身会在元素上设置内嵌 width 样式。将 disable-inline-widthsizes 配合使用时,AMP 元素会将 sizes 的值传播到元素的基本代码,正如嵌套在 amp-img 内部的 img 一样,它自己在 AMP 中通常不会将内嵌 width 设置为 sizes

示例:使用 disable-inline-width 属性

在以下示例中,<amp-img> 元素的宽度不受影响,sizes 仅用于从 srcset 中选择一个源。

<amp-img
  src="https://acme.org/image1.png"
  width="400"
  height="300"
  layout="responsive"
  sizes="(min-width: 320px) 320px, 100vw"
  disable-inline-width
>
</amp-img>

heights

所有支持 responsive 布局的 AMP 元素均支持 heights 属性。此属性的值是基于媒体表达式的 sizes 表达式,与 img sizes 属性类似,但存在以下两个主要区别:

  1. 它适用于元素的高度,而不是宽度。
  2. 允许使用百分比值,例如 86%。如果使用百分比值,则表示的是元素宽度的百分比。

如果在指定 heights 属性的同时也指定了 widthheight,则 layout 将默认为 responsive

示例:使用 heights 属性

在以下示例中,图片的高度默认为宽度的 80%,但是,如果视口的宽度超过 500px,则高度最大为 200px。因为同时指定了 heights 属性以及 widthheight,布局默认为 responsive

<amp-img
  src="https://acme.org/image1.png"
  width="320"
  height="256"
  heights="(min-width:500px) 200px, 80%"
>
</amp-img>

media

大部分 AMP 元素都支持 media 属性。media 的值为媒体查询。如果查询不一致,则不对元素进行任何呈现,并且不提取元素的资源,可能也不提取其子资源。如果浏览器窗口更改大小或方向,则重新评估媒体查询,是否显示该元素取决于新的评估结果。

示例:使用 media 属性

以下示例有 2 张图片,其中包含相互排斥的媒体查询。根据屏幕宽度,将对其中一张图片进行提取和呈现。media 属性适用于所有 AMP 元素,因此,可用于非图片元素,例如广告。

<amp-img
  media="(min-width: 650px)"
  src="wide.jpg"
  width="466"
  height="355"
  layout="responsive"
></amp-img>
<amp-img
  media="(max-width: 649px)"
  src="narrow.jpg"
  width="527"
  height="193"
  layout="responsive"
></amp-img>

placeholder

placeholder 属性不仅可以在 AMP 元素上设置,还可以在任何元素上设置。placeholder 属性表示,标有此属性的元素充当 AMP 父元素的占位符。如果指定了占位符元素,则占位符元素必须是 AMP 元素的直接子级。默认情况下,AMP 元素的占位符会直接显示,即使尚未下载或初始化 AMP 元素的资源也是如此。准备就绪后,AMP 元素通常会隐藏其占位符,而显示具体内容。占位符的确切行为取决于元素的实现。

<amp-anim src="animated.gif" width="466" height="355" layout="responsive">
  <amp-img placeholder src="preview.png" layout="fill"></amp-img>
</amp-anim>

fallback

fallback 属性不仅可以在 AMP 元素上设置,还可以在任何 HTML 元素上设置。后备是一种惯例,通过该惯例,元素可以告知用户,浏览器不支持该元素。如果指定后备元素,该元素必须是 AMP 元素的直接子级。反馈的确切行为取决于元素的实现。

<amp-anim src="animated.gif" width="466" height="355" layout="responsive">
  <div fallback>Cannot play animated images on this device.</div>
</amp-anim>

noloading

noloading 属性指示是否应为此元素关闭“加载指示器”。许多 AMP 元素在列出时会显示“加载指示器”,这是表示元素尚未完全加载的基本动画。添加此属性后,元素可以选择不采用此行为。

(tl;dr) 布局要求和行为总结

下表列出了 layout 属性可接受的参数、CSS 类和样式。请注意:

  1. 前缀为 -amp- 的所有 CSS 类以及前缀为 i-amp- 的元素分别被视为 AMP 的内部类和内部元素,不允许在用户样式表中使用。在此介绍它们仅供参考。
  2. 即使按照要求在表中指定了 widthheight,默认规则仍适用,这与 amp-pixelamp-audio 相同。
布局 宽度/
高度是否为必需项?
是否定义大小? 是否有其他元素? CSS“显示”
container block
fill 是,父项大小。 block
fixed 是,由 widthheight 指定。 inline-block
fixed-height 只有 height 为必需项;width 可以设为 auto 是,由父容器和 height 指定。 block
flex-item 是,取决于父容器。 block
intrinsic 是,取决于父容器和 width:height 的宽高比。 是,元素为 i-amphtml-sizer block(行为类似于替换的元素)。
nodisplay none
responsive 是,取决于父容器和 width:height 的宽高比。 是,元素为 i-amphtml-sizer block