X.1 EPUBとCSSレイアウト
注意:この章はまるっと書きかけです。もとい、この文書はCSSレイアウトの確認のために書かれたものです。そのため内容は、不正確なことがあること、EPUBの読書システムでの実機確認はしっかりとは行っていないことに注意してください。
EPUBのレイアウト
EPUB 3.0ではEPUB Content Documentsに規定されているとおり、基本的にはCSSを使ってレイアウトを行います。本章ではCSSによる縦組みレイアウト手法を考えてみます。
ただしEPUB 3.0では、読書システムでのサポートの統一性の観点から、W3Cの最新の仕様をそのまま使えることにはなっていません。また、読書システムで利用したいプロパティを完全にサポートしているとも限りません。そのため、本章で解説したレイアウト手法をEPUB内で利用する場合にはそのことに注意してください。
この章に書くことではないですが、EPUBの制作関連の情報として、日本電子書籍出版社協会の電書協 EPUB 3 制作ガイドやKADOKAWA-EPUB 制作仕様、VivliostyleのEPUBサンプル、アンテナハウスのEPUB関連情報、EPUBに関するブログを書かれている電書魂などが参考になるでしょう。
CSSによる縦書きレイアウト
ブラウザにおける縦組みのレイアウトの考え方については、W3C技術ノートの「Requirements for Japanese Text Layout」(日本語訳:日本語組版処理の要件)がまず参考になります。
また、CSSの仕様書以外では、縦書きWeb普及委員会のWebサイトにある「技術解説」やビヨンド・パースペクティブ・ソリューションズのCSS研究部のサイト、あとはMozilla Developer NetworkのCSSリファレンス(日本語訳のページ)が日本語解説として参考になるでしょう。
X.2 縦書きレイアウトの基礎
CSSによる縦組みは、CSS Writing Modes Level 3が基礎になります。
要素内の文字列を縦書きにするためには、writing-modeプロパティを次のように使います。ただし、IEではGrouping contentとなる要素に指定する必要があるようです(以降、EPUBのレンダリングエンジンとして使われていないIEやEdgeについては触れません)。
-ms-writing-mode: tb-rl; /* for IE. */
-webkit-writing-mode: vertical-rl; /* for safari. */
writing-mode: vertical-rl;
これで半角英数字以外のおおよその文字が正立します。正確にはUnicode® Technical Report #50(UTR50)によって規定されています。ただし現在は、この仕様通りに正立しないことがあり得ることに注意してください。
writing-modeの話に戻ります。この指定をbody要素に指定してもFirefox 44.0では上手くブラウザを操作できなくなります。Safariでも現状高さを指定しておく必要があります。そのため、描画領域を縦書き化するためのCSSは次のようになります。
html {
height: 100%; /* for firefox, safari. */
}
body {
-webkit-writing-mode: vertical-rl; /* for safari. */
writing-mode: vertical-rl;
width: -moz-calc(100vw); /* for firefox. */
height: 100%; /* for firefox, safari. */
}
さらに、Mobile Safari対策のために次のmeta要素を入れるようにしてください(EPUBのHTMLでは不要です)。しかし現状Mobile Safariでは描画時に、縦組みの始まりである右端側にスクロール位置が置かれません。
<meta name="viewport" content="height=device-height, initial-scale=1.0, shrink-to-fit=no">
また、寝ている状態(初期値:mixed)になっている半角文字を正立させたい場合には、text-orientationプロパティにuprightを指定します。逆に日本語等を寝せたい場合にはsidewaysを指定します。
一部の文字だけ縦中横にしたい場合、基本的にはtext-combine-uprightプロパティにallを指定します。ですが、各ブラウザへの実装が目下進められている段階であり、現時点で使用するためにはその指定が煩雑です。
X.3 段落のデザイン
段落本文をデザインするに当たって現状重要になる仕様は、CSS Fonts Module Level 3とCSS Text Module Level 3、CSS Text Decoration Module Level 3です。また、段落のより複雑なレイアウトを制御するために、CSS Inline Layout Module Level 3、CSS Line Grid Module Level 1などがあります。
フォントの指定
ブラウザ上で縦書きを使う場合、WindowsとMac OSの両方にある書体である游明朝、または游ゴシックを指定しておくのが簡単には按配が良くお勧めです。なお、読書システムでは標準の日本語フォントが搭載されていることも多いので、後述のMonospace以外はEPUBで書体を指定しないほうが無難です。
ただし、Firefoxでは縦書きで游書体を指定した際は、日本語と半角の英数字でベースラインのずれが気になるかと思います。そのため英字の書体も合わせて指定してみても良いかもしれません。
ということで、このページでは、次のように指定しています。
@font-face {
font-family: 'Yu Mincho Custom';
src: local('Yu Mincho'), local('YuMincho');
}
@font-face {
font-family: 'Yu Mincho Custom';
src: local('Times New Roman');
unicode-range: U+0-2FF;
}
@font-face {
font-family: 'Yu Gothic Custom';
src: local('Yu Gothic'), local('YuGothic');
}
@font-face {
font-family: 'Yu Gothic Custom';
src: local('Trebuchet MS');
unicode-range: U+0-2FF;
}
p {
font-family: 'Yu Mincho Custom', serif;
}
h1, h2, h3, h4, h5, h6, li, dt, dd, figcaption {
font-family: 'Yu Gothic Custom', sans-serif;
}
なお、OpenTypeフォント自体が持っている情報をCSSで有効化するためには、font-variantプロパティやfont-feature-settingsプロパティなどを使います。仕様書以外に、Adobe Typekitのヘルプセンターに日本語で説明があり、参考になるでしょう。
また、コードのフォントはデフォルトではSafariできれいに表示されません。よって、Safari用に具体的に指定する必要があります。
@font-face {
font-family: 'Vertical Mono';
src: local('Consolas'), local('Menlo'); /* for safari, and adjust windows. */
}
code, samp, var {
font-family: 'Vertical Mono', monospace; /* for sfarii, and adjust windows. */
}
また、iPhone(iOS 9)のMobile Safari上では自動的にフォントサイズに修正が入るため、これを打ち消す必要があります。それらの対応としてこのページでは、次のように指定しています。
body {
-webkit-text-size-adjust: 100%; /* for font size in ios safari. */
}
読書システムでは、Monospaceの書体を包含していないことも多いです。そこで、 Source Han Code JPや、日本語のフォント幅に正確性を求めないのであればOffice Code Proを含めるのが良いでしょう。
段落本文内の英数字
縦書きを想定したHTMLの本文を書くにあたり、本文内の英数字は半角で書いて構いません。また、記号は基本的に全角で書きます。つまり、横書きと同じです。ただし、作品において英数字の文字列が明らかに短いものしか記載しない場合は、英数字を全角で書いてすべて正立させてしまう方針もあるでしょう。
なお、半角スペースが入らない半角文字の文字列は、ブラウザによってはword-break: all;
をかけないと自動的に次行に送られないことに注意してください。通常はそこまで長い文字列は記載されないと考え、例えば次のように設定しておき、都合に合わせてHTML側に<span>タグを入れてもよいでしょう。
/* .url = URL文字列,
:root:lang(en) = 英語文字列 を想定。 */
code, samp, .url, :root:lang(en) {
word-break: break-all;
}
なお、このページではfigcaption要素内で絵文字を連打しているために、Firefoxでは次行に送られないので、あわせてこの指定を行っています。
リンクのデザイン
リンクのデザインは、縦書きの場合、文字列の右側に実線が引かれていることをブラウザに対して勧めています。
なお、Firefox 44ではa要素に対して、text-orientation: sideways;を指定すると実線が引かれなくなってしまいます。
ルビ
ルビを簡単に確認します。ルビのレイアウトはCSS Ruby Layout Module Level 1にて規定されています。ルビのレイアウトにそこまで気を使わない場合には、グループルビとインラインルビを把握していれば十分でしょう。
また、Chrome 49ではfont-feature-settingsプロパティを使うこと(値:ruby)でルビ用字形が有効になるようです(Windowsで確認)。ただし、この指定はブラウザのデフォルトCSSで指定することを勧めていて、CSS作成者が指定すべきではないことに注意してください。
例えば、このページでは次のCSS(以降SCSSの場合もある)を適用してきます。
rt, rtc {
font-variant-east-asian: ruby;
-webkit-font-feature-settings: 'ruby';
font-feature-settings: 'ruby';
}
rtc {
ruby-position: under;
}
@supports not (display: ruby-text-container) { /* for chrome. */
rtc {
&::before {
display: inline;
content: '\FF08';
}
&::after {
display: inline;
content: '\FF09';
}
}
}
@mixin inline-ruby {
display: inline;
font-size: inherit;
white-space: inherit;
text-emphasis: inherit;
font-variant-east-asian: inherit;
-webkit-font-feature-settings: inherit;
font-feature-settings: inherit;
}
.inline-ruby {
@include inline-ruby;
rt, rp, rtc {
@include inline-ruby;
}
}
その結果、次のよう描画されます。最後の「札幌(さっぽろ)」と表示されている箇所がインラインルビです。
先日、イベントに参加するために北海道に行ってきました。雪が今年はあまり降っていないということで大通などの歩道は地面が見えていました。食事については🍣をたくさん食べてきました。鮪やタコ、北寄貝のほか、旬の鰤や真鱈の白子などなど……。その時の写真をこのページに掲載します。
—— 2016年、札幌にて
なお、EPUB内にrtc要素があると、現在のepubcheck 4.0.1での確認がパスできないことに注意してください。
X.4 箇条書きのデザイン
(後で書くかも。)
X.5 表のデザイン
この節では、表のデザインを考えます。
なお、EPUB内で縦組みの複雑なレイアウトを行う場合、display: table;
による指定が現状もっとも安全でしょう。
ここで図版はすべてfigure要素を使います。
px値 | em値 |
---|---|
16px | 1em |
15px | 0.9375em |
14px | 0.875em |
13px | 0.8125em |
12px | 0.75em |
11px | 0.6875em |
10px | 0.625em |
次に、キャプションがある場合を考えてみます。
px値 | em値 |
---|---|
16px | 1em |
15px | 0.9375em |
14px | 0.875em |
13px | 0.8125em |
12px | 0.75em |
11px | 0.6875em |
10px | 0.625em |
次に、表を横書きにしてみます。なお、横書きにする場合、描画領域を超えると問題があります。
px値 | em値 |
---|---|
16px | 1em |
15px | 0.9375em |
14px | 0.875em |
13px | 0.8125em |
12px | 0.75em |
11px | 0.6875em |
10px | 0.625em |
次に、横書きの表にキャプションを加えてみます。
px値 | em値 |
---|---|
16px | 1em |
15px | 0.9375em |
14px | 0.875em |
13px | 0.8125em |
12px | 0.75em |
11px | 0.6875em |
10px | 0.625em |
表が横に長く、セルが多い場合には、画面領域から落ちてしまいます。
px値 | em値 | em値 | em値 | em値 |
---|---|---|---|---|
16px | 1em | 1em | 1em | 1em |
15px | 0.9375em | 0.9375em | 0.9375em | 0.9375em |
14px | 0.875em | 0.875em | 0.875em | 0.875em |
13px | 0.8125em | 0.8125em | 0.8125em | 0.8125em |
12px | 0.75em | 0.75em | 0.75em | 0.75em |
11px | 0.6875em | 0.6875em | 0.6875em | 0.6875em |
10px | 0.625em | 0.625em | 0.625em | 0.625em |
つまり、本文縦組みのスタイルでは、表内の文字組が縦書きでに行(tr要素)が左方向に並んでいく場合、本文のあるhtmlに表を埋め込むのは良いのですが(セルがたくさんあると下に切れますが)、表内が横書きで行(tr要素)が下方向に並んでいく場合、本文に埋め込むのは(右方向にも、下方向にも)非常に気をつけないといけなくなるのが分かります。そのため、表内が横書きなら別htmlするのを基本としても良いでしょう。
X.6 画像のレイアウト
この節では、縦組みレイアウトにおける画像の配置を考えてみます。
ブラウザにおける300dpi相当の画像の配置
まずは、EPUBを考えずにブラウザでの配置を確認します。
ベースCSSとして、img要素に対して次のスタイルがかかっているとします。
img {
max-width: 100vw;
max-height: 100%;
}
300dpi相当の画像を図版として配置する場合、HTMLは次のようになります。
<figure class="bfl image">
<p class="image-img-wrap"><img alt="🍣" src="image/sushi-tuna_96dpi.jpg" srcset="image/sushi-tuna.jpg 3.125x" class="image-img" /></p>
</figure>
class属性について触れておきます。.bflは、画像に限らずfigure要素が使われる図版を設定するためのモジュールを指定します。.imageはfigure要素内に配置されるのが画像の図版であること示すモジュールです。.image-img-warpは画像図版であるimg要素を包含していることを示します。.image-imgは画像図版のimg要素そのものを指します。
CSSは次のように指定します。
.bfl {
margin: 0 1.5em 0 0;
max-height: 100%;
+ * {
margin-right: 1.5em;
}
}
.image-img {
display: block;
}
ここで重要なのは、max-height: 100%;の指定です。これにより、後述のキャプションを画像の下部に配置する場合において、img要素が描画領域の高さを判断できるようになります。img要素をblock化してるのは,余計な余白を描画しないように念のため設定しています(※1)。
すると、次のように配置されます。
これに、キャプションのある場合を考えてみます。HTMLは次のようになります。キャプションを持つことを示すために、figure要素のclass属性にbfl-wfcを加えています。
<figure class="bfl bfl-wfc image">
<p class="image-img-wrap"><img alt="図2" src="image/sushi-tuna_96dpi.jpg" srcset="image/sushi-tuna.jpg 3.125x" class="image-img" /></p>
<figcaption class="bfl-fc"><span class="bfl-fc-title">図<span class="bfl-fc-ordinal">2</span></span> 🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣</figcaption>
</figure>
figcaption要素を持つ場合、img要素のalt属性は図番号のみを入れる形で構いません。
CSSは今回、次のように記述しました。
.bfl-wfc .image-img {
max-width: 75vw;
}
.bfl-fc {
display: block;
font-size: 0.8em;
margin-right: 0.5em;
line-height: 1.5;
text-align: justify;
}
.bfl-fc-title {
font-weight: bold;
margin-bottom: 0.25em;
}
.bfl-fc-ordinal {
@include text-combine-upright-all;
}
ここで重要になるのは、描画領域における画像とキャプションの割合です。画像が大きい場合には、描画領域の横幅75%を上限とし、残りの25%分の横幅分を最低でもキャプションに割り当てるようにしました(以降、キャプションが表示される場合の割合はキャプションが画像下にあっても同じ)。そのため今回の設計では、キャプションが25%以上の横幅を持つと、描画領域からキャプションが落ちることに注意してください。
ちなみに図番号が2桁の場合のには次のように表示されます。
次に、キャプションを画像の下に配置してみます。HTMLは、先のHTMLに対して、figure要素のclass属性にbfl-wfc-wsdを加えます。その際、CSSを上書きする必要性から、bfl-wfcの後にbfl-wfc-wsdを記述してください。
<figure class="bfl bfl-wfc bfl-wfc-wsd image">
<p class="image-img-wrap"><img alt="図3" src="image/sushi-tuna_96dpi.jpg" srcset="image/sushi-tuna.jpg 3.125x" class="image-img" /></p>
<figcaption class="bfl-fc"><span class="bfl-fc-title">図<span class="bfl-fc-ordinal">3</span></span> 🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣🍣</figcaption>
</figure>
そして、CSSは次のように記述します。
@media screen and (min-height: $page-height) {
.bfl-wfc-wsd {
-webkit-writing-mode: horizontal-tb; /* for safari. */
writing-mode: horizontal-tb;
display: table;
border-collapse: collapse;
.image-img-wrap {
display: table-cell;
height: intrinsic;
height: fit-content;
min-width: -moz-calc(16em * 0.8);
}
.image-img {
max-width: 100vw;
max-height: 75%;
max-height: -moz-calc(75vh - 6em - 1em);
margin: 0 auto; /* in case width of caption is longer than image. */
}
.bfl-fc {
display: table-caption;
caption-side: bottom;
min-width: 16em;
margin: 0.35em 0 0;
}
.bfl-fc-title {
margin: 0 0.25em 0 0;
}
}
}
基本的には、CSSで表組しているだけです。画像の高さに対する最大値は、前述していたように、.bflに指定したheight-max: 100%
の指定を明示することで、有効値を計算してくれます。
なお、Firefoxでは縦書きの中で横書きにした場合、その要素は縦書きの親要素の高さを取得できません。ここでは、描画領域の高さをもとに画面領域にはみ出さないように調整しています。また、Firefoxで、かつ画面のピクセル密度が1よりも大きい場合に、.image-img-wrap要素の領域が画像の領域まで収縮できません。そのため、現状その分画像の周りに余白ができてしまいます。
ここで、縦に画像が長い場合も確認してきましょう。
キャプションがない場合は次のとおりです。
キャプションがある場合は次のとおりです。
次に、ページメディアにおいて、ページ内に1つの図版だけ表示したい画像も考えておきます。例えば、キャプションも画像に含まれている場合です。その場合は、figure要素のclass属性にimage-pageを加えておくことにします。
次に、図版に2つの画像が縦に並ぶ場合を考えてみます。
HTMLは、それぞれの画像を、これまでのfigure.image要素のclass属性につけていたclass属性をimage-tandemのみに変えて部品として用意します。そして、それらをdiv.images要素で包含します。さらに、figure.bfl.tandem要素で包含します。
CSSの解説はfigure.image要素で記述した時の応用です。
その結果、次のように表示できます。
縦に長い場合も確認しておきます。画像周りの値を変更したのみです。
これに対して、キャプションがある場合は次のようになります。先のfigure.image要素の場合と同じようにfigcaption要素を加えているので、figure.tandem要素のclass属性にtandem-fcを加えてキャプションがあることをfigure要素側で把握させています。
さらに、キャプションを画像の下に持った例です。
縦に長い場合も確認しておきます。
次に、横に並ぶ場合を考えてみます。横に並ぶ場合は、左から右に並ぶ場合と、その逆が考えられます。まずは、左から右で考えてみましょう。
なお、figure要素のclass属性につけていたimage(tandem)をsidebysideに変えています。
これに対して、キャプションがある場合は次のとおりです。
キャプションがあることをfigure要素が知らないと横幅が画面領域を超えてしまうため、figure要素のclass属性に sidebyside-fcを加えています。
キャプションが下に配置する場合には、次のとおりです。
先と同じく、キャプションがあることをfigure要素が知らないと横幅が画面領域を超えてしまうため、figure要素のclass属性に sidebyside-with-fcを加えています。
次に、横並びで、右から左に並ぶ図版を考えてみます。
figure要素のclass属性につけていたfiugre.sidebyside要素のclass属性にsidebyside-rtlを足します。
なお、directionプロパティを使うと手軽に左右反転できるのですが、EPUBではdirectionプロパティを使えません。
これに対して、キャプションがある場合は次のとおりです。
figure.sidebyside.sidebyside-fc要素のclass属性にsidebyside-rtlを加えています。
キャプションが下に配置する場合には、次のとおりです。
先と同じように、figure.sidebyside.sidebyside-fc.sidebyside-sdl要素のclass属性にsidebyside-rtlを加えています。
EPUBに対応させることを検討する
ここまでの画像配置の手法は、ブラウザでの配置方法です。しかし、EPUBではこのままは上手くいきません。EPUB 3.0ではHTML5の勧告を元にしていますので、現在srcset属性を使うとValidatorが通らないためです。ただし、EPUB 3.1では使えるようになることが予定されています。
そこでこの項では、srcset属性を使わずにHTMLとCSSで図版を配置することを、検討してみます(EPUB対応の結論は次項のSVGラッピングを参照してください)。
- height属性を指定する:しかし横幅が小さいデバイスで見た時に矩形比が保てません。
- image-resolutionプロパティを使う:詳しく見ていませんが、このプロパティを使うことで対応できるようになると思われます。しかし実装されていません。
- zoomプロパティ使う:セレクタでのzoomプロパティの使用は非標準です。特にFirefoxでは利用できません。
- transformプロパティを使う:親ボックスが縮小されず、余白が出てしまいます。
各手法において補足があるとおり、完全な解決策はないのですが、height属性を使うことになるでしょう(特に後述の軽さを求めることも考慮しなければなりませんので)。
srcset属性の以外にも問題があります。
まず、読書システムとしてよく利用されるReadiumやiBooksでは、縦書きの中で横書きを指定していたfigure[class$=sdl]要素において、画像のmax-heightの%指定が有効にならないというバグがあります。これにより、画像が大きいと描画領域から落ちてしまいます。そこで、!importantをつけて強制的にその指定を有効化させる必要があります。
また、Kindleでは現在max-heightなどの最大値/最小値の指定がサポートされていません。そのため、Kindle用のメディアクエリーである@amzn-kf8を使って、これらの処理を迂回させる必要があります。
さらに、前項で解説してきたCSSレイアウトで実装すると、(たぶん)最大値関係のvwの計算と画像の自動縮小処理で、現状のiBooks 4.7(on iOS 9 / iPad Air 1)で図版が数枚あると動作がかなり重くなってしまいます(iPhoneの場合はどうやら処理がある程度パスされること、Kindleではそもそも最大値の計算が効かないので、iPadのみで重くなります。現時点でAndroidのタブレットでは確認していません)。
……ということで、前項の図版のCSSレイアウトは基本的に「とりあえずできた」レベルであって、そのままEPUBに持ち込むことはできない話だったのが分かります。
そこで、描画処理を軽くるするに、図版の画像の大きさを指定しまうことを検討してみます。これによりsrcset属性を使わなくても、画像の大きさがピクセル密度が異なっても同じように表示できるようになるという、もう一つの問題の解決策にもなるからです。しかし、画像の縦と横の長さを両方とも指定するのはあまりお勧めできません。なぜなら読書システムの描画領域の大きさがばらばらだからです。その際、画像の長辺が描画領域よりも画像が大きいと矩形比が保てなくなります。よって、全体が縦書きであれば縦方向を固定するheight属性を、横書きであればwidth属性を指定して、別方向(進行方向)の長さは描画領域の長さに応じて自動的に調整をかけられるようにするのが無難な対応になると考えています。
また、単位vw, vhについては「計算処理のコストが高いと考えられること」「スクロール型の読書システムの場合には画面幅に図版が入りきらなくても大きくは問題にならないこと」を踏まえて%に指定し直します。ただしこの場合、キャプションのみが次ページに表示される問題が発生しえます。これはvwを使って画像自体の最大値を指定してもheight属性のほうが優先されるためです。この問題にはここでは目をつぶります。
この対応策を用いることで、EPUBでの縦書きレイアウトにおける図版画像の配置のHTMLを、以下のように書き直します。CSSは現時点においてはこのページでは先のものと同じスタイルを適用させています。なお、gokko-soup.jpgは300dpiの画像です。
<figure class="bfl image">
<p class="image-img-wrap"><img alt="ごっこ汁" src="image/gokko-soup.jpg" height="230" class="image-img" /></p>
</figure>
キャプションがある場合は次のとおりです(以降、絵文字は適宜JIS2004の範囲内にある文字に置き換えて見てください)。ただし、先述したように、図版画像が描画領域よりも大きい場合、キャプションが別ページに表示されてしまいます。
キャプションが下に配置する場合は次のとおりです。ただしiphoneのibooksでは、図版画像の上下に余白ができてしまったり、図版画像の大きさの割合がやや小さくなったりと問題が多少あります。しかしながら、クリティカルな問題ではないため、現状この形式を使うのが良いでしょう。
SVGラッピングを使った画像の配置
前項の方法はiBooksのみを考えると上手く展開できます。しかしながら、Readiumを考慮すると良くありません。横長の画像の場合に、矩形比を保ったまま画面領域で上手く収まらないからです(iBooksでは読書システムが画像の矩形比をSVG画像のように保たせます)。
そこで、HTMLとCSSのみで解決するのを諦め、画像の配置には、いわゆるSVGラッピングと言われる手法を使うことにします。また、それにより、長さ指定でvw/vhの単位を使ってもiBooksが重くなることがありません(先の記述の何かが良くなかっただけかもしれませんが…)。よって、非常に按配が良いです。
ただし、KindleではSVGラッピングした画像を縮小できません。そこでフォールバックをかけます(svg要素内でフォールバックを記述したかったのですが、epubcheckを上手くパスできませんでした)。
結果、現時点で、Readium、iBooks、Kindleすべてに対応し、手元でのepub→mobi変換が簡易である図版配置の記述は、次のように書けます。
<figure class="image">
<div class="image-svg-wrap">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="276.5px" height="230.4px" viewBox="0 0 276.5 230.4">
<image xlink:href="image/sushi-tuna.jpg" xlink:title="鮨" width="864px" height="720px" transform="scale(0.32)" />
</svg>
</div>
<img src="image/sushi-tuna.jpg" width="277" height="230" hidden="hidden" class="fallback-kf8" />
</figure>
なお、epubcheck時にwaringが表示されますが、それはバグです。
また、区経費を保つために画像の自動縮小が起こりえますが、それの違和感をなくすために、svg要素の背景には薄いグレーを敷くことをお勧めします。

※この項の図版は、CSSを書き加える前の状態です。