
CSSで写真のふちをぼかす方法(border枠とbeforeを使ったテクニック)
背景画像の縁(ふち)をCSSでぼかすデザインの作り方をご紹介します。
ポイントは土台画像の下にbefore画像を敷いて、それぞれのbackgound-clipを土台はpadding-boxに、before画像はborder-boxにする事です。
土台画像のborderを透過させれば下のぼかし画像が見える様になり、これがぼかし枠になります。
CSSで画像の縁をぼかすテクニック
今回はCSSのborder枠部分をぼかすボックス演出についてご紹介します。
通常ボックスにつけるborderは色を付けて装飾する事が多いと思います。
わかりやすく言うとborderを利用しながら、画像の周りをぼやけた画像で囲むニュアンスです。
今回の構成のコツ
ボックスの背景画像の下に、before要素でぼかした背景画像を敷きます。
上の背景画像はborderの内側までにしておき、下のぼかした背景画像はborder領域まで画像を見せる訳です。
これにより画像の周囲をぼかした画像で取り囲む形になり、お洒落感が演出できます。
今回はぼかし画像をそのまま見せるのではなく、borderから透過させた合わせ技になっています。
CSSの枠部分をぼかす場合の注意
画像の縁部分がぼかされるので、ぼかされた時に見栄えする画像を選ぶようにしましょう。
ぼかされても画像の延長部分なのだとわからないとぼかす意味がありませんからね。
シンプルなボックス枠のぼかし
各構成ソース
それではHTMLとCSSの各ソースをご紹介ます。
そのままコピーペーストしても使う事ができます。
HTML
<div class="border_bl"></div>
ボックス枠のdivだけですので非常にシンプルですね。
中に文字を入れる事ももちろんできますが、それは後述します。
CSS
.border_bl { width: 100%; height: 300px; background: url(../images/css_border_blurred_img2.png) 50%/cover; background-origin: border-box; background-clip: padding-box; font-size: 2em; border: solid 1.5em rgba(0,0,0,0.2); position: relative; padding: 1em; } .border_bl:before { position: absolute; z-index: -1; top: -1.5em; right: -1.5em; bottom: -1.5em; left: -1.5em; border: inherit; border-color: transparent; background: inherit; background-clip: border-box; -webkit-filter: blur(9px); filter: blur(9px); content: ""; -webkit-clip-path: inset(0 round 10px); clip-path: inset(0 round 10px); }
サンプル例
CSSの解説と実装の流れ
土台ボックスの作成
まず土台となるボックスに幅と高さを指定して、背景画像とborder枠を付けます。
borderは広めの幅(1.5em)と色、そして透明度を付けます。今回は0.2にしています。
background-clipはpadding-boxまで
背景画像の部分は、background-clipをpadding-boxにしておく必要があります。
これによりその外側にあるborder枠の下には背景画像は映らなくなります。
このborder枠を0.2で透明にする事で下に敷く背景画像を映す訳です。ここが一つポイントですね。
※content: "";は必ず入れておいて下さい。
※枠線の色・太さやぼかしのメリハリは、土台ボックスのborder: solid 1.5em rgba(0,0,0,0.2);部分で調整できます。
before要素の作成
土台ボックスにposition: relative;を設定し、before要素を絶対配置でおきます。
この時before要素の重なりはz-index: -1とし、土台の下に潜り込ませます。
絶対配置の位置を上下左右-1.5emとする事で、土台ボックスの枠まで含んだ領域まで広がってくれます。
before要素は土台要素をコピーする形で背景画像と枠を構成します。
borderはinheritで踏襲してtransparentで透明にし、backgroundもinheritにしましょう。
padding-boxとborder-boxの差を作る
ただし背景画像のbackground-clipだけはborder-box;にして、枠線部分の領域まで背景画像が映されるようにします。
土台の枠部分が0.2で透けているので、そのぶん下のbefore要素の背景要素が薄く見えた状態になります。
badkgouund-clip: padding-box;で土台の背景画像を枠の内側に留めているのが、ここで効いてくる訳です。
本サンプルの領域差
土台…padding-boxで背景画像は枠の内側まで
before…border-boxで背景画像(ぼかし)は枠一杯まで
この領域差をぼかし部分の枠として使います。
before要素全体をぼかす
要素をぼかすのに使うのがfilterプロパティです。
filter: blur();内に入れられた数値分、背景画像全体がぼやけます。
-webkit-filter: blur(9px); filter: blur(9px);
-webkitのベンダープレフィックスとともに9pxで設定しています。
先ほどの領域差がぼかし枠になる
土台の0.2の透明枠をつけた背景画像が上に、beforeのぼやけた背景画像が下にあります。
そしてこの両者には、padding-boxとborder-boxの領域差があります。
その分だけ0.2の透明枠の下にあるぼかし画像が見えます。これが「ぼかし枠」となるのですね。
ぼかすだけだと画像の周囲までぼやける
単純にfilter: blur();でぼかすだけだと、before画像の周囲までぼかしが広がってしまいます。
これをきれいに枠内で納めるため、before要素にclip-pathを使っています。
-webkit-clip-path: inset(0 round 10px); //プレフィックス clip-path: inset(0 round 10px);
試しにこのclip-pathの行を削除すると、ぼかしが枠の外まで広がるのがわかります。
clip-pathで、要素周りの輪郭を10px切り取っている形ですね。
overflowを使ったボックス枠のぼかし
下の事例はoverflowを使った枠のぼかしです。こちらの方が馴染みが深いかも知れませんね。
以前までは上記で説明したclip-pathが反映されないブラウザがありました(旧Edge)。
Edgeに対応させるためには、ぼかしが周囲に漏れないようoverflow: hidden;を利用していた訳です。
今はEdgeでもclip-pathが使えるので問題ないのですが、overflow: hidden;でも同じような枠のぼかしを実現できます。
各構成ソース
CSS
.border_bl{
overflow: hidden;
position: relative;
padding: 1em;
width: 100%;
height: 300px;
background: url(../images/css_border_blurred_img2.png) 50%/ cover padding-box content-box, linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2));
font-size: 2em;
}
.border_bl:before {
position: absolute;
z-index: -1;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: url(../images/css_border_blurred_img2.png) 50%/ cover;
-webkit-filter: blur(9px);
filter: blur(9px);
content: "";
}
サンプル例
解説:土台ボックスの変更
このサンプルの場合、基本的にoverflow:hidden;を使っています。
そして土台要素にborderを設置するのではなく、背景画像にliner-gradientを使用します。
border領域を使わず、代わりに背景画像のpadding領域をliner-gradient要素で透過させているのです。
background-clipをcontent-boxにする
background-clipを「content-box」とすれば、padding領域のliner-gradient部分の下に画像は入り込みません。
これによりbefore画像を下に敷いた時に、liner-gradient部分の下にbeforeのぼかし画像が見える様になる訳です。
before要素
before要素は基本的には前回と同じですが、今回の土台には枠線が無いのでその分before画像を広げる必要がありません。
ですので絶対配置の位置は上下左右0になっています。
あとは画像全体をぼかすだけです。上の土台画像のcontent-box領域と下の背景画像の「領域差」がぼかし枠になります。
本サンプルの領域差
土台…content-boxで背景画像はpaddingの内側まで
before…背景画像(ぼかし)は枠一杯まで
この領域差をぼかし部分の枠として使います。
両サンプルの違い
以上2つの実現方法を紹介しましたが、両者には明確な違いがあります。
それはこのボックス内にテキストを入れる時に現れます。
ボックス内にテキストを流し込むとき、ぼかし部分の上からテキストが入ってはいけませんので適切な余白が必要になりますよね。
1つ目のサンプルのテキスト余白
1つ目のサンプルでは土台に1emのpaddingを入れると、きちんと余白ができてくれます。
2つ目のサンプルのテキスト余白
しかし2つ目のサンプルでは土台に1emのpaddingを設定しても、ぼかした枠の幅が変わるだけでテキスト周りの余白はできてくれません。
それは2つ目のサンプル(overflow: hidden;の方)が、背景画像のpadding部分がぼかしの役割を担っているためです。
1つ目…背景画像のborder部分がぼかしを担当
2つ目…背景画像のpadding部分がぼかしを担当
テキストが入らないのであればどちらでもOKですね。
overflowサンプルでテキストを使いたい場合
2つ目のoverflowのサンプルでテキストを流したい場合、after要素を付ける事で実現できます。
after要素入りの各構成ソース
CSS
/*after要素を使う場合*/ .border_bl { overflow: hidden; position: relative; padding: 3em; width: 100%; height: 300px; color: #fff; font: 600; text-shadow: 1px 1px #000; } .border_bl:before, .border_bl:after{ position: absolute; z-index: -1; top: 0; right: 0; bottom: 0; left: 0; border: solid 1.5em rgba(0, 0, 0, 0.2); background: url(../images/css_border_blurred_img2.png) 50%/cover border-box padding-box; content: ""; } .border_bl:before { border-color: transparent; background-clip: border-box; -webkit-filter: blur(9px); filter: blur(9px); }
サンプル例
実装解説
このサンプルの場合土台に背景画像は使わず、beforeとafterの両方に背景画像を使っています。
土台はテキスト表示のみに役割を分担した形です。
代わりにbeforeやafter要素に対し、1つ目のサンプル同様に背景画像とborder枠を使っています。
本サンプルの重なり順
今回afterが増えて3つの要素になりますが、重なり順としては以下の様になりますね。
・1番上:土台
・2番目:after画像
・1番下:beforeぼかし画像
一番下のbefore要素の背景画像に対して、filter: blur();でぼかしを入れます。
さらにbefore要素の背景画像のbackground-clip:を、border-boxにしています。ここもポイントです。
これによりbeforeの背景画像は、上にあるafterの背景画像と違ってborder枠の下まで画像が表示されます。
それに対してafterの背景画像のbackground-clip:はpadding-boxに留めています。
このbeforeとafterの領域差により、下のbeforeのぼかし画像の枠が見えるという訳です。
本サンプルの領域差
土台…背景は何もなしテキストのみ
after要素…padding-boxで背景画像は枠の内側まで
before要素…border-boxで背景画像(ぼかし)は枠一杯まで
この領域差をぼかし部分の枠として使います。
土台はテキストを表示するためだけのものなので、自由にpaddingなどの装飾を付ける事ができるという訳です。
枠に丸みを付ける場合
土台の枠に丸みを付ける場合は以下の通りです。
これまでのサンプルにも既に丸みは付けてあり、ソースにも既に記載されています。
CSS
.border_bl { width: 100%; height: 300px; background: url(../images/css_border_blurred_img2.png) 50%/cover; background-origin: border-box; background-clip: padding-box; font-size: 2em; border: solid 1.5em rgba(0,0,0,0.2); position: relative; border-radius: 10px; //追記 padding: 1em; } .border_bl:before { position: absolute; z-index: -1; top: -1.5em; right: -1.5em; bottom: -1.5em; left: -1.5em; border: inherit; border-color: transparent; background: inherit; background-clip: border-box; -webkit-filter: blur(9px); filter: blur(9px); content: ""; -webkit-clip-path: inset(0 round 10px); clip-path: inset(0 round 10px); //追記 }
ソースの解説
今回は土台とbefore要素の両方に丸みを付けなければなりません。でないと片方のみ四角になってしまいます。
土台はborder-radiusで丸くして良いのですが、before要素の方にはclip-pathプロパティを使います。
clip-path: inset(0 round 10px);
丸くするというよりも、10pxだけ輪郭を丸く切り取る感じですね。
上手く重なってくれない場合
これに私も遭遇して解決に時間が掛かった経験があります。
現状のCSS環境でこのCSSを追加して実装した時に、土台の下にbefore属性が入ってくれない事があります。
この仕組みはbefore属性が、z-index: -1で土台ボックスの下に潜り込まないと始まりません。
下に隠れてくれる事で、土台につけた透明枠ごしにぼかしたbefore画像部分を見せる事ができる訳です。
外枠の下に入り込んでいる場合がある
大抵の場合、z-indexのスタッキングコンテキストが影響しています。
絶対配置でz-indexの重なり順を-1にした際、土台となるWEBページレイアウト枠より下に潜り込んでいる様です。
この時その親要素に背景色が付いていたら見えない訳です。
親要素でリセットを掛ける
そこでposition:relative;が設定してある直近の親要素を探し、z-index: 0;を設定してみましょう。
こうする事で親要素が考慮されなくなり、あらためてz-indexを-1にした要素が下に重なってくれるようになるはずです。
ですので実装時は、position:relative;となっている親要素にご注意下さい。