2017/04/13

CSS3 背景画像だけにガウスぼかしをかける方法

モダンなシングルページレイアウトのウェブサイトで、背景画像をすりガラスのようにぼかしてタイトルを強調させるデザインをよく見る。多くの場合は画像自体にあらかじめフィルタをかけているのだが、CSS3を使うとfilterプロパティを使うだけでblur効果をかけられる。

ただ、ちょっと面倒だったので方法をまとめておく。


backgroundプロパティについて


最初に背景画像を指定するため、backgroundプロパティについて学んだ。
backgroundプロパティは、背景関連の値を一度に指定できるショートハンドプロパティだ。(marginやborderなんかと同じ)

基本的にはショートハンドプロパティを使うのだが、せっかくなのでbackgroundプロパティについて掘り下げる。

  • background-color
    • 背景色のプロパティ
    • ex. background-color: #123456;
  • background-image
    • 背景画像のプロパティ
    • ex. background-image: url(http://example.com/bg.png);
  • background-origin
    • background-imageの基準となる位置のプロパティ
    • ex. background-origin: (border-box | padding-box | content-box);
  • background-position
    • background-originに対する相対的な位置を指定するプロパティ
    • ex. background-position: (top | bottom | left | right | center | ...);
  • background-size
    • background-imageの大きさや比率のプロパティ
    • ex. background-size: (cover | contain | auto | ...);
  • background-repeat
    • background-imageを繰り返し表示するか指定するプロパティ
    • ex. background-repeat: (repeat-X | repeat-Y | repeat | space | round | no-repeat | ...);
  • background-clip
    • 背景色と背景画像の領域のプロパティ
    • ex. background-clip: (border-box | padding-box | content-box);
  • background-attachment
      • background-imageの表示位置のプロパティ
      • ex. background-attachment: (scroll | fixed | local);


といろんなプロパティがあるのだが、以下のようなデフォルト値が設定されている。
そのため、必要に応じで変更を加えたいプロパティを指定する。
  • background-color: transparent;
  • background-image: none;
  • background-origin: padding-box;
  • background-position: 0% 0%;
  • background-size: auto auto;
  • background-repeat: repeat
  • background-clip: border-box;
  • background-attachement: scroll;

今回は画面いっぱいに背景画像を表示したいので、以下のようなCSSになる。
また、画像の読み込みが失敗したときのため、デフォルトの背景色を変更しておく。
.class {
  background-color: #666666;
  background-image: url(http://example.com/bg.png);
  background-repeat: no-repeat;
  background-size: cover;
}

/* shorthand */
.class {
  background: #666666 url(http://example.com/bg.png) no-repeat;
  background-size: cover;
}



filterプロパティについて


次に、画像にフィルタをかけるためにfilterプロパティについて学んだ。
CSS3で新たに追加されたプロパティなのだが、まだドラフト段階なのでモダンブラウザでのみ利用できる。

わりと簡単に画像にフィルタをかけられるので、画像編集ソフトが苦手な人でも使える。(そもそもfilterプロパティが使えるなら、だいたいの人は画像編集ソフトで加工できる気がするけど…)

filterプロパティには、以下の値(フィルタ機能)を指定できる。

  • url
    • SVGフィルタを作ってidを参照する
    • ex. filter: url("filters.svg#filter-id");
  • blur
    • ガウスぼかしを適用する(今回使いたいのはコレ)
    • ex. filter: blur(5px);
  • brightness
    • 明るさを変更する
    • ex. filter: brightness(0.5);
  • contrast
    • コントラストを変更する
    • ex. filter: contrast(200%);
  • drop-shadow
    • ドロップシャドウ効果(影をつける)を適用する
    • box-shadowとかtext-shadow的なやつ
    • ex. filter: drop-shadow(16px 16px 10px black);
  • grayscale
    • グレースケールに変換する
    • ex. filter: grayscale(80%);
  • hue-rotate
    • 色相回転を適用する
    • カラーサークルで色を変えていくイメージ
    • ex. filter: hue-rotate(90deg);
  • invert
    • 階調反転を適用する
    • ネガポジ効果みたいなやつ
    • ex. filter: invert(100%);
  • opacity
    • 透明度を変更する
    • ex. filter: opacity(50%);
  • saturate
    • 彩度(あざやかさ)を変更する
    • ex. filter: saturate(200%);
  • sepia
    • セピア色に変換する
    • filter: sepia(100%)

これだけのfilter関数が用意されており、また「filter: contrast(200%) brightness(150%)」のように複数のフィルタを組み合わせることもできる。

今回は背景画像にぼかしをかけたいので、以下のようなCSSになる。
.class {
  filter: blur(5px);
}



背景画像だけをぼかす


前提知識を学んだところで、ようやく本題に。
3つのステップを踏んで、背景画像だけをぼかすCSSを書く。

画面いっぱいに背景画像を表示する

まずはフィルタのかかっていない背景画像を、画面いっぱいに表示する。
<!-- index.html -->
<div class="container">
  <h1 class="title">Black Everyday<br>Company</h1>
</div>
/* style.css */
.container {
  width: 100vw;
  height: 100vh;
  background: #666 url(https://bcrikko.github.io/web-design-practices/single-page-layout/asset/header.jpg) no-repeat;
  background-size: cover;
}

.title {
  color: white;
  text-align: center;
  font-size: 60px;
  padding-top: calc(100vh / 2 - 60px);
}

背景画像を画面いっぱいに表示したかったので、.containerにwidth:100vw、height:100vhを指定している。1vwや1vhは、ViewPort(画面の大きさ)を1/100した値なので、100vw/100vhで画面いっぱいになる。

ここで気になるのが、width:100%やheight:100%でもいいんじゃないか?という疑問。
%指定は親要素に依存するので、今回の場合はbodyにpaddingやmarginがあると 思い通りにならない。
「画面いっぱいに表示する」という用途ではvwやvhを使うのがオススメ。


background-sizeプロパティには、背景画像を画面いっぱいに表示したかったのでcoverを指定している。
他にも、以下の値が設定できる。

  • 長さ / パーセンテージ
    • 背景の領域を長さ(10pxとか)やパーセンテージ(50%とか)で指定する
  • auto
    • 自動的に表示領域内に収まるように表示される
  • cover
    • アスペクト比を保持したまま、背景領域を完全に覆う最小サイズになるように拡大縮小する
    • 縦長、横長の画像でも空白なく表示できる
  • contain
    • アスペクト比を保持したまま、背景領域に収まる最大サイズになるように拡大縮小する
    • 画像すべてが表示されるように調整するので、横長なら上下に、縦長なら左右に空白がうまれることがある

背景をぼかす

次に背景画像をぼかす。
(htmlは同じなので省略)
/* style.css */
.container {
  /* 省略 */
  position: relative;
}
.container::before {
  content: '';
  position: absolute;
  /* 輪郭がぼやけてしまうのでブラー範囲を広げる */
  top: -5px;
  bottom: -5px;
  left: -5px;
  right: -5px;
  background: inherit;
  filter: blur(5px);
}

.title {
  /* 省略*/
}

フィルタをかけるために、.containerの疑似要素(::before)を使っている。.containerのbackgroundの設定を継承(inherit)し、それに対してフィルタをかけている。

疑似要素を使う理由は、.containerに対してフィルタをかけてしまうと含まれるすべての要素に対して同じフィルタがかかってしまうためだ。(上図のように.titleまでぼけてしまう。)

全部にフィルタをかけないために擬似要素を使っているのに、上図は.titleまでぼけてるじゃないか!と思われるかもしれない。これの原因と対策については、次のステップで説明する。


また、ネガティブマージンを使って疑似要素の範囲を広げる理由は、画像の隅にぼかしによる余白ができてしまうためだ。だから、blurで指定したピクセル分、範囲を広げている。
このあたりは、Design Colorさんの説明がわかりやすい。


疑似要素を最背面に移動させて完成

「背景をぼかす」のステップで.titleまでフィルタがかかっていた。それはposition: absoluteを使ったため、フィルタが最前面にでてきてしまったからだ。
そのため、背景画像だけにフィルタがかかるように最背面に移動させる。
(htmlは同じなので省略)
/* style.css */
.container {
  /* 省略 */
  z-index: 0;
}
.container::before {
  /* 省略 */
  z-index: -1;
}

.title {
  /* 省略 */
  text-shadow: 0 0 10px #333;
}

position: absoluteで最前面にでてきたフィルタをz-indexで最背面に移動させて完成!
ついでに、.titleをより浮かび上がらせるために、text-shadowプロパティを使ってドロップシャドウ効果で影を落としている。






以上

written by @bc_rikko

0 件のコメント :

コメントを投稿