2009年9月10日 (木)
非矩形ブロックの position:fixed
カテゴリ: ウェブデザイン
| コメント (0)
| トラックバック (0)
|
| ![]()
透過PNG固定ブロックでメニューとか作ってると、ついついロゴとか大きくしてみたり、フッター部分の上にちょっとしたボタンを付けたくなったりします。……ていうかそれ私ですが。
ところが固定ブロックの一部分だけをはみ出させたりした場合、いささか困った状況になる場合があります。特にページ全体をセンタリングしたり、ページレイアウトが固定幅だったり、本文に float レイアウトを使ったりしてるときは。……てゆーかそれも私ですが!
今回はそんな「ページの上とかに固定ブロックのメニューを表示しつつ、固定幅レイアウトで、float 段組して、なおかつセンタリングしたい」というワガママちゃんのためのTips。
なにより自分が忘れないうちにメモっときます。(笑)
とりあえずブロック構成の確認
現在、うちとこのサイトは以下のような構成になってます。多少ページごとに違う場合もありますが、だいたいこんな感じで統一してあります。

不良少年サイト構成図
① ページタイトル (見出し)
② メインコンテンツ
③ サイドバー
④ TOPCAT 応援バナー
⑤ TOP ページリンク
⑥ メインメニュー
⑦ ページ先頭リンク
⑧ アクセスカウンタ
赤で囲ったエリアが CSS の ‘position: fixed’ で位置固定してあるコンテンツ、番号は実際に HTML で記述している順番です。携帯電話やテキストブラウザなどで見た場合でも、一応読めるように書いたダス。
検証してませんが、もしかするとSEOにもちょびっとは効果があるかも。
これらを以下のようにグループ分けします。括弧の中は CSS の属性です。
- タイトルブロック (position: fixed / 非対応ブラウザでは position: absolute)
① ページタイトル - コンテンツブロック (position: relative)
② メインコンテンツ (float: left)
③ サイドバー (float: right) - バナーブロック (position: absolute)
④ TOPCAT応援バナー - ヘッダブロック (position: fixed / 非対応ブラウザでは position: absolute)
⑤ TOPページリンク
⑥ メインメニュー - フッタブロック (position: fixed / 非対応ブラウザでは position: relative)
⑦ ページ先頭リンク
⑧ アクセスカウンタ
各グループは <div> 要素で区切るため、同じグループに入るコンテンツの番号は連続していなければなりません。
まずはHTML部分から
前述したように、position: fixed なメニュー + ページ幅固定 + float 段組 + センタリングはけっこうクセがあります。
特に IE6、IE7 は顕著で、気を抜くとすんげーレイアウトが崩れます。いまだユーザー最多なブラウザがバグまみれってのはどうかと思うんですが、崩れちゃうもんは仕方がありません。頑張って書きましょう。
真っ先に考えたのは <div> でコンテナブロックを作って、上で書いた全ブロックをその中につっこむ、最近あちこちで見かける方法なんですが、これだと float でメインコンテンツとサイドバーを並べた際、今回のように float ブロックの後に position: relative のブロックがひとつもないと、IE7 で見事に引っかかります。(relative ブロックがあればオゲ)
てな訳で、今回はブロックごとにコンテナを作ることにします。これだと CGI や PHP 等でメニュー部分を埋め込む場合にも楽ですし、全ブロックが独立してるのでブラウザ間の違いも吸収しやすくなります。
……記述が冗長になるのと、全体の幅などを変えたときに修正箇所が増えるのが難点ですが。
では、以下のHTMLを見てください。
<!-- タイトルブロック -->
<div id="title_base">
<div id="title">
<h1>非矩形ブロックの position:fixed</h1>
</div>
</div>
基本的に、上記のコードをブロックの数だけ繰り返すだけです。
同一ブロックに複数のコンテンツが入る場合は、以下のように記述します。
<!-- ヘッダブロック -->
<div id="header_base">
<div id="header">
<!-- TOPページリンク -->
<a href="/" title="不良少年" id="logo">
<span>不良少年</span>
</a>
<!-- メインメニュー -->
<div id="navigator">
<h2>Navigation</h2>
<ul>
<li><a href="/">TOP</a></li>
<li><a href="/about.xhtml">ABOUT</a></li>
<li><a href="/product/">PRODUCT</a></li>
<li><a href="/blog/">BLOG</a></li>
<li><a href="/link/">LINK</a></li>
<li><a href="/contact/">CONTACT</a></li>
</ul>
</div>
</div>
</div>
実のところ、センタリングしない、または固定幅にしないのなら、一番外側の <div id=”header_base”> ブロックはなくても大丈夫です。
CSS に <div id=”header”> ~ </div> の横幅や、ウィンドウ左端からの位置を書くだけで済みますので。
非矩形固定ブロックの高さは 0 にする
CSSでの固定ブロック+透過PNGに関しては、以前の記事で書いたので割愛します。
ここでは header_base、および header ブロックの CSS のみ記述します。
#header_base
{
display: block;
position: fixed!important;
position: absolute;
top: 0;
text-align: center;
width: 100%;
height: 0;
}
#header
{
display: block;
position: relative;
top: 0;
margin: 0 auto;
width: 800px;
height: 0;
}
ここで重要なのは最後の ‘height: 0;’ のトコ。
高さを 0 にしてどーすんだって感じですが、実はこれが「非矩形ブロックの position:fixed」のキモだったりします。
もう一度、上のサイト構成図を見てください。
⑤のTOPページへのリンクと⑥のメインメニューで、一つのブロックになっています。
さてこのブロック、よく見るとL字型ですね。
矩形以外の、こういった変則的な形のブロックの高さが 0 ではない場合、親要素 header_base と header ブロックの高さは、通常一番大きい子要素 (この場合では⑤のTOPページリンク) の高さに合わせて調整されます。
また、ブラウザの各レイヤーは z-index を指定しない限り、後に記述されたブロックが前のブロックよりも上に配置されます。
ところが⑥の下には④の応援バナーがあったりします。スクロールした場合は他のブロックが入ることもあります。
こうなると④の位置までヘッダブロックがあるとみなされ、その下のレイヤーである④のリンクがクリックできないというトンデモナイ事態に陥る訳です。
このため、親要素 header_base と header ブロックの高さをあらかじめ 0 に指定し、⑤、⑥のコンテンツはそれぞれ親要素からはみ出すよう、個別に高さを指定しています。
たったこれだけのことを説明するために、あたしゃいったい何行書いてんでしょうね。とほほ~。
前述の通り、これがセンタリングしない場合や、ページ幅が固定ではない場合、こんな面倒くさいことはしなくても大丈夫です。
float レイアウトも必要ないなら、普通にページ全体を覆うコンテナブロックを作るだけで済みます。
あれもしたいこれもしたいと欲張るから、こんな苦労をする羽目になるんですが! (泣)
どなたか、もちょっと楽な方法ありましたら教えてください。