“HTML や XML のようなマークアップを発展させ拡張可能な UI を作る技術は、
WPF から Flex まで星の数ほどある。中でも Web Components は XBL という技術を先祖にもっている。
10 年以上前、Mozilla が XUL のお供に作った XML ミタメ定義言語(のようなもの)が XBL だ。
ただ XBL は多機能すぎ、また XML に傾倒しすぎていた。
そこで XBL を簡素化し、10 年来のウェブの変化や JavaScript の隆盛を踏まえ
今風に再発明したものが Web Components である。
API は新しく仕切りなおされたため、先祖の面影を伺うことはほとんどできない。
でも Web Components 関連標準の謝辞は XBL を参照しているし、Shadow DOM のコンセプトも XBL に由来する。”
Posts tagged "html"
“HTMLの進化が1998年に停滞したころ、ブラウザベンダーによって開発されたHTMLのためのAPIの一部がDOM Level 1(1998年)とDOM Level 2 CoreおよびDOM Level 2 HTML(2000年にはじまり2003年に最高潮になる)として規定・発行された。これらの取り組みは2004年に発行されたDOM Level 3仕様とともに次第に弱まっていき、 ワーキンググループはすべてのLevel 3草案を完了する前に閉じてしまった。
2003年に、Webフォームの次世代として位置づけられた技術であるXFormsの公表は、HTMLに代わるものを見つけるよりも、進化するHTML自身に再び関心を巻き起こした。この関心は、Web技術が新しい技術(RSSや後のAtomのような)に限られていたXMLの展開というよりむしろ、実際に展開された技術(HTMLのような)を置き換えるとするところから生まれた。
既存のHTMLウェブページとの非互換なレンダリングエンジンの実装をブラウザに要求することなく、XForms 1.0で導入された多数の特徴を提供することがHTML4のフォームを拡張することで可能であることを示すというコンセプトの証明は、この回帰した関心の最初の結果であった。草案がすでに公に利用可能であって、すべての資源に投入を要請されていた一方、初期の段階では、仕様はOperaソフトウェアの著作権下にあった。
HTMLの進化が再開されるべきであるという意見は2004年のW3Cワークショップで試みられた。ここでHTML5の作業(後述)の基礎となる原則の一部、 前記のフォームに関連した機能をカバーする初期草案の計画と同じく、MozillaとOperaの共同でW3Cに提案された。この計画は以前に選択したWebの進化の方向性と矛盾するものであるとして却下された。代わりに、W3Cスタッフと会員はXMLベースの代替品の開発を継続することを決議した。
その後まもなく、WHATWGと呼ばれる新しい舞台のもとでApple、Mozilla、Operaは共同で作業を継続する意向を発表した。公開メーリングリストが作成され、草案はWHATWGのサイトに移された。その後著作権は3つのベンダー共同が所有するよう修正され、仕様の再利用を可能にした。
WHATWGは複数のコアとなる原則に基づく。特に技術は下位互換性を持つ必要があり、たとえこれが実装よりむしろ仕様が変わることを意味しても仕様と実装は一致する必要があり、仕様は実装が相互にリバースエンジニアリングすることなしに完全な相互運用性を達成可能であることが必要だというものである。
特に後者の要件は、以前にHTML4、XHTML1、 DOM2 HTMLという3つの別な文書で指定された範囲をHTML5仕様が要求した。 それはまた、これまで慣例と考えられていたよりも多くの必要事項を含むことを意味した。
2006年、結局W3CはHTML5の開発に参加することに興味を示し、2007年にHTML5仕様の開発にWHATWGと協力するためのワーキンググループ を設立した。Apple、Mozilla、OperaはW3CにW3Cライセンスのもとで仕様を公開することを許し、WHATWGサイトのバージョンでは制限の少ないライセンスを維持した。
それ以来、両方のグループが一緒に取り組んできた。
”
“当時僕らが公式には “Web Applications 1.0″、裏では “HTML5″ って呼んでた仕様について W3C と共同作業を始めたのは今から数年ほど前 (2007 年頃) だった。僕らは仕様の名前を “HTML5″ と変更し、W3C もそのコピーを公開するようになったんだ。すると程なく、W3C では標準をいくつかの標準に分割したから (つまり、2D Canvas API, Server-Sent イベント、postMessage とかにね)、WHATWG 側でもそれに合わせるよう努力してみたんだ。けれど複数バージョンの仕様があることで混乱し、結局 WHATWG 側では僕が担当するすべてをまとめた、1 つの仕様だけに戻すことにしたんだ。僕らが今 “HTML Living Standard” って呼んでるやつにね。それから数年、この文書と W3C 側のいろんな文書はちょっとずつフォークしていったんだ。WHATWG 標準の冒頭 (訳注: 多分ここのこと) で書いてるようにね。
最近になって、HTML 戦線における W3C と WHATWG の目標もちょっとずれてきた。WHATWG では HTML や関連技術の正確な説明を作り上げることに集中してきた、つまり、バグは見つけたらすぐ [1] 直し、新しい機能は必要になったり使えるようになったら追加し、実装も追いかけてきた。その間 W3C はご立派な W3C 標準化プロセスに従ってスナップショット作りにいそしんできたんだ。そして遂に W3C ワーキンググループの議長達と僕は作業を 2 つに分けることにしたんだ。W3C HTML5, Canvas, Microdata 仕様の執筆に責任を持つ人と WHATWG 仕様のエディタ (僕) は別にしようってね。[2]
”
“これから先に進むため、長期的な計画をどうしていくか、僕はこれからも HTML ワーキンググループの議長達と一緒に決めていく。古い “other Hixie drafts” コンポーネントは無くしたよ。
ここで書いたことは、4月にアナウンスした WHATWG は W3C コミュニティグループ になるって件とは関係ないんだけど、要するに、W3C の HTML ワーキンググループからは独立するけど W3C との協力関係は保たれるってことさ。[4]
最終的な結果としては、HTML Living Standard の策定作業が再び加速され、W3C ワーキンググループと共同作業を始める前のペースを取り戻せることを、僕は期待している。
”
クロスドメインでのリソース読み込みのあれこれメモ。
クロスドメインで何らかのテキストを読み込む方法
- <iframe src=”target”> <frame src=”target”>
- <script src=”target”>
- <link rel=”stylesheet” type=”text/css” href=”target” >
- <object data=”target”> <embed src=”target”>
- XmlHttpRequest Level 2, XDomainRequest
ほかにもありそう。
クロスドメインでのリソースの読み込みに対して影響を与えるHTTPレスポンスヘッダ
- Content-Security-Policy
HTMLに対して指定可能。読み込み可能なリソースの出自を指定可能。XSSを防ぐ。- X-Frame-Options
あらゆるリソースに対して指定可能。iframe,frame,object,applet,embedによる読み込みを拒否。- Access-Control-Allow-Origin
あらゆるリソースに対して指定可能。XHR Lv.2、XDRに対する読み込みを拒否。まとめ
攻撃の対象となるHTMLページを、攻撃者の用意した罠ページからJavaScriptあるいはCSSとして読み込まれるのを防ぐ手段はないので、HTMLをJSあるいはCSSとして読み込むことに成功すれば、HTML内の機密情報を攻撃者は奪取可能。いまのところ、そういうブラウザの致命的なバグが見つかっていない(見つかる都度修正されてる)という、わりと危ういバランスの上に成り立っている。
「Webデザイナーのための jQuery入門」という本を書きました
2011年12月7日発売です。もう本屋に並び始めたみたい。
これは、Webデザイナーとか、HTML+CSSを普段書いてるような人でJavaScriptをほとんど知らないという人がターゲットで、そういった人らがjQuery使ってちょっとしたものを自分で作れるようになれるようになったらええんじゃないかという感じで書かれた本です。ちょっとしたモノっていうのは、この本で解説している、以下のような機能です。
- 画像のロールオーバー
- 入力フォームのガイドテキスト(「検索ワードを入力してください」みたいやつ)
- アコーディオン
- 外部ファイルを読み込んで表作成
- スライドショー
- タブコンテンツ
- ツールチップ
- プラグインの使い方と作り方
僕は他のjQuery解説本はさっぱり読んでいないんですが、自分がこの本を書く上で目指したことは、「この本を読んだ人が、自分で考えてスクリプトを書けるようにこと」です。いけてるサンプル集が欲しいとか、リファレンスが欲しいとかいう人は、この本はそういうものではないので買わないほうがいいですし、既になんかしらのプログラミング言語に長けている人も、他の本の方がいいかと思います。「jQueryを使いながらしっかりプログラミング入門」というのが、イメージに近いものかなと思ってます。というか、そうなったらいいなと思ってます。
使わないと覚えられない
こういう入門書を書いておいて言うのもなんですが、個人的には、「自分でJavaScriptを書かないと覚えられるわけないでしょ」って思ってます。だから、この本を読んでも、自分で書いたりしないと忘れます。確実です。
自分は、この文章を書いている時点で、仕事として6,7年ぐらい、HTML・CSS・JavaScriptを書いており、今はほとんどJavaScriptプログラマーみたいな感じですが、JavaScriptをちゃんとやりだしたのは、jQueryが流行ってみんな使い出したちょっと前という感じです。
プログラミング言語としては、JavaScript、Python、PHPが書けるといえば書けますが、職業プログラマとして通用するのは、JavaScriptだけみたいな感じです。PHPは、3年前に興味があって本を買ってそこそこ勉強しましたが、特に何を作る機会があるわけでも無く、それ以降はwordpressをちょっといじるときに不自由がないぐらいで、まぁ、早い話、忘れてしまっています。Pythonについては、最近、Google App Engineというものを使うためにちょっと勉強したので、触り程度習得していますが、このまま使う機会が他になければ忘れてしまいそうな感じです。そういう経験からといいますか、なんといいますか、要するにそういうプログラミング言語を覚えたかったら使わないと覚えられるわけないじゃーんと思うのです。
ちなみに、自分がこれをやってかなりJavaScriptを覚えたなーと感じているのは、tinyscrollingという、ページをするするスクロールするライブラリをかなりじっくり見てみた時かなーと思ってます。それ以前は他の人が書いたものを全然読もうとしたことがなかったので、苦しみながら一つ一つ調べてよみときつつ、そういう風に書くのかーなどと思ったものでした。一行一行、そこでどういうことをしているのか、わざわざコメントを書いたりもして。あとは、フリーランスをやっているとき、勉強がてら、趣味的に、この本で書いているようなちょっとした機能を沢山つくってみたことが、JavaScript習得のためにかなり役に立ってるかなと思ってます。
JavaScriptは身につけやすいかも
よく、こういう本を買う人の中には、「私もこれを買えばjQuery使えるようになるかしらワクワク」と思う人がいるかと思いますが、きっと、その本がいかに良書で、自分にびっくりするほどフィットして役立ったとしても、仕事や趣味でjQueryを使っていかなければ、さっさと忘れてしまうことでしょう。僕だって仕事でこれだけJavaScript書いていなければ忘れてしまいます当然。
ですが、JavaScriptを使う機会は、最近どんどん増えています。Webサイト上のさまざまな機能が、どんどんJavaScriptを使って作られるようになってきているのは、説明するまでもないでしょう。だから、継続的に使っていけるという意味でも、JavaScriptは覚えやすいものだと思うんです。
それと、仕事をしていて思うのですが、JavaScriptを使った機能は、依頼されることもあるといえばあるのですが、Webデザイナとかコーディングをしている人のほうから提案していくような形で仕事になることも多いのです。そういうのやりたいならそれJavaScriptでこんな感じにできまっせみたいな風に。JavaScriptを普段からやっていれば、UIの引き出しも自分の中に増えるので、そういう提案もできるようになるかもしれないですよ。そうすれば、素敵なUIのサイトも自由に作れるように。ああなんて素敵なんだみたいな。
知識なしでJavaScriptに立ち向かう人たち
Webデザイナーとか、HTMLをやっている人は、仕事上、「こういう機能が無料で使えるようになってるみたいだからこれ使ってみてよ」みたいな風に、なんかしらのライブラリを使うように頼まれ、うんうん唸りながらなんとか実装したみたいな経験がある人がいるんではないかと思います。それで、ちゃんと動かなくて、中身を見てみるもサッパリ分かんねぇ!みたいな状況とか。あとは、ロールオーバーとかタブとか、当たり前のように頼まれたりとか。そういうのは、当たり前に使われるようになってきてはいるものの、JavaScriptを自分で学んでみたことがない人にとっては、その実装は、なかなかハードルの高いことだと思うんです。
世の中には「jQueryプラグイン100選」みたいなブログ記事が山のようにあって、あーなんてjQueryって簡単で素敵なんだ鼻血ブーと思う人もいそうですが、JavaScriptの知識を持たない人がそういうのをちょろっと使ってなにかやっちゃうのは、言ってみれば、「高性能のバズーカを持って戦争に行く」みたいなもんですよ。そのバズーカは高性能だから、ボタン押せばドカンとやっちゃえるかもしれないけど、バズーカに不備があったらどうにもできないし、それって、「使い方はボタン押せば弾でます」みたいなのを知っているだけとかではないですか?そういう状態は、かなり良くない。仕事としても責任感の無いことをしてることになるんじゃないですかね。
そういう状態で思い通りに動かなかったら、超苦しむでしょう大体。でもそれは苦しんで当然なのです。しっかり訓練してからバズーカを打ったほうがいいに決まってます。しっかり訓練といかないまでも、基礎的な体力と知識を付けてから使うべきです。そうすれば、バズーカが動かなかったら何故動かないのかすぐ分かりますし、故障しても自分で直したりできるようになるかもしれないです。
いかに便利な道具があったとしても、知識なしにそれを使うのは、そういうような状態に結構近いもんじゃないかと思ってます。
JavaScriptをどうやって勉強したらいいのか
「よーしではJavaScriptをちゃんと覚えるぞー。どうしたらいいの?」という質問に対する答えは、かなり明確では無いです。この文章の頭のほうで、自分はこのライブラリみて覚えたとか、自分で作ってみて役に立ったとか書きましたけど、そういうモチベーションが高まってるという状況は、人生の中において結構稀だと思います。趣味でJavaScriptを書きだすという人は、変人とまではいきませんけど、滅多にいるわけではないかと思います。
そんな風にJavaScriptを覚えようと思った人が、こういった本を手にとってJavaScriptを勉強しだしても、あっという間に挫折してしまうでしょう。JavaScriptの基本的な文法や機能を一から読んでいっても、それをどうやってつかうのか、さっぱり想像できないんじゃないでしょうか。
ちなみに、他のプログラミング言語を勉強したことのある人であれば、こういった、JavaScriptの文法を一から見ていくという学習方法は、おおいにアリです。プログラミング言語は色々ありますが、基本的な概念は共通なので、文法がわかれば、それをどう使うのか、イメージが頭の中に思い描けたりするのです。だから、その処理の流れを実現するためのコードを書くにはどうするか調べる…みたいな感じです。それがプログラマっていう仕事です。
自分は、JavaScriptからプログラミングを覚えたような感じなので、プログラミングの基礎知識が無い状態からはじめたようなものでした。そんな自分がJavaScriptを覚えていったステップとしては、何かを作りながら、徐々に文法を覚えていったような感じです。仕事柄、ロールオーバーやポップアップをちょっと実装するみたいな機会も多かったりしましたし。こういうふうに、何かを作りながらスキルを伸ばしていくというのは、JavaScriptを覚えるって言うこと以外でも、だいたいそんな感じなのじゃないかなと思います。仕事としてデザインを行うようになり、だんだんとデザインの基礎も勉強するようになったとか、料理を作っていくうちに料理の基礎を覚えたとか。考えてみれば当たり前の話ですが。
この本の構成
この本は、読者が、プログラミングの知識が全く無い状態を考慮して構成されています。これが最適解かはわかりませんが、「よーしではJavaScriptをちゃんと覚えるぞー。どうしたらいいの?」に答えたような本にしたつもりです。最低限必要な概念や知識を説明した上で、実際にサイトで使いそうなものを作っていき、その中でJavaScriptの基礎にも触れながら、jQueryを覚えていけるような流れで書きました。
そして、jQueryの高機能なセレクタや、初心者にとって利用頻度の低い機能については一切解説しないことにしました。その代わり、コードの一行一行がどういう意味を持っているのか、いちいち細かく説明するようにしました。jQueryの機能は非常に多く、便利なものが山盛りですが、それらをすべて把握するよりも、基本的な機能を組み合わせ、やりたいことが実現できる様になったほうが有意義だと考えたので、そのようにしています。自分が初めてtinyscrollingのコードを読んで、一行一行その行がどういう意味なのかを書いてた時のように、一つ一つ意味を解説し、「これはおまじないだ」みたいな説明の仕方をしないように心がけました。
実際にロールオーバーなりタブなりの機能を作ってみる章では、それぞれにつき、基本形と発展形を用意するようにしました。基本形と発展形の動作はほとんど同じですが、「このコードはこういうふうにも書ける」とか、JavaScriptの変数や関数など、基本的な機能を理解してもらうために、このような構成にしています。
というわけで、この本はそんな感じで書かれています。
JavaScriptを覚えたいと思ってる人が読んでくれたらいいかなーと思ってます。
CSSとJavaScriptによって、Webページの中央(水平・垂直方向)に、高さと幅がわからない1つの画像を、ブラウザの表示領域の外にはみ出すことなく配置する、6(+2)つの方法を考えた(Chrome、Firefoxのみ) ~本当の「中央」はどれか?~
最近Tumblrのテーマのカスタマイズを通してHTML、CSS、JavaScriptの扱い方を少しずつ学んでいる。その中で、Tumblrのポストページにおいて画像のみをブラウザの画面の中央に表示したいと考え、その方策について試行錯誤を重ねてきた。
何をしたいのか: Chrome、Firefoxだけでいいので、Webページの中央(水平・垂直方向)に、高さと幅がわからない1つの画像を、ブラウザの表示領域の外にはみ出すことなく配置したい
あくまで個人用のテーマを作っているので、他のユーザーが閲覧することをあまり想定せず、常用しているブラウザ以外のInternet ExplorerやSafari、Operaなどでの動作は考えていない。また、無闇にクロスブラウザを志向して、多くの例外処理を施していくコストはあまりに高くつく。よって、Chrome、Firefoxのみで表示の確認をし、実現できるかどうか調べていくことにした。
画像をWebページの水平方向と垂直方向で中央に表示する事は、最初はCSSのみでできると思っていた。ところが、水平方向での中央表示は、「text-align: center;」や「margin-left: auto;」と「margin-right: auto;」の組み合わせ(あるいは「margin: 0 auto;」)で割と簡単にできても、垂直方向での中央表示がなかなかできなかった。どの方法も画像やブラウザ表示領域のサイズがわかっていないと駄目だったからだ。Tumblrでは様々なサイズの画像が存在するので、事前にサイズを知る事も難しく、予め指定する方法は採用できない。
また、画像をブラウザ表示領域内に収まるように表示する事も同様だった。ちなみに、「画像をブラウザ表示領域内に収まるように表示する」を厳密に言うと、画像のサイズがブラウザ表示領域を超える場合は、領域内に収まるようにリサイズするが、超えない場合は画像本来のサイズで表示するという事だ。つまり、小さい画像を無理やり大きく表示しないという方針になる。これを実現しようとしたところ、Chromeでは「max-height: 100%;」と「max-width: 100%;」の組み合わせでできても、Firefoxではブラウザ表示領域のサイズを直接指定しないと同じ表示にはならない場合があり、このCSSの組み合わせだけではできないことがわかった。
そこでJavaScriptによって、画像やブラウザ表示領域のサイズを取得し、その値とそれを必要とするCSSプロパティと共にstyle要素に追加していくことにした。
このCSSとJavaScriptの組み合わせで色々と調べていくうちに、やりたいことを実現するのに6つぐらいの方法があることがわかったが、調べた限りではこうした方法をまとめたページがなかったので、今回ソースとサンプルページと共にまとめてみた。ただし、まだまだ勉強不足なので、誤って認識している可能性が非常に高く、あくまで個人的なメモという位置付けであることに注意してもらいたい。もちろんこの他により良い方法があるならば是非教えて頂きたいし、間違っているところがあれば適宜指摘してほしい。
HTMLは簡略化のため、HTML5の表記を用いている。また、CSSの追加にはinsertRuleの使用で統一している。これは「これでできる! クロスブラウザJavaScript入門:第20回 JavaScriptによるスタイルの操作|gihyo.jp … 技術評論社」を参考にした。
前述の通り、クロスブラウザ、クロスプラットフォームは考慮していない。Windows XPにおけるChrome 8.0.552.224、Firefox 3.6.13上のみで最終確認をしている。
1. ブラウザ表示領域の高さから、画像がブラウザ上で表示される時の高さ(つまり画像本来のものではない)をマイナスし、それの半分を余白として画像の上に置く
<!doctype html>
<meta charset=utf-8>
<title>Case 1</title>
<style>
body {
margin: 0;
}
img {
display: block;
margin-left: auto;
margin-right: auto;
}
</style>
<img src=http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png>
<script>
var h = window.innerHeight, s = document.styleSheets[0];
s.insertRule('img{max-height:' + h + 'px;max-width:' + window.innerWidth + 'px;}', s.cssRules.length);
window.onload = function() {
s.insertRule('img{margin-top:' + ((h - document.images[0].height) / 2) + 'px;}', s.cssRules.length);
};
</script>
CSSに関しては、body要素に「margin: 0;」の指定をしているのはUser Agentに設定されているデフォルトスタイルシートを無効にするため。また、わざわざimg要素に「display: block;」を指定しているのは、何故かinline要素の状態だと7pxほど下に余白が付いてしまうので、block要素にしてその余白を消すため。
11/02/11追記: 余白ができる理由については、以下が参考になった。
なぜ、少し隙間ができるかというとテキストの表示がベースラインとなっているので(デフォルト)、ディセンダ(文字が下に少しはみ出る分)の領域が空いてしまっている。
そのため、vertical-alignをtext-bottomに合わせることでimgの隙間もなくなる。
これはインライン要素に対して起こる事なのでdisplay:blockなどでブロック要素にすることでも回避できる。
Chapter 4 トラブルシューティング編 - prog*sig


黒の画像と白の背景の境にある薄水色の部分が余白。「vertical-align: middle;」などの指定でも消えるようだ。
しかし、img要素の親要素が、href属性が設定されたa要素だと、画面全体がリンクとしてクリックできるようになってしまうという問題があるようだ。
JavaScriptに関しては、document.documentElement.clientHeightとdocument.documentElement.clientWidthではなく、window.innerHeightとwindow.innerWidthを使用しているのは、画像をブラウザ表示領域内に必ず収める事を目的としているため、ページが画面外にはみ出す場合を想定する必要がなく、スクロールバーのないブラウザ表示領域のサイズの取得で問題ないからだ。また、画像がブラウザ上で表示される時の高さが必要であるため、画像本来の高さを表すnaturalHeightではなくheightを使用している。
画像の表示の処理が遅いと、画像が一旦画面の一番上に表示されてから中央に表示されるように見える事がある。
2. 画像を本来表示される位置から、ブラウザ表示領域の高さと幅のそれぞれ半分ずつ右方向と下方向に移動させ、画像がブラウザ上で表示されるときの高さと幅のそれぞれ半分ずつ左と上の余白を詰める
<!doctype html>
<meta charset=utf-8>
<title>Case 2</title>
<style>
body {
margin: 0;
}
img {
position: relative;
top: 50%;
left: 50%;
}
</style>
<img src=http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png>
<script>
var h = window.innerHeight, w = window.innerWidth, s = document.styleSheets[0];
s.insertRule('body{height:' + h + 'px;width:' + w + 'px;}', s.cssRules.length);
s.insertRule('img{max-height:' + h + 'px;max-width:' + w + 'px;}', s.cssRules.length);
window.onload = function() {
s.insertRule('img{margin-top:-' + (document.images[0].height / 2) + 'px;margin-left:-' + (document.images[0].width / 2) + 'px;}', s.cssRules.length);
};
</script>
「CSSで上下左右中央に画像を配置する」を元にしている。「CSSで画面全体に対して天地中央に配置するテクニック(1) | 先端研究ブレイドLAB」も参考になる。
画像の表示の処理が遅いと、画像が一旦画面の右下に表示されてから中央に表示されるように見える事がある。
3. body要素を本来表示される位置から、ブラウザ表示領域の高さと幅のそれぞれ半分ずつ右方向と下方向に移動させ、画像をブラウザ上で表示される時の高さと幅のそれぞれ半分ずつを、body要素の位置を基準にして左方向と上方向に移動させる
<!doctype html>
<meta charset=utf-8>
<title>Case 3</title>
<style>
body {
position: fixed;
top: 50%;
left: 50%;
margin: 0;
}
img {
position: relative;
}
</style>
<img src=http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png>
<script>
var s = document.styleSheets[0];
s.insertRule('img{max-height:' + window.innerHeight + 'px;max-width:' + window.innerWidth + 'px;}', s.cssRules.length);
window.onload = function() {
s.insertRule('img{top:-' + (document.images[0].height / 2) + 'px;left:-' + (document.images[0].width / 2) + 'px;}', s.cssRules.length);
};
</script>
「これでできる! クロスブラウザJavaScript入門:第20回 JavaScriptによるスタイルの操作|gihyo.jp … 技術評論社」を元にしている。
6つの方法の中で唯一、ブラウザの画面サイズを変えても画像が中央に表示されるようになっている。
また、2と同じく画像の表示の処理が遅いと、画像が一旦画面の右下に表示されてから中央に表示されるように見える事がある。
4. 画像を背景に設定し、「background-position: center;」によって水平方向と垂直方向で中央に表示し、画像のサイズがブラウザ表示領域を超える時は「background-size: contain;」を指定して領域内に収める
<!doctype html>
<meta charset=utf-8>
<title>Case 4</title>
<style>
body {
margin: 0;
background-position: center;
background-repeat: no-repeat;
}
</style>
<script>
var h = window.innerHeight, i = new Image(), s = document.styleSheets[0];
i.src = 'http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png';
i.onload = function() {
s.insertRule('body{background-image:url(' + i.src + ');' + ((h < i.height || window.innerWidth < i.width) ? '-moz-background-size:contain;background-size:contain;' : '') + 'height:' + h + 'px;}', s.cssRules.length);
};
</script>
img要素を用いない方法。1~3では画像をブラウザ表示領域内に収めるのにmax-height、max-widthを指定していたが、背景画像の場合は「background-size: contain;」を指定する。ただし、画像がブラウザ表示領域内に収まるサイズのときは、ブラウザ表示領域いっぱいまで拡大して表示されてしまうので条件分岐が必要だった。ちなみに、背景画像を指定している時はbody要素に幅の指定をする必要はないようだった。
ところで、1~4の場合、「画像がブラウザ上で表示される時のサイズ」を取得するには画像の読み込みが完了していて、且つ画像がブラウザ上で描画されている事が条件になる。後者は、例えばimg要素に「display: none;」や「opacity: 0;」を指定していたら取得できないという事だ。よって、画像の読み込み完了を待つ時間がどうしても必要となり、画像を素早く快適に閲覧していく事ができなくなる。特に画像のファイルサイズが大きかったり、画像の読み込み速度が遅い環境だと、ページの表示に関して、重大なスタイルの崩れや遅延を引き起こしかねないと考えられる。特に4は画像の読み込みが完了してから初めて画面上に現れるようになっているので、注意が必要になる。
5. body要素に「display: table-cell;」と「vertical-align: middle;」を指定して垂直方向での中央表示を行う
<!doctype html>
<meta charset=utf-8>
<title>Case 5</title>
<style>
body {
display: table-cell;
vertical-align: middle;
}
img {
display: block;
margin-left: auto;
margin-right: auto;
}
</style>
<img src=http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png>
<script>
var h = window.innerHeight, w = window.innerWidth, s = document.styleSheets[0];
s.insertRule('body{height:' + h + 'px;width:' + w + 'px;}', s.cssRules.length);
s.insertRule('img{max-height:' + h + 'px;max-width:' + w + 'px;}', s.cssRules.length);
</script>
「異なるサイズの画像を縦横中央配置にしてリスト状に並べる | CSS-EBLOG」を元にした。
table-cell要素では余白の指定は適用されないので、「margin: 0;」の指定は必要ない。
11/01/17追記
5.1. 5に加えてhtml要素に「display: table;」を、html要素とbody要素両方に「height: 100%;」、「width: 100%;」を指定する。
<!doctype html>
<meta charset=utf-8>
<title>Case 5.1</title>
<style>
html, body {
height: 100%;
width: 100%;
}
html {
display: table;
}
body {
display: table-cell;
vertical-align: middle;
}
img {
display: block;
margin-left: auto;
margin-right: auto;
}
</style>
<img src=http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png>
<script>
var s = document.styleSheets[0];
s.insertRule('img{max-height:' + window.innerHeight + 'px;max-width:' + window.innerWidth + 'px;}', s.cssRules.length);
</script>
「hail2u.net - Weblog - 横スクロールのサイトデザイン」を参考にした。
後述の6と比べてCSSの記述は多いものの、JavaScriptへの依存が小さくなっている。なお、この方法は、不可解なことに後述の7のようにChromeではCSSのみで表すことができない。「max-height: 100%;」と「max-width: 100%;」の組み合わせでは、正常に画像をブラウザ表示領域内に収めることができない場合があるようだ。
6. body要素に「text-align: center;」で水平方向での中央表示、img要素に「vertical-align: middle;」で垂直方向での中央表示をし、body要素にブラウザ表示領域の高さをline-heightに指定する
<!doctype html>
<meta charset=utf-8>
<title>Case 6</title>
<style>
body {
margin: 0;
text-align: center;
}
img {
vertical-align: middle;
}
</style>
<img src=http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png>
<script>
var h = window.innerHeight, s = document.styleSheets[0];
s.insertRule('body{line-height:' + (h - 2) + 'px;}', s.cssRules.length);
s.insertRule('img{max-height:' + h + 'px;max-width:' + window.innerWidth + 'px;}', s.cssRules.length);
</script>
「vertical-alignの説明-CSS TIPS」を参考にした。
1~5と比べると、CSSでは一番わかりやすく簡潔な形。ただし、何らかの文字があると、その文字にもブラウザ表示領域の高さが付いてしまう。また、line-heightに指定したブラウザ表示領域の高さから2をマイナスしているのは、何故か画像の表示が領域内に僅かに収まらない場合があるため。とてもスマートな形とは言えないが…。
以前は5に「display: block;」を適用せずに邪魔な余白を受け入れて画像の上側に7pxほどの余白を付け、その分画像の最大サイズを削っていく方法を採用していたのだが、これでは画像を最大限に表示することができなかった。それから色々と調査、比較を行った結果、今のところ6が一番シンプルなので、使い方に注意しつつテーマに採用している。
その他: ブラウザには「中央」を表す位置が複数ある?
11/01/09追記: Firefoxでの確認を怠っていた。以下はChromeで起こる現象で、Firefoxでは1~5は同じ表示のようだが、6のみ画像が数px上側に表示された。
上記6つの方法を比較すると、画像の中央表示に僅かな差異がある事が確認できた。画面サイズを変えていくつかの場合を見ると、1、5、6の画像は同じ表示なのだが、2、3、4は数px右側に表示され、4だけ数px下側に表示される。どれが本当の「中央」を表すのだろうか?
11/01/09追記
azu_reさんより以下の指摘を頂いた。
Chrome,Firefoxだけならメディアクエリ、box-alignとbox-packプロパティ使えばCSSだけでいけるかも。
http://twitter.com/azu_re/status/23716469900578816
このツイートをヒントに調べてみたところ、ChromeならばCSSのみで実現できることが確認できた。Firefoxではどうもサイズの大きい画像では、img要素のみでは幅と幅の最大値のサイズの指定がうまくいかず、img要素の親要素をdiv要素にすると、1の画像の下側に余白が生じてしまう問題が残り、解消できなかった。参考までにChromeのみで動作するソースとサンプルページを記載しておく。
7. body要素に「display: -webkit-box;」を指定し、「-webkit-box-pack: center;」で水平方向での中央表示、「-webkit-box-align: center;」で垂直方向での中央表示をする
<!doctype html>
<meta charset=utf-8>
<title>Case 7</title>
<style>
html, body {
height: 100%;
}
body {
display: -webkit-box;
-webkit-box-align: center;
-webkit-box-pack: center;
margin: 0;
}
img {
max-height: 100%;
max-width: 100%;
display: block;
}
</style>
<img src=http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png>
「CSS 3のボックスレイアウトでコンテンツを画面の中央に配置する - builder by ZDNet Japan」が多いに役に立った。
ブラウザの画面のサイズを変えると、画像の中央表示は維持しつつ画像のサイズもその変化に追随するようになっている。img要素に「display: block;」を指定しているのは、1で言及している問題を回避するためだが、img要素の親要素が、href属性が設定されたa要素だと、通常時は問題ないが、ブラウザ画面のサイズを変えると表示が崩れて画像が無いところもクリックできるようになってしまうようだ。
12/03/19追記
7のボックスレイアウト(現在はFlexible Box Layoutに変わっている)を使用せずとも、CSSのみでInternet Explorer 9.0.5、Firefox 11.0、Chrome 17.0.963.79、Safari 5.1.4、Opera Next 12.00 alpha(build 1328)上において実現できる方法が、Firefox 11.0の画像ページの表示に実装されていることがわかった。
8. 画像の絶対位置を上下左右とも0にし、領域間の上下左右の余白を自動的に調節する
<!doctype html>
<meta charset=utf-8>
<title>Case 8</title>
<style>
img {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
max-height: 100%;
max-width: 100%;
}
</style>
<img src=http://gyazo.com/8e52ce00a418a0ae0bdeb16e87f0a1de.png>
「Firefox で使われている上下左右中央配置のスタイルシート | Unformed Building」を参考にした。
上記のように、これまでの7つの方法と比べて最も簡潔でわかりやすいものとなっている。また、7のようにブラウザの画面のサイズを変えると、画像の中央表示は維持しつつ画像のサイズもその変化に追随するようになっている。欠点としてOpera 11.61では中央表示にならないことが挙げられるが、Opera Nextでは正常に動作していることから、メジャーアップデートによって将来的にそれも解消されるだろう。少なくとも当初の望み通りChromeとFirefoxでは正常に動作しているので、これを採用することにする。
