Kindle で電子書籍を出してハマった点(HTML, CSS)

公開日:

個人で Kindle の電子書籍を作る機会がありまして、普段ウェブページを作っている経験から HTML5, CSS3 の技術仕様をある程度知っていれば楽勝かと思いきや、思わぬところでハマった部分や分からない部分があったので、備忘録を兼ねて残しておきます。

参照したのはEPUB Packages 3.1(www.w3.org)の仕様とAmazon Kindle パブリッシング・ガイドライン(PDF)(kindlegen.s3.amazonaws.com)の2つです。

用意したファイルは以下の4種類です。

  • OPFファイル(XML)
  • 表紙画像
  • 目次ファイル(XHTML)
  • コンテンツファイル(XHTML, CSS, 画像など)

このうち、表紙画像は画像ファイルを用意してOPFファイルにそのリソース位置を一行記すだけですし、OPFファイルと目次ファイルもEPUB仕様書にコードサンプル付きが書かれているので、とくに難しい点はありませんでした。

以下はコンテンツファイルに関することです。

文字エンコーディング宣言

ウェブページを作る際、HTTPヘッダで

Content-Type: text/html; charset=utf-8

を出力していれば(X)HTML内に文字エンコーディングを記述する必要はありません。これがもっともシンプルかつ確実なわけです。

一方、何らかの事情で(X)HTML内に文字エンコーディングを記述する場合、これは大変複雑です。

まず、(X)HTML内に記述しなければならないケースとして

If an HTML document does not start with a BOM, and its encoding is not explicitly given by Content-Type metadata, and the document is not an iframe srcdoc document,

HTML文書がBOMで開始せず、かつそのエンコーディングが Content-Type メタデータによって明示的に指定されず、かつ文書がiframe srcdoc文書でない場合

という条件があり、その上で

<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<?xml version="1.0" encoding="utf-8"?>

の3種類の書き方があります。

3種類のうち好きな書き方を選んで良いわけではなくて、HTML文書(text/html)かXHTML文書(application/xhtml+xml)かによって効果のある記述が変わってきます。それを把握するには仕様の 4.2.5.4 節以外にも目を通さなければならないですし、また仕様だけでなくブラウザ側の挙動も知っておく必要があり[1]、初心者が使いこなすのは困難でしょう。

電子書籍の場合、複数の(X)HTMLファイルをEPUB形式(Kindleの場合は .mobi または .azk ファイル)に変換してオフラインでも読めるようになりますから、たぶんHTTPヘッダは関係なくて(X)HTMLファイル内の文字エンコーディング宣言を認識するんじゃないかと思います。

その辺の詳しい原理に関する記述は見つけられませんでしたが、Amazonのガイドライン「6.6 サポートされているその他のエンコード」にはこのように書かれています。

HTML のエンコードは、<head>セクション内の<meta>タグまたはXML 宣言を使用して指定することをお勧めします。

方法1:

<html>

<head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

方法2:

<?xml version="1.0" encoding="UTF-8"?>

Kindleの場合、コンテンツのHTMLは text/html 形式で記述しても問題なさそうで、それなら <meta charset="utf-8"> でもいいような気がしますが、まあこのように書かれている以上、 http-equiv 属性かXML宣言のどちらかにしておいた方が良いのかもしれません。

max-width, max-height が使えない

リキッドデザインのページでは、画像に対して

img {
  max-width: 100%;
  height: auto;
  display: inline-block;
}

などと指定して、大きな画像が小さい画面ではみ出ないようにすることがよく行われますが、ガイドライン「16.3.1 無視されるHTML タグ」によると、 Kindle では max-width, max-height は効かないようです。「9.4.3 レスポンシブレイアウトの画像サイズ」では

widthスタイル属性でパーセンテージの値を使用して、ブロック画像とフロート画像をスタイル指定することをお勧めします。これにより、端末の解像度に関係なく、画像が画面の大きさに対して同じパーセンテージで表示されます。

と書かれているので、

<img src="" alt="" style="width: 100%"/>

とするのが良いようです。

で、全幅の画像はこれで良いのですが、困ったケースもあります。

例えば横幅200pxの画像を横並びにしたい場合、本来は以下のように書けば「大きな画面では200pxで表示、スマホ縦のような小さい画面では画面幅の50%で表示」となります。

<style type="text/css">
img {
  max-width: 50%;
  height: auto;
  display: inline-block;
}
</style>
<img src="image1.png" alt="" width="200" height="200"/><!--
--><img src="image2.png" alt="" width="200" height="200"/>

ところが max-width が使えないとなると

<img src="image1.png" alt="" style="width: 50%"/><!--
--><img src="image2.png" alt="" style="width: 50%"/>

とせざるを得ず、この場合大きな画面でも画面幅の50%で表示されますから、画像自体もそれなりに大きなサイズのものを用意しなければなりません。

これは max-width で実装するのと同等の効果を持つ代替策が思いつきませんでしたので、容量増には目をつむって iPad Pro 12.9 インチなど大きなタブレットも想定したサイズの画像を用意することで対処しました。

type="text/css" は必須

スタイルシートを記述する際、 link 要素、style 要素、style 属性のいずれかを使います。

HTML4 時代は style 要素の type 属性が必須(link 要素の方は任意)、また style 属性を使う際は HTTP ヘッダまたは meta 要素でデフォルトスタイルシート言語を指定する必要がありましたが、 HTML5 ではどちらも不要になりました。

ところが、 Kindle においては type 属性を書かないとスタイルシートを認識しないようです。しかもOSによって対応が異なり、 iOS は link 要素、style 要素ともに必須、 Windows, Android は link 要素には必須ですが style 要素は省略しても認識しました。

まあともかく全部書けばいいだけですし、書くことによるデメリットもないので対応は簡単なのですが、なにぶんガイドラインに記述がなかったので、原因を特定するまで時間が掛かってしまいました。

:target 疑似クラス が効かない

EPUBは電子書籍フォーマットだけあって、書籍ならではの表現に特に注意が払われています。

その一つに「脚注」があり、ガイドラインでも 9.3.12 節に「脚注のガイドライン」がサンプルコード付きで書かれています。

aside 要素や epub:type 属性を使うなど、セマンティックを重視した書き方を推奨されており、それはそれでいいのですが、そこまでやるなら脚注にジャンプしたり、脚注から元の場所に戻ったりしたときに :target 疑似クラスを使って背景色を変えるなど強調表示にもこだわりたいところです(Wikipediaがやっているように)。

ところが :target 疑似クラスは認識されないようで、そのようなスタイル付けはできなさそうです。困ったのは、それがガイドラインからは分からないことで、疑似クラスやCSSセレクターなどは一部しか対応可否が書かれていないのです。まあ未記載のものは未対応ということなのかもしれませんが、こういったガイドラインに未記載なものは実際に端末に表示させて対応可否を確認するしかないのでしょうかね。私が電子書籍の制作手法に疎いだけなのかもしれませんが、まるで Firebug すらなかった時代のようなやり方をしていて、もう少しなんとかならないものかなーと思った次第です。

  • [1]例えばテキストブラウザで有名なLynx(lynx.invisible-island.net)が <meta charset=""> に対応したのは2012年2月12日リリースの 2.8.8dev.10 であり、Lynx for Win32(lynx-win32-pata.osdn.jp)が追従した 2.8.9rel.16TH をリリースしたのは2017年9月9日です。メジャーなブラウザではかなり昔から charset 属性を認識しているそうですが、このようなマーナ―ブラウザまで考慮すると、つい最近まで対応していないものが存在し、いやもしかしたら未だ対応していない環境すらあるかもしれません。