先日CODEPENで見かけたマスク表現が新鮮だったので、紹介したいと思います。
仕組みを見ると厳密にはマスクではないんですが、透過pngを利用するものとは違って、マスク部分を動かせるのが特徴です。
backgroundの継承を利用
まず、元ネタはCODEPENのこちら。
見てわかるように、非常にシンプルなコードでマスク表現が実現されています。
JSも書いてありますが、こちらマウスにマスク要素が追随するという記述しか書いてありません。僕は初見の際にいったいどういう仕組みになっているのか、直ぐにはわかりませんでした。
では、仕組みを解説していきましょう。
まず、htmlはbody、#mask、#lampという3層のレイヤーになっています。
1 2 3 4 5 6 7 8 9 | < body > < div id = "mask" > </ div > < div id = "lamp" > </ div > </ body > |
続いて肝心のCSSは以下のように書きます。
ポイントは、bodyと#lampのbackground関連の記述。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | body{ background-image : url ( '../images/bg.jpg' ); background-size : cover ; background-attachment : fixed ; width : 100 vw; height : 100 vh; } #mask{ background-color : rgba ( 0 , 0 , 0 , 0.5 ); width : 100 vw; height : 100 vh; display : block ; } #lamp{ position : fixed ; top : 0px ; left : 0px ; width : 300px ; height : 300px ; border-radius : 150px ; border-style : solid ; border-color : white ; box-shadow : 1px 1px 12px white ; background : inherit ; } |
このCSSで#lampはbodyのbackground設定を継承しています。
bodyの背景はbackground-attachment:fixed;によって、ウィンドウに対して固定されており、それを継承する#lampの背景もウィンドウに対して固定されたものとなります。
この設定によって何が起こるかというと、
bodyと#lampの背景がシンクロします。
要素の大きさに関係なく背景が同じになるんです。
つまり、同じ背景を持つふたつのレイヤーでマスクとなる要素を挟み込むことでマスク表現を実現しています。
なので実際には穴を開けて透過しているわけではなく、手前の要素に最下部のレイヤー背景が映し出されているというわけです。
※おまけみたいなものですが、マウスに要素を追随させるJSも載せておきます。
1 2 3 4 5 6 7 8 9 10 11 | $( function (){ var pageX; var pageY; $( 'body' ).mousemove( function (e){ //-150してるのは要素の縦横が300で、要素の中央にマウスが来るようにするためです。 pageX = e.pageX - 150; pageY = e.pageY- 150; $( '#lamp' ).css( 'left' ,pageX); $( '#lamp' ).css( 'top' ,pageY); }); }); |
メリットデメリット
最大のメリットは、動かすことができるマスクが作れるという点です。
要素の大きさが変わっても対応できるので、テキストによって高さが変化するボックスに対しても気軽に使用することができます。
また、背景の継承によって表現が実現されているので、透過部分となる要素の中にテキストや画像を置くことも可能です。
マスクっぽいのアニメーションで開閉するアコーディオンボックスなんかも作れますし、png画像と組み合わせれば複雑な形のマスクを実現することも可能です。
デメリットは、背景とマスク側の背景を同期させる関係でbackground-attachment:fixed;が必須となる点でしょうか。実際に使うとなると、結構使いどころを選ぶと思います。
こういった表現をCSSだけで実現できるのは、なかなか貴重だと思うので機会があれば使ってみたい手法です。