フレームページをHTML5化する方法

[`evernote` not found]
[`livedoor` not found]
[`yahoo` not found]

普段、残業なんて滅多にしない職場で働いている自分ですが、この2週間ほどは激務でした(どれぐらい激務だったかはいいません。あくまで個人的にそう思っただけで、中にはそんなの激務じゃないと言われそうなレベルの量なので)

それはともかく、その間にやっていた仕事がframesetやframeタグを使っているフレームを利用したHTMLファイルをHTML5化するというもの。しかし、知ってる人も多いと思いますが、framesetやframeタグはHTML5で廃止されてしまっています。とりあえず代替方法としてiframeタグを使うことになったのだけれども(この実装方法に突っ込まないでください。時間がなかったのでこうするしかなかった)、最初、うまい実装方法が思いつきませんでした。しかも、対応ブラウザはIE6以上と言われています(HTML5なのに、IE6以上って………)。

例えば、以下のようなコード。

サンプルページ
ヘッダとして上部に50px、フッタとして下部に70px、そしてメインのページをその間に入れたフレームページです。ヘッダとフッタは問題ありません。問題はメインページです。動的に高さを変更しなければいけないわけですが、うまい方法が思いつきませんでした。

最初はそれぞれのiframeをtable,tr,tdタグで囲って、tableの高さを100%にし、一番上のtrの高さを50px、一番下のtrの高さを70pxにしてみました。一見、うまくいったように思えたのですが、IE10以下でダメでした・・・。

次に考えたほうほうが、#mainをdivタグで囲み、そのdiv(#main_containerとする)をbodyと同じ幅と高さと位置にして、box-sizingをborder-boxにしたうえで、padding-topを50px、padding-bottomを70pxにしたうえで、#mainの高さと横幅を100%にしたらいけるんじゃ・・・なんて思ったけど、よくよく考えるとIE7ではbox-sizing非対応だったのでできません(IE6はもともとbox-sizing:border:box;と指定した時と同じ振る舞いだったはずです)。

困ったなぁ。どうしたらいいんだ・・・。と思いながらふと思いついた。先ほどの#main_containerのtopを50pxにして、bottomを70pxにしたらどうなるんだろう・・・。と。

結果、期待通り、上部に50px、下部に70px空いた要素となりました(てっきり、どっちも指定している場合、どっちかが優先されるもんだと・・・。CSSはある程度わかってきたと思ったんだけどなぁ。CSS界隈では常識だったりするんだろうか?)

というわけで、以下が実装結果。

CSS

HTML

サンプルページ

IE6やIE7ではうまくいかないところもあったので、何度か試行錯誤してどのブラウザでも実装することができました。同じように左・中央・右にわけたフレームページでは下記のようになります。

HTML4

HTML4:サンプルページ

HTML5

HTML5:サンプルページ

応用として、framesetの中にframesetがあるページも下記の通り。
HTML4:サンプルページ
HTML5:サンプルページ

ただし、最後のはIE6でうまく動きませんでした。こういうページの場合は、最初に作ったframe1-html5.htmlの中の#mainのsrc属性を、二つ目に作ったframe2-html5.htmlにするほうがいいかもしれません。

ios8にfloatバグがあるようだからFlexboxで対応してみた

[`evernote` not found]
[`livedoor` not found]
[`yahoo` not found]

先日、1年ほど前に仕事でiPad用に作ったサイトを触っていると、floatを利用した箇所が大きく崩れることがあることが分かった(いつもではないし、崩れ方も異なる)。

確か下記のようなCSSでした。

家に帰って実装してみて試してみると再現されなかったので違うかもしれませんが、とにかく上記のレイアウト指定ならリストは3列の並びになるはずなのに、3つ並んでる行もあれば2つしかない行もあるし1つしかない行もあったわけです。

調べてみたらiOS8のバグのようでした。
参考:iOS8でリストのレイアウトが崩れたら : のり記
参考:W3GさんはTwitterを使っています: “iOS8 SafariのCSSレンダリングが不安定化になるのは特定のJS実行下で発生する模様。pushStateでnth-childが効かなくなると。http://t.co/bO2Kasuyk3 他にもcliclイベント発火でfloatが無効されたりJSとの因果関係で不安定化する”

最初は、『display:inline-block』で対処するか。と思ったのだけど、試してみると全て2行表示になってしまった。inline-blockを指定した要素は改行すると隙間ができてしまうんですよね。対処方法はあるのは知ってるのですが(参考:inline-blockを並べた場合に発生する「隙間」を消去するCSS » INSPIRE TECH)、勉強がてらFlexboxを使ってみることにしました。

例えば先ほどのスタイル指定だと、下記のようにすれば同じレイアウトになります。

ただ、これだとちょっと古いブラウザだとレイアウトが崩れます。そこで、Flexboxの『flex-wrap』が指定してるかどうか調べたうえで、指定できるならFlexboxを、指定できないならfloatを指定することにしました。

CSS

JavaScript(jQuery使用)

実行結果:ios8でのfloatバグ対応

Flexboxは結構前から知ってはいたのですが、実装されてるブラウザも少なく、ころころ仕様も変わるもんだから利用を避けてたのですが、最近になって十分に使えるようになってきたようです(参考:これからのCSSレイアウトはFlexboxで決まり! | Webクリエイターボックス)。いろいろなプロパティがあってややこしいのですが、機会があればまた使ってみようと思います。