親要素ブロックを半透明、子要素ブロックを不透明にする

ほんの最近まで携わっていた案件でサイトデザイン案のHTMLコーディングした際に遭遇した事例ですが、要は図1のような表示結果を図2のように親要素を半透明にしつつ、その子要素ブロックは不透明にしたいというケースの対応策です。

図1
図2

図の場合はサンプルなので簡単な構成ですが、

  • 背景に何かしらの画像を background に設定してて、
  • コンテンツ領域の縁を半透明にしつつ、
  • コンテンツ領域は不透明にして内容の可読性を確保したい

といったケースが想定されます。Webデザインとしては比較的レアなケースですが。

【対応策その1】filter プロパティの利用

CSSだけで対応しようとする際、真っ先に思い浮かぶのが filter プロパティの利用ですが、工夫しないと上手く対応できません。例えばHTMLが

1
2
3
<div id="parentBlock">
    <div id="childBlock"></div>
</div>

となっているケースでCSSを、

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
body {
    background : #333;
}
div#parentBlock {
    width        : 200px;
    height       : 200px;
    background   : #ff6;
    filter       : alpha( opacity=50 );
    -moz-opacity : 0.50;
    opacity      : 0.50;
}
div#childBlock {
    width      : 150px;
    height     : 150px;
    background : #fff;
}

としてしまうと、図3のように子要素ブロックも filter プロパティの効果が適用されて半透明になってしまいます。

図3

ちなみに div#childBlock に

1
2
3
4
5
6
7
8
div#childBlock {
    width        : 150px;
    height       : 150px;
    background   : #fff;
    filter       : alpha( opacity=100 );
    -moz-opacity : 1.00;
    opacity      : 1.00;
}

と不透明になるように改めて filter プロパティを定義しても効果がありません。

1
2
<div id="parentBlock"></div>
<div id="childBlock"></div>

とHTMLの #parentBlock と #childBlock の親子関係を解消した上で、CSSを

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
div#parentBlock {
    width        : 200px;
    height       : 200px;
    background   : #ff6;
    filter       : alpha( opacity=50 );
    -moz-opacity : 0.50;
    opacity      : 0.50;
}
div#childBlock {
    position   : absolute;
    top        : 0;
    left       : 0;
    width      : 150px;
    height     : 150px;
    background : #fff;
}

とすることで白いブロックだけを不透明にします。タイトルのように「親要素ブロックを半透明、子要素ブロックを不透明にする」から離れましたね(笑)。またHTMLの改変が難しいケースではこの対応策を採るのは難しいことが多いでしょう。

【対応策2】親要素の背景をアルファチャンネルを持つPNG画像にする

PNG画像はアルファチャンネルをサポートしているので、それを利用して半透明の背景画像を別途作成し、div#parentBlock の背景とすることでも一応の解決が図れます。

HTMLは最初の

1
2
3
<div id="parentBlock">
    <div id="childBlock"></div>
</div>

のままで、CSSを

01
02
03
04
05
06
07
08
09
10
div#parentBlock {
    width        : 200px;
    height       : 200px;
    background   : url("./bgParent.png");
}
div#childBlock {
    width      : 150px;
    height     : 150px;
    background : #fff;
}

とします。bgParent.png がアルファチャンネルを設定したPNG画像です。

ただこの対策法の場合、IE6以前ではアルファチャンネルの設定を持つPNG画像をサポートしていないため、不透明の画像として背景表示されます。

【対応策3】対応策2+IE6用アルファチャンネル対応JSライブラリの利用

巷にはIE6のためにアルファチャンネルに対応させる(ないし再現する)ためのJSライブラリがありまして、IE6(以前)のブラウザの場合はそのJSライブラリを読み込むことで、現在一定のシェアを持つブラウザ全てに対応させる方法もあります。

色々種類はあるようですが、自分は

の二種類を試してみました。

IE PNG FIX

IE PNG FIXは大まかに

  1. サイトから取得したiepngfix.zipを解凍して、フォルダを適当な場所に設置
  2. HTMLではscript要素でiepngfix_tilebg.jsを読み込む記述を追記
  3. CSS側では専用のプロパティを追記

の手順で利用可能です。例えばこんな感じになります。

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<html>
<head>
<title>TEST</title>
<!--[if lte IE 6]>
<script type="text/javascript" src="./iepngfix/iepngfix_tilebg.js"></script>
<![endif]-->
<style>
body {
    background : #333;
}
div#parentBlock {
    width        : 200px;
    height       : 200px;
    background   : url("./bgParent.png");
    behavior     : url("./iepngfix/iepngfix.htc");
}
div#childBlock {
    width      : 150px;
    height     : 150px;
    background : #fff;
}
</style>
</head>
<body>
<div id="parentBlock">
    <div id="childBlock"></div>
</div>
</body>
</html>

自分の環境では IETester でページ表示させた際に IETester が落ちてしまいました。レガシーなIEの確認に IETester を利用している場合は結構面倒なことになります。

DD_belatedPNG

DD_belatedPNG の場合は JavaScript でアルファチャンネルを適用させるメソッドを呼び出す形で対応する形式のようです。こちらの利用サンプルを以下に掲載してみます。

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
<head>
<title>TEST</title>
<!--[if lte IE 6]>
<script type="text/javascript" src="./DD_belatedPNG.js"></script>
<script type="text/javascript">
    DD_belatedPNG.fix('#parentBlock'); // 引数は適用する要素の指定
</script>
<![endif]-->
<style>
body {
    background : #333;
}
div#parentBlock {
    width        : 200px;
    height       : 200px;
    background   : url("./bgParent.png");
}
div#childBlock {
    width      : 150px;
    height     : 150px;
    background : #fff;
}
</style>
</head>
<body>
<div id="parentBlock">
    <div id="childBlock"></div>
</div>
</body>
</html>

個人的には DD_belatedPNG の方がやや使い勝手が良いかなぁと思っています。