AMP (Accelerated Mobile Pages) プロジェクト入門:新しいフレームワークとしてのAMP HTMLを用いてWebサイトを制作する

モバイルでのWebページの高速表示を可能にしてくれるGoogleのAMP (Accelerated Mobile Pages)プロジェクト。これはAMP HTMLというオープンソースのフレームワークを用いて実現されます。これまでWebサイトのコーディングといえば、HTMLを書いてCSSを書いて(場合によってはBootstrap等のフレームワークを用いて)、jQueryのプラグインとかを突っ込んで動きをつける、みたいな感じだったと思います。今回はこの新しいフレームワークであるAMP HTMLを、従来のWebサイト制作に置き換えるものにできるのかを試してみました。以下で作ったサンプルは2016年1月1日現在でAMP HTMLのValidatorをパスしていますが、今後の仕様変更によっては書き換えが必要な場合もあるので注意してください。

はじめに

Webサイトといっても必要なものは実はそんなに多くない場合がほとんだと思います。一般的なサイトで必要なものといえば

  • メニューボタンとメニューウィンドウ
  • ファーストビューでの画像のスライドショー
  • バナーなどのカルーセル表示
  • 画像をタップすると拡大表示されるスライドショー
  • 広告表示
  • Google Analytics

くらいじゃないでしょうか。普通はこれらを実現するためにjQueryとそのプラグインをあちこちから探してきてあれこれ詰め込んだり、場合によっては自分でJavaScriptを書いたりする思います。

AMP HTMLではこれらすべての機能を(まだ完全ではないですが)、jQueryだの何だのを入れずに実装することができます(というか jQueryを含むJavaScriptは原則使用禁止になっています )。ということでこれら一つ一つを、AMP HTMLでどのように実装するか見てみます。

サンプルコードはGistにアップロードしています。またyukiyamashina.com/playground/amp.htmlにアクセスすると、サンプルコードが実際にどんな感じになるのかを確認できます。スマホやChromeのDeveloper Tools、SafariのResponsive Design Mode等でみてください。

基本の基本から

まずは基本中の基本、AMP HTMLでのHello Worldです。AMP HTMLのGet Startedに載っているものです。

<!doctype html>
<html ⚡>
  <head>
    <meta charset="utf-8">
    <link rel="canonical" href="hello-world.html" >
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <style>body {opacity: 0}</style><noscript><style>body {opacity: 1}</style></noscript>
    <script async src="https://cdn.ampproject.org/v0.js"></script>
  </head>
  <body>Hello World!</body>
</html>

html要素でいきなり絵文字が出てきてびっくりしますが、<html amp>でもOKです。必要なのは

  • html要素にamp属性、もしくは⚡をつける
  • 非AMPページがある場合はrel-canonicalでそのページを、なければAMPページそのものを指定する
  • CSSを追加で指定する場合はstyle要素でインラインスタイルを当てる
  • https://cdn.ampproject.org/v0.jsを読み込む。これで以下のビルトインのコンポーネントが使えるようになります:
    • amp-ad
    • amp-img
    • amp-pixel
    • amp-video

これが最低限のAMP HTMLファイルです。

メニューボタンとメニューウィンドウ

ではWebページに必要な機能を実装していきます。まずはメニューボタンとメニューウィンドウです。サンプルコードから該当部分を抜き出すとこんな感じです:

...
<script async custom-element="amp-lightbox" src="https://cdn.ampproject.org/v0/amp-lightbox-0.1.js"></script>
...
</head>
<body>
...
 
<button on="tap:open-menu">MENU</button>
 
<amp-lightbox id="open-menu" layout="nodisplay">
    <nav>
        <header>
            <h2>MENU LIST</h2>
        </header>
        <button on="tap:open-menu.close">CLOSE</button>
        <ul>
            <li><a href="#">MENU 1</a></li>
            <li><a href="#">MENU 2</a></li>
            <li><a href="#">MENU 3</a></li>
            <li><a href="#">MENU 4</a></li>
            <li><a href="#">MENU 5</a></li>
            <li><a href="#">MENU 6</a></li>
            <li><a href="#">MENU 7</a></li>
            <li><a href="#">MENU 8</a></li>
        </ul>
    </nav>
</amp-lightbox>

classとか説明に不要なものは省いてあります。

メニューウィンドウにはamp-lightbox要素を使います。これは拡張コンポーネントなのでhead要素内で専用のスクリプトを読み込む必要があります。amp-lightboxはjQueryのlightbox的なものを実装できるもので、amp-lightbox要素の子要素が画面全体を覆い尽くすようになります。このときにトリガーとなるのがon属性を指定した要素で、ここの場合はbutton要素がそれに当たります。on属性の値にはtap:...を指定し、…の部分にはamp-lightboxのid属性の値を入れます。これで『 button要素(メニューボタン)をタップしたら、amp-lightboxの子要素(メニューウィンドウ)が画面一杯に表示される 』ことが可能になります。

また、amp-lightbox内のbutton要素にはon="tap:open-menu.close"が指定されています。ここで、buttonがタップされるとamp-lightboxを閉じてね、というのを設定しています。

実は…

~~現時点ではamp-lightbox内のanchor要素をタップしてもリンクに飛ばずにウィンドウが閉じてしまいます。タップじゃなくてクリックするとちゃんとリンク先に遷移してくれるので、amp-lightboxでのtouchイベントがその辺にまだ対応してないようです。一応AMP HTMLリポジトリのissuesに上げておいたので、今後改善されてちゃんとリンク先にタップで移動できるようになるのを期待しています。~~

【2016年1月10日追記】
#1327でこのバグは無事解決されました。

ファーストビューでの画像のスライドショー

続いてファーストビューでの画像のスライドショーです。

…が、これは普通にCSSでできてしまうのでサンプルコードではCSS Animationを使用しています。興味のある方はstyle要素を見るか、CODEPENを参照してください。

バナーなどのカルーセル表示

次いでバナー等のカルーセル表示です。サンプルコードの該当部分はこんな感じです:

...
<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
...
</head>
<body>
...
 
<amp-carousel width=480 height=160 layout=responsive type=slides autoplay loop>
    <amp-img width=480 height=160 layout=responsive src="#"></amp-img>
    <amp-img width=480 height=160 layout=responsive src="#"></amp-img>
    <amp-img width=480 height=160 layout=responsive src="#"></amp-img>
</amp-carousel>

カルーセルにはamp-carousel要素を使用します。amp-carouselも拡張コンポーネントなので、scriptの読み込みが必要です。amp-carouselにはtype属性があり、これをslidesにすることでスライド式のカルーセルになります。またautoplayやloopといった属性を指定しておくと自動再生&ループさせることができます。

左右のコントロール矢印はデフォルトではvisibility:hiddenになっています。なので矢印を表示させたい場合はCSSでvisibility: visible;を指定する必要があります。

amp-carousel要素とamp-img要素にそれぞれlayout=responsiveが指定されていますが、これをするとwidthとheightで指定した縦横比のままにデバイスの幅にあわせてくれます。layoutは他の値も取れるので(要素によってはどの値をもてるかが決まってたりします)、AMP PROJECTの”How to Control Layout”を見てみてください。

画像をタップすると拡大表示されるスライドショー

画像タップからの拡大表示&スライドショーにはamp-lightboxとamp-carouselを組み合わせて作ります。こんな感じになります:

<amp-img
    on="tap:photogallery" role="button" tabindex="0"
    src="#" alt="image-1"
    width=480 height=480 layout=responsive></amp-img>
<amp-img
    on="tap:photogallery" role="button" tabindex="1"
    src="#" alt="image-2"
    width=480 height=480 layout=responsive></amp-img>
<amp-img
    on="tap:photogallery" role="button" tabindex="2"
    src="#" alt="image-3"
    width=480 height=480 layout=responsive></amp-img>
<amp-img
    on="tap:photogallery" role="button" tabindex="3"
    src="#" alt="image-4"
    width=480 height=480 layout=responsive></amp-img>
<amp-lightbox id="photogallery" layout="nodisplay">
    <amp-carousel width=480 height=480 layout=responsive type=slides loop>
        <amp-img
            src="#" alt="image-1"
            on="tap:photogallery" role="button" tabindex="0"
            width=480 height=480 layout=responsive></amp-img>
        <amp-img
            src="#" alt="image-2"
            on="tap:photogallery" role="button" tabindex="1"
            width=480 height=480 layout=responsive></amp-img>
        <amp-img
            src="#" alt="image-3"
            on="tap:photogallery" role="button" tabindex="2"
            width=480 height=480 layout=responsive></amp-img>
        <amp-img
            src="#" alt="image-4"
            on="tap:photogallery" role="button" tabindex="3"
            width=480 height=480 layout=responsive></amp-img>
    </amp-carousel>
</amp-lightbox>

上の4つがトリガーとなる画像、それらをタップして拡大表示されるものがamp-lightboxの中に入っています。amp-lightboxの中でスライドショーにするためにamp-carouselをさらにいれています。amp-lightboxとamp-carouselについてはそれぞれ上で説明したのでもう大丈夫だと思います。

実際にはamp-lightboxの中のamp-carouselを画面中央に表示させるために、classをつけてCSSを当てています。その辺はサンプルコードをたどってください。

ここでも…

~~現時点ではコントロールの矢印をタップしても画像が切り替わらずにlightboxが閉じてしまいます。クリックイベントだとちゃんと画像が切り替わるので、メニューウィンドウと同様にamp-lightboxのタップイベントの処理の問題かなと思っています。なのでメニューウィンドウの方の問題が解決すれば、こちらも動いてくれると期待してます。~~

【2016年1月10日追記】
メニューウィンドウでのバグと同様に#1327でこのバグは解決済みになってます。

広告表示

さて、広告表示です。Google Adsenseの場合は例えば

<amp-ad width=300 height=250
    type="adsense"
    data-ad-client="ca-pub-7999477986195214"
    data-ad-slot="1761149686"></ins>
</amp-ad>

のようにすることで300×250の広告を表示させることができます。2016年1月1日現在で以下の広告ネットワークに対応しています:

Google Analytics

Google Analyticsについてはamp-analyticsという拡張コンポーネントが作られていますが、

This extension is still a work in progress. Details below can change.

となっているようにまだまだのこれからといった状況のようです。2016年1月1日現在、#development=1をつけて開発モードにしてみると、amp-analytics要素を使用した場合

AMP validation had errors:
http://0.0.0.0:8000/amp.html#development=1:269:4 DISALLOWED_TAG amp-analytics

のようにDISALLOWED_TAGと言われてしまいます。現状はamp-pixelを用いて

<amp-pixel src="https://ssl.google-analytics.com/collect?v=1&tid=UA-XXXXXXXX-Y&t=pageview&cid=$RANDOM&dt=$TITLE&dl=$CANONICAL_URL&z=$RANDOM"></amp-pixel>

のようにすることでカウントできたりしますが、Analyticsはもう少し見守った方が良さそうです。Google Tag Managerもサポートされるとありがたいですが、あれを使うとscriptを入れ放題になることを考えると、あまり期待できないかもしれません。

まとめ

という感じで、まだ完全ではないものの、一般的なサイトはAMP HTMLを使って普通に作れるんじゃないかと思っています。2016年はAMP HTMLという新たなフレームワークを共通で使用することで、未だにjQuery依存症に溢れた人たちを脱皮させて、フレームワークに触れるきっかけを与えれるんじゃないかと期待してます。