hasLayout問題を解決するzoom:1;の落とし穴

IEのヘンテコなCSS解釈の原因と言われるhasLayoutプロパティ。
どうやらこのhasLayoutプロパティの値がfalse(デフォルト値)の場合に、いろいろとまずいことが起こるようです。IEだけfloatした要素周辺のmarginやpaddingがおかしかったり、相対配置/絶対配置した要素がどこかに消えてしまったりする・・・という経験はcssレイアウトの際に誰もがぶつかる問題です。

また、hasLayoutがTrueとFalseの要素が混在している場合には、IE7のズーム機能を利用した際に、隣あった要素が重なってしまったりします
この辺はコリスさんのIEでのCSSのバグを回避するhasLayoutに分かりやすい説明があります。

このhasLayoutの問題を解決するためにzoomプロパティが利用されることがあります。(zoomプロパティはIEの独自拡張であるため、これを使うこと自体どうか、という意見もありますがここでは触れません)
具体的には次のように、

* {
margin: 0;
padding: 0;
zoom: 1;
}

ユニバーサルセレクタに指定したり、

body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td {
margin:0;
padding: 0;
zoom:1;
}

などとして、ブラウザスタイルをリセットする際に同時に指定するのが一般的なようです。しかし、zoom:1;をli要素に指定してしまうとマーカーの表示がおかしくなってしまう問題があります
これに対しては

li {zoom: normal;}

としてzoomプロパティの値をデフォルトに戻すことで対処をできるようです。

ここまでは前提で、本題はここからです。

そんなわけで実際に業務で、スタイルリセットにzoom:1;を導入してみたのですが、さらなる落とし穴があることに気づいてしまいました。
STOPN’ LISTENさんのclearfixに関するの記事をご覧いただくとお分かりになると思うのですが・・・そうです。zoom:1;はclearfixにも使われるのです。

つまり、何でもかんでもzoom:1;にしてしまうと、floatが意図しないところでclearされてしまう恐れがあります。具体的には次の図のような例で、問題が起こります。

図: *{zoom:1}で問題の起こるレイアウトの例

XHTMLのコード

<p><img src="/img/2007/09/16_example_img.gif" alt="画像" width="120" height="90" class="photo" /> 段落1テキスト段落1テキスト段落1テキスト段落1テキスト段落1テキスト段落1テキスト段落1テキスト段落1テキスト段落1テキスト</p>
<p>段落2テキスト段落2テキスト段落2テキスト段落2テキスト段落2テキスト段落2テキスト段落2テキスト段落2テキスト段落2テキスト</p>

最初の段落に含まれている画像に対してfloat:leftを指定し、本文を右側に回りこませているという、何の変哲もないレイアウトです。回り込んでいる本文が途中で段落分けされていることがポイントです
ここで* {zoom: 1;}を指定すると、以下の図のようになります。

図: *{zoom:1}でレイアウトに問題が起こった状態の例

図と同じサンプルページも用意しました(IE6/7で見てくださいね)。

段落分けされた途端、clearされてしまっているのがお分かりになるかと思います。これはp要素に対してzoom:1;が効いているからです。これを回避するにはp {zoom:normal;}のようにしてデフォルトの値を上書きするしかありません。個人的にこれは全くナンセンスだと思うのですが・・・。

スタイルリセットの段階でzoom:1;を指定してしまうと、そのサイトのコンテンツは全てがこの挙動になってしまいます。

サイトをリニューアルする際にzoom:1;を新たに導入する、という場合には注意が必要です。今まで正常に表示されていたコンテンツが、先述の例のようにレイアウトが変わってしまうことがあるからです。

サイトを一人で制作し運営していく分には、この挙動を理解した上で制作をすることになるので、全く問題はないと思います。しかし、複数人でチームを組んで一つのサイトを制作・運営する場合には状況が違います。
制作チーム全員がこの挙動を理解することが必須となるのです。人数の多いチームともなると、これはなかなかに簡単なことではありません。

よって、複数人でチームを組んで制作・運営をしている大規模サイトの制作においては、スタイルリセットにzoom:1;を組み込むべきではない、と言えます。

ただ、やはりzoom:1;の便利さは捨てがたいものがあります。idセレクタや子孫セレクタなどを使用して、特定の領域にだけ限定的に利用する分には問題はないでしょう。

zoom:1;は便利ですがご利用は計画的にということです。

日暮里駅の「ガムテープ道案内」

数日前にはてブのトップで見かけた@nifty:デイリーポータルZ:「新宿駅ガムテープ道案内」の作者実演をみた!がおもしろいです。

工事中だった新宿駅構内にある道案内表示が、実はガムテープでできている!ということが密かにネットで話題になっていたらしいです。
そのうちトリオフォーというグループがガムテープ文字を作っている人物を突き止め、インタビューをし、本人をゲストにイベントまで開催してしまったということです。

その人物とは佐藤修悦さんという警備員の男性で、彼の作るガムテープ文字には修悦体という名前まで付いているといいます。また、自主的に始めたものが駅の人に認められてオフィシャルな仕事になった、というエピソードがいいじゃあありませんか。

写真: 日暮里駅構内で見たガムテープ道案内 そんな記事を見ていると・・・現在は日暮里駅で修悦体が見られるというじゃないですか!日暮里駅といえば、私が通勤で利用しています。というわけで早速現物を拝見してきました。

確かに、確かに、ガムテープでできています・・・!こういう普段通り過ぎるだけの通路にこんなアートが隠されていたなんて、本当に目から鱗です。
通路で人を誘導するためのただの案内表示。でもこれってユニバーサルデザインというやつだよなぁ・・・なんて一人うなずいてしまいました。

今、高円寺で展示会をやっているようです。明日(9月2日)で終わりなのではありますが・・・。
しかし日暮里駅のガムテープ道案内は、工事をやっているうちはずっと"展示中"に違いありません。

英辞郎 on the WebをGoogleツールバー for Firefoxから使う

記事内容を削除しました – 2007年11月10日(土)

表題の内容は英辞郎 on the Webの利用規約に違反するものであったため、削除させていただきました。

下記のコードだけ、残しておくことにします。自己責任でご利用ください。

<search charset="UTF-8">http://eow.alc.co.jp/{query}/UTF-8/?q={query}</search>

appendChildに失敗する原因

最近はJavaScriptをいじってるのが楽しくなってきたのでそんなネタでも。

ノードをDOMツリーに追加するappendChildメソッド。当然ですが、ノード以外のものを追加しようとするとエラーになってしまいます。

例えば文字列を追加しようとした場合、Firebugのコンソールではuncaught exception:…とかいうエラーが出ます。数行に渡って激しく怒られるため、最初は一体何事かと思いました。

Firebugコンソールのエラー表示: uncaught exception...

例えば<p id="result">appendChild</p>というp要素があってそこにappendChildしたいとすると…

window.onload = function() {
var result = document.getElementById('result');
var string = '成功!!';
result.appendChild(string); // ←stringは文字列なのでエラー
}

文字列を追加したい場合はcreateTextNodeメソッドを使って文字列をテキストノードに変換する、もしくは最初からcreateTextNodeを使って文字列ではなくテキストノードを作ってappendChildしなければなりません。これで1時間は悩みました・・・orz

window.onload = function() {
var result = document.getElementById('result');
var string = '成功!!';
var textNode = document.createTextNode(string);// テキストノードに変換
result.appendChild(textNode); // ←textNodeはテキストノードなので成功
}

innerHTMLを使えば文字列のまま扱えますが、追加される対象親ノードの中身が全部書き換えられてしまう点に注意。innerHTMLだと"追加"というより"書き換え"っていう感じですね。

window.onload = function() {
var result = document.getElementById('result');
var string = '成功!!';
result.innerHTML = string;
}

Continue reading

無いものねだりはやめて、腹くくれ

某サイトリニューアルの案件に、来月から取り掛かることになりました。

こういう風にできるって分かっているのに、こういう風にすればもっと効率的になるのに・・・というアイデアが、現在の自分のスキルと知識では実装できないものだったりするととてもイライラします。
・・・これはアイデアとさえ呼ばないんでしょうね。ただの無いものねだりです。

何でもモノを作るのにはコストがかかりますが、そのコストに見合うだけの成果が出なければいけません。成果が出ないものについては実行することができないのが現実です。

そんな「できない」ものについてあーでもないこーでもない、と考えるのは時間の無駄です。「できる」、もしくは「できそう」なことについて考え、さっさと実行に移した方がいいのです。

とにかく、無いものねだりはやめて「できる」ことをちゃんと見極めて設計しよう・・・と自分に言い聞かせるためのエントリーです。。