krzm.jp
黒住浩司 Webサイト

トップページのCSS3効果①

内容

はじめに

CSS3は、視覚的な効果の面でも、様々な機能が増えています。当サイトでも多用しているのは、ボックスのドロップシャドウ(box-shadowプロパティ)と、輪郭の角丸(border-radiusプロパティ)です。これらのプロパティCSS Backgrounds & Borders Module Level 3モジュールに属し、2012年7月段階で勧告候補になっています。は、いわゆるベンダー接頭辞も既に必要なく、ほとんどのブラウザーでほぼ共通して利用できます。また、IE9でも対応しています。

こうした効果を含め、当サイトのトップページのheaders領域で使用しているCSS3の効果を、この記事では解説していきます。

WordPressのカスタムヘッダー画像

headers領域には、WordPressの「カスタムヘッダー」機能を利用して、画像を出力しています。ようは、WordPressの管理機能を使って画像を出力し、その切り替えも可能にするものです。

カスタムヘッダー管理画面
WordPressの「カスタムヘッダー」管理画面。ここで画像を選択し、表示を切り替えられるようになっている。

カスタムヘッダーを有効化する方法は、別の機会に解説するとして、この画像はimg要素のsrc属性にWordPress関数header_imageを挿入することで、HTMLページに出力されています。ですから、カスタムヘッダーはimg要素として、扱うことになります。


<img alt="" src="<?php header_image(); ?>" />

カスタムヘッダーのために用意してあるのは、以下のような“ふつう”の画像です。

ヘッダー画像

これに、RGB3色の走査線が入るとともに、画像を少しぼかしてゴーストが出ているかのように見せかけています。その実現に、CSS3が一役買っているわけです。

まず、カスタムヘッダー部分は、以下のようなHTML構造になっています。

ソースコード画像
カスタムヘッダー画像画像を含むheadersのHTML(PHP)ソースコード

すなわち、div要素headersの中に直接img要素が配置されているわけですが、同じimg要素を2つ入れてあります。

headersボックスのスタイル指定

同じものが2つ、というところがポイントなのですが、その前に土台のheadesボックスを見ていきましょう。headersには、以下のスタイルを指定しています。


body.home #headers, body.error404 #headers {
	background-color:rgb(240,240,240);
	background-image:url("../images/top_header_bg.png"), linear-gradient(to bottom, rgb(32,32,32) 0%, rgb(240,240,240) 40%, rgb(240,240,240) 80%, rgb(196,196,196) 100%);
	background-size:auto !important;
	background-repeat:repeat !important;
	border-radius:16px 16px 8px 8px;
	box-shadow:inset 0px 0px 32px rgb(0,0,0), inset 0px -16px 32px rgb(0,0,0), inset 0px -8px 16px rgb(0,0,0), 0px 0px 1px 2px rgb(255,255,255), 0px 4px 12px rgba(128,128,128,0.3);
	z-index:2;
}

headersの指定は、他のページとトップページでは異なるので、body要素のclass属性で分別するセレクターになっています。

また、CSSファイルを対象やバージョンに応じて細分化しているので、実際には、上記の指定は複数のCSSファイルに分かれています。

これらのうち、まずbackground-colorプロパティで背景色を明るいグレーにしています。まあ、このプロパティに、目新しいものはありません。

background-image値の複数指定

次のbackground-imageプロパティでは、画像とグラデーションの指定を行っています。CSS3では、複数の背景画像を指定できるようになっているので、画像とグラデーションの定義をしているのです。

背景画像のtop_header_bg.pngファイルが、3色の走査線を表現しています。

画像拡大図

上図は、top_header_bg.pngファイルを拡大表示したものですが、1ピクセルの正方形を半透明のRGB各色で塗りつぶし、1ピクセルの隙間を空けて並べています。この小さな画像の繰り返しによって、走査線を表します。

結果画像
top_header_bg.pngによる背景画像の表示結果

headersに対し、繰り返し表示指定のbackground-repeat:repeatを!important付きで明示的に強制しているのは、他のページのheaders用の指定では、繰り返しを無し(no-repeat)にしているので、それを打ち消すためのものです。

グラデーション

さて、background-imageでは、もうひとつの値にCSS3で追加されたグラデーションCSSグラデーションは、CSS Image Values and Replaced Content Module Level 3で定義されています。2012年4月段階で、勧告候補です。を指定しているのですが、グラデーションはbackground-colorではなく、background-imageの値として使うのです。値は、関数形式になっていて、以下の4つが用意されています。

  • linear-gradient() 線形グラデーション
  • radial-gradient() 円形グラデーション
  • repeating-linear-gradient() 線形グラデーションの繰り返し
  • repeating-radial-gradient() 円形グラデーションの繰り返し

今回は線形グラデーションを使っていますが、その内容は、以下のように引数をカンマで区切って並べたものです。


linear-gradient(
	to bottom,
	rgb(32,32,32) 0%,
	rgb(240,240,240) 40%,
	rgb(240,240,240) 80%,
	rgb(196,196,196) 100%
)

最初のto bottomは、グラデーションの向きで、「上から下へ」を意味します。こうしたキーワードのほかに、角度(deg)を数値指定することも可能です。以下の図は、角度とキーワードの概念図です。

概念図
CSS3グラデーションの角度とキーワードの概念図

最近まで、Chromeは標準とは異なるグラデーション方向のキーワードや角度を使っていましたが、最新のver26では、仕様どおりになっています。また、IE10や、Firefox、Opera、Chromeの最新版Chromeが仕様どおりのグラデーションに対応したのは、ver.26からです。ver.25では、まだベンダー接頭辞付かつ独自仕様の値を使用しています。当サイトのグラデーション指定からは、既に独自仕様の指定を削除したため、Chrome ver.25では正しく表示されません。すべてで、値のベンダー接頭辞は必要ありません。

そして、残りの引数が、グラデーションパターンの色と位置を表します。ここでは通常のrgb関数で色指定していますが、CSS3で追加されたrgba関数も使えます。「a」は0(透明)~1(不透明)で透明度を表し、たとえばrgba(255,0,0,0.5)とすれば半透明の赤になります。ですから、透明グラデーションの適用も可能になりますが、今回は透明度のないグラデーションです。

グラデーション構成図
グラデーションパターンの色と位置の構成

また、各パターンの位置は、グラデーションの方向に沿って、パーセント単位で指定します。つまり、パターンの値は、色指定と位置のセットになっているということです。

さて、background-imageに入れた複数の値ですが、初めの値の方が前面に表示されます。ですから、今回の場合、画像が前面で、グラデーションはその背面に表示されることになります。top_header_bg.pngは、もともと透明度のあるPNG画像として作ってあるので、背面のグラデーションも透けて見えています。

結果画像
グラデーションの表示結果

border-radius

あとは、border-radiusプロパティborder-radiusはCSS Backgrounds and Borders Module Level 3で定義されています。で4隅をそれぞれ、角丸にしています。4つの値は、左上、右上、右下、左下の順になります。


border-radius:16px 16px 8px 8px;

左上と右上は、headersの親ボックスに指定してあるborder-radiusで、既に角丸に切り取られていますが、念のため、headersにも指定しています。

結果画像
border-radiusの適用結果

このほか、border-radiusでは、値の数に応じて、以下のようなコーナーを指定することになります。

概念図
border-radius値の個数と対応コーナーの関係

また、各値は、「角丸半径」を表しています。角丸は、コーナーに接する円の形で表されるので、その円の半径サイズを数値指定します。

概念図
角丸半径の概念図

box-shadow

そして最後は、ドロップシャドウのbox-shadowプロパティbox-shadowはCSS Backgrounds and Borders Module Level 3で定義されています。です。値は、カンマ区切りで以下の5つの影を定義しています。このプロパティも、複数の値、すなわち複数の影が適用できるのです。


inset 0px 0px 32px rgb(0,0,0),
inset 0px -16px 32px rgb(0,0,0),
inset 0px -8px 16px rgb(0,0,0),
0px 0px 1px 2px rgb(255,255,255),
0px 4px 12px rgba(128,128,128,0.3)

頭にinsetというキーワードが付いているものがありますが、これはボックス内側の影を指定します。キーワードがない場合は、外側の影になります。

半角スペースで区切ったpx数は、以下の指定です。

  • 水平方向の影のオフセット(正の値で右、負の値で左方向)
  • 垂直方向の影のオフセット(正の値で下、負の値で上方向)
  • 縁のぼかし
  • 影を拡張(スプレッド)する距離
概念図
ドロップシャドウ構成の概念図

このうち、縁のぼかしと影の拡張は省略することができますが、数値を3つだけ書いた場合、3つ目は必ずぼかしになります。つまり、ぼかしを省いて拡張を指定することはできません。

最後の値は影の色で、ここでもrgba関数を使用し、影を半透明にすることもできます。

今回の指定では、最初の3つで内側の影を、まさに三重にかけています。

結果画像
inset 0px 0px 32px rgb(0,0,0)によるドロップシャドウ(内側)の表示結果
結果画像
inset 0px -16px 32px rgb(0,0,0)を追加した表示結果
結果画像
inset 0px -8px 16px rgb(0,0,0)を追加した表示結果

4つ目は、ボックスの周囲に、2ピクセルの枠線を付けているような形になります。そして、5つ目では、ボックスの下側にグレーの影を伸ばしています。これらによって、headersの下辺が、内側に微妙にへこんでいるような演出をしています。

結果画像
0px 0px 1px 2px rgb(255,255,255)と0px 4px 12px rgba(128,128,128,0.3)の追加によるへこみ用の影(ボックス外側の下)

なお、headersの下には、次のdiv要素top_contentsが続いています。positon:absolute等が指定されていない限り、同じ親を持つ兄弟要素は、後に書かれているものの方が前面に表示されます。すると、背景色が白に設定してあるtop_contentsによって、headers下辺の影が隠れてしまうので、headersがtop_contentsの前面になるように、z-indexプロパティで値を2にして重ね順を変更しています。

ヘッダー画像のスタイル指定

以上で、土台としてのheadersが出来上がりました。その上に、カスタムヘッダー画像を重ねるわけですが、その指定は以下のとおりです。なお、2つの画像にそれぞれ、header_image1、header_image2というid属性値を振り、セレクターに利用しています。


#header_image1 {
	display:block;
	position:absolute;
	left:0px;
	top:0px;
	border-radius:8px 8px 0px 0px;
	opacity:0.2;
}
#header_image2 {
	display:block;
	position:absolute;
	left:4px;
	top:4px;
	border-radius:8px 8px 0px 0px;
	opacity:0.3;
	box-shadow:inset 0px 0px 8px rgb(0,0,0);
}

配置

まず、画像を重ね合わせる方法として、デフォルトのインライン表示をdisplay:blockでブロックレベル表示に切り替え、position:absoluteで絶対配置を指定し、あとはleftとtopプロパティで位置決めしています。header_image1はheadersの左上隅に、header_image2はそこから4ピクセル、左と下にずらして重なるように配置しています。

画像の重ね合わせ方法
2つの画像の配置とサイズ構成

HTMLのソースコード上では、header_image2の方が後に記述されているので、重ね順は、header_image2の方が前面になります。

なお、子要素を親要素内で絶対配置するには、親ボックス側にpositionプロパティでabsoluteかrelativeが指定されていなければならないのは、CSS2での常識です。

ここまではCSS2のお話でしたが、CSS3効果としては、border-radiusで、画像にも角丸を指定しています。

opacity

そして、これらの画像で最も肝心なスタイルは、やはりCSS3で追加されたopacityプロパティopacityはCSS Color Module Level 3で定義されています。2011年6月段階で、W3C勧告として仕様が確定しています。です。opacityでは0~1の値を指定しますが、これはrgbaのaと同じように、0~1が透明~不透明の透明度になります。この透明度は、対象要素全体に均等opacityの透明度は、対象要素に均等にかかるだけでなく、その子要素にも適用されます。これに対し、背景色やグラデーションに使用する透明カラーは、それを使用した対象だけに透明度が適用され、子要素が透明になることはありません。にかかります。

なお、header_image1のサイズは100%、header_image2のサイズは100.25%と、スタイルではなくimg要素のwidth属性で指定しています。この、若干サイズの異なる画像が、位置を若干ずらして重なり、それぞれの透明度によってゴーストのようにぶれて見えるのです。

重ね合わせ結果
透明度を指定した画像の重ね合わせによりぶれを表現

さらに、それぞれの透明度によってheaderの背景にある走査線、グラデーション、そしてドロップシャドウが透けて見えることで、すべての演出が完成する次第です。

ヘッダー画像効果の完成図
ヘッダー画像部分の完成状態

制作意図

こうした効果を意図した理由は、カスタムヘッダーがimg要素として配置されるので、「img要素としての状態のままで、どのような処理が適用できるのか?」ということを追求してみたかったからです。スタイルシートを利用していると、画像はたいてい背景画像(background-image)として使うことが多いので、img要素をどう扱えばよいのか、試してみた次第です。今回の例では、最後に出てきたopacityプロパティが、その中心的な役割を果たしてくれたといえます。

もちろん、単なるCSS3の探究という目的のほかに、headers領域で表現しようとしたもののイメージは、ジョージ・オーウェルの小説「一九八四年」に登場する、テレスクリーン私の勝手な想像では、この機器は30~40インチ程度の薄型液晶テレビのようなものと考えていましたが、実際の1984年には、まだこの機器を製造することはできなかったでしょう。しかし、2013年の現在では、そうしたテレビやディスプレイは実現されているだけでなく、最早時代遅れであり、今日的なテレスクリーンは携帯電話やスマートフォンとして、多くの”人民”の日常生活に溶け込んでしまっているのが現実です。小説を超えた、何とも”素晴らしい”未来ですね、この忌々しい現代は。から着想を得ています。あの思考警察が、人民を監視するために使っている”コミュニケーション”機器です。そう、「ビッグブラザーがあなたを見ている」のです。

真理省
真理省。それは白いコンクリートをきらめかせ、上空三百メートルの高さまでテラスを何層も重ねながら、聳え立っている(早川文庫版「一九八四年」より)

次回は、このheaders上に配置する、ナビゲーションボタン(topnav)に使用した効果について、解説します。

サンプル ソースコード

サンプルコード1

body.home #headers, body.error404 #headers {
	background-color:rgb(240,240,240);
	background-image:url("../images/top_header_bg.png"), linear-gradient(to bottom, rgb(32,32,32) 0%, rgb(240,240,240) 40%, rgb(240,240,240) 80%, rgb(196,196,196) 100%);
	background-size:auto !important;
	background-repeat:repeat !important;
	border-radius:16px 16px 8px 8px;
	box-shadow:inset 0px 0px 32px rgb(0,0,0), inset 0px -16px 32px rgb(0,0,0), inset 0px -8px 16px rgb(0,0,0), 0px 0px 1px 2px rgb(255,255,255), 0px 4px 12px rgba(128,128,128,0.3);
	z-index:2;
}
#header_image1 {
	display:block;
	position:absolute;
	left:0px;
	top:0px;
	border-radius:8px 8px 0px 0px;
	opacity:0.2;
}
#header_image2 {
	display:block;
	position:absolute;
	left:4px;
	top:4px;
	border-radius:8px 8px 0px 0px;
	opacity:0.3;
	box-shadow:inset 0px 0px 8px rgb(0,0,0);
}