Chienomi

SIサイトの細かなモバイル対応

ウェブサイト開発

概要

特にサイトのデザインをいじる気はなかったのだが、 写真を使ったページを縮小した時に画像がはみだしてしまう、という問題があり、 モバイルフレンドリーの観点から修正を実行した。

だが、実際はかなり根が深かった。 結局、PureDocの改修を含む大掛かりな作業になってしまったのだ。

配置方法

私のサイトは見た目はシンプルだが、実際は結構複雑なことをしている。 特にSIサイトに関しては、かなり難しいことを実験している面がある。

SIサイトの難しさは、やはり「レスポンシブデザインで右カラムが上にくる」ということにある。

CSSで指定する場合、左右に並べるのは必ずしも左が先でなくても配置できるが、これを上下にする場合は基本的には「先にくるものが上」になる。 そのため、SIサイトではサイドバーである右カラムがHTML上は「先に」書かれている。

だが、左カラムが先にこない、ということは、左右に並べるために

display: table-cell

が使えないということを意味する。

となると使用できる方法はかなり限られてくるのだが、 しかも高さが一定でない上に、「チェックのボーダー」は親要素の背景になっているため、absolute配置を利用して並べてしまうと、要素の高さが維持されない。 また、両方とも高さが固定でない以上、ネガティブマージンを使う方法も取れない。 floatを使う方法が、事実上唯一だと思われた。

実際に、この問題は試行錯誤の末、既にfloatを使う方法を用いている。 だが、それでもうまくいかない部分があった。

widthとpaddingとmarginの関係

基本的にはwidthをまず確保し、そこにpaddingとborder-widthとmarginを足す。 全体幅を指定したい要素に関しては、それらを0にした入れ子要素を用意するのが無難だ。

しかし、100%の幅を用意したい場合、width: 100%を指定すると、必然的に親ボックスからはみだすことになる。 なぜならば、この時点でコンテンツの幅は親ボックスいっぱいまで確保されていて、その外に足すことになるからだ。

ところが、paddingに相対値を指定すると、paddingはwidthに含まれるのが普通。

つまり、padding: 1em;とした時は、ボックスの外に1emを足すことはしない。 paddingのボックス相対(主に%)を使用する場合、親ボックスはその要素のようだ。 つまり、paddingに25%を指定すると、ボックスの内側50%にコンテンツボックスが生成される。

だが、paddingは相対値は普通にあるが、marginはレイアウトボックスではあまりない。 border-widthに至ってはまずない。

そのために、widthの相対値がとても使いにくい。 UIデザインはスケーラブルな時代になってきているはずなのだが、ウェブの場合、結局スケーラブルな値ではなく、 スタティックなピクセル値を自分で計算して書いて、それに対してスケールするという美しくないことになっている。 しかも、その中にピクセル値に対して曖昧な物理絶対値(特にフォントのポイント指定)を含むのでぐっちゃぐっちゃだ。

結局は全てスタティックなピクセル値に書きなおした。

  • #MainContainerはW850+PAD50+MGNautoで950pxボックス
  • #TopPanはwidth838+border6の850pxボックス。HTMLに直接指定されていたPADは除去。
  • サイズ調整は入れ子のh1要素による指定に変更
  • #LeftPageは590pxでPADauto, MGNは0
  • #SideBarは225pxで左に35pxのMGN。PADは0で、#LeftPageと合わせて850pxボックス
  • つまりカラムの間のボーダーは、サイドバーのMGNが持っている

なぜ画像のmax-widthが効かないのか

厄介なのが画像だ。 画像は既にwidthやheightのボックス相対指定でスケールするようになっている。 一般的にはmax-width: 100%を用いるのだろう。

だが、そもそもの発端はmax-width: 100%が効かない、ということだった。

なぜ効かないのか。実はGeckoでは親要素がピクセル値を持っていなければ画像のwidth/height系プロパティを無視するのだ。 例えば親要素がボックス相対値であっても、その親要素はスタティックなピクセル値ならば問題ない。 例えば幅600pxのボックスに入れ子にされた幅100%のボックスの中であるならば、 画像は600pxに対する幅になる。これは、max-*のプロパティでも効く。

だが、親ボックスがピクセルで固定されたボックスに入れ子にされていても、max-*プロパティで決定されていると効かない。

これがBlinkだと問題ない。例え相対widthの中のmax-widthで決定されたボックスの中であれ、max-width: 100%;を指定すればちゃんと効く。 モバイルでGeckoを使っている人は恐らく少数派なので、あまり問題ない、とも考えられる。

だが、単純なテストを行うと、そのような問題は出ない。 例えば

<html>
<head></head>
<body>
<div style="width: 50%">
<p>
<img src="file:///home/aki/share/pic/vlcsnap-2015-05-12-02h05m49s780.png" style="max-width: 100%;" />
</p>
</div>
</body>
</html>

のようなだ。そこで色々試したのだが、

  • inline-blockの中では画像のwidthは効かない。これはGeckoでは効かないがBlinkでは効く
  • block要素の中ではfloatされている要素は高さを持たないが、inline-blockの中では持つ。これはGecko/Blink共通

ということが分かった。

多分だが、これは明確な仕様にはなっていない。曖昧な部分なのだろう。 仕様に準拠した「論理的な記述」からはかけ離れているが、実際の挙動に合わせて意図した通り動かすため、 #UnderContainerを950pxを超える場合はinline-blockに、950px以下ではblockになるようにした。

その他の修正

Webfontの修正

SIではなくReasonSetのほうで使用しているwebフォントのロゴたいぷゴシックだが、OTFのほうがグリフはかなり多いのだが、かなり空白グリフがある。

空白グリフというのは結構な問題だ。というのは、通常、グリフがない文字についてはフォールバックされ、他の代替フォントを使用して表示する。 そのため「表示されないから読めない」ということは避けられるのだが、空のグリフが存在していると結局空白を表示してしまうため、文字が表示されないため見えない。

空のグリフは削除してしまうのが望ましい。 これを問題にしたのは、「精悍」の「悍」の字が出なかったためだ。

これをcockscombさんのGitHubコード を使用して修正した上で再生成してこの問題を修正した。

PureDocの修正

PureDocのPuredoc::XHTPureDoc.stdメタメソッドがオプショナルなパラメータを正しく解釈しなかったため、修正した。

これはPuredoc::XHTPureDoc.getoptionsメソッドが戻り値をちゃんと指定していなかったためである。

原稿のGitリポジトリ

原稿はCodebreakで草稿も含めて公開しているが、 久しぶりに更新した。若干歴史にも改変を加えたが、ゴミの除去が主だ。

プロフィール

プロフィールに部活の履歴を追加し、 項目としてBiographyを加えた。