HTML
CSS
CSS3

CSS3で角丸要素にマスクをかけようとしたらドハマりしたので攻略法を伝授します。

More than 1 year has passed since last update.


やりたかったこと

角丸要素にマスクをかけて、中の子要素をCSSでアニメーションさせたい

どんなアニメーションかというと、要素の中に小さな円があって、それが要素内をぶわぁ〜って広がっていくような感じ。

【成功イメージ】

maskimage_success_sample1.gif


ハマったポイント

子要素に対してマスクはかかっていたが、アニメーションさせた時に角丸の四隅がマスクされない。

【こうなった】

maskimage_fail.gif


失敗コードその1


HTML

<div class="box">

click me!
<div class="boxInner"></div>
</div>


SASS

.box{

text-align:center;
width:400px;
height:400px;
background:#efefef;
border-radius:50px;
position:relative;
overflow:hidden;
margin:10% auto;
}
.boxInner{
content:'aaa';
width:100px;
height:100px;
background:#ff0000;
border-radius:50%;
position:absolute;
top:-2%;
left:-2%;
&.anm{
animation-name: slidein;
animation-duration: 4s;
}
}
@keyframes slidein {
0% {
top:-200%;
left:-200%;
opacity:1;
width: 0%;
height:0%;
}
100%{
top:-100%;
left:-100%;
opacity:0;
width: 500%;
height:500%;
}
}


javascript

$(function(){

$('.box').on('click',function(){
$('.boxInner').toggleClass('anm');
})
});

※javascriptはクリックした時にクラスを追加するためだけに書いています。

実際の動作はこんな感じ

maskimage_fail_sample1.gif

マスク処理サンプル:失敗その1(デモ)


原因

keyframes内でopacityの値を入れているとマスクされないようです。

opacityを外したら四隅はマスクされました。

でも、動作的に円が中心から広がっていくようなイメージではない(widthを広げている)ため、何かイメージと違うのでこれはボツ。


失敗コードその2


HTML

<div class="box">

click me!
<div class="boxInner"></div>
</div>


SASS

.box{

text-align:center;
width:400px;
height:400px;
background:#efefef;
border-radius:50px;
position:relative;
overflow:hidden;
margin:10% auto;
}
.boxInner{
width:100px;
height:100px;
background:#ff0000;
border-radius:50%;
position:absolute;
top:-2%;
left:-2%;
&.anm{
animation-name: slidein;
animation-duration: 2s;
}
}
@keyframes slidein {
0% {
transform:scale(0.1);
}

100% {
background:#FFCADE;
transform:scale(50);
}
}



javascript

$(function(){

$('.box').on('click',function(){
$('.boxInner').toggleClass('anm');
})
});

実際の動作はこんな感じ

maskimage_fail_sample2.gif

マスク処理サンプル:失敗その2(デモ)

widthを広げるのではなく、transform:scaleで拡大させる作戦。

動作はイメージ通り、でも四隅がマスクされない問題勃発。。。


原因

keyframes内でtransformを設定しているとこうなるらしい。


完全に詰んだ・・・orz

この手のエフェクトはGoogleのマテリアルデザインなんかでも採用されていたりするので、色んな所で見たりもしていたけど、

まさか角丸だとマスクされないとは・・・

先人たちはこのピンチをどのように切り抜けてきたのであろうかと、

悩みながら試行錯誤を繰り返して約半日。

9割9部諦めていた時に...


神は降臨した!

border-radiusで丸くした部分にoverflow:hiddenが効かない対処法

神様仏様qiita様!

やはり、同じ問題を抱えて解決された方がいらっしゃった!

cssに「mask-image」なるプロパティが存在していたのですね!

画像で要素にマスクがかけられるようだ!

これを使って修正してみた!


成功コード


HTML

<div class="box">

click me!
<div class="boxInner"></div>
</div>


SASS

.box{

text-align:center;
width:400px;
height:400px;
background:#efefef;
border-radius:50px;
position:relative;
overflow:hidden;
margin:10% auto;
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);

mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);

}
.boxInner{
width:100px;
height:100px;
background:#ff0000;
border-radius:50%;
position:absolute;
top:-2%;
left:-2%;
&.anm{
animation-name: slidein;
animation-duration: 2s;
}
}
@keyframes slidein {
0% {
transform:scale(0.1);
}

100% {
background:#FFCADE;
transform:scale(50);
}
}



javascript

$(function(){

$('.box').on('click',function(){
$('.boxInner').toggleClass('anm');
})
});

実際の動作はこんな感じ

maskimage_success_sample1.gif

マスク処理サンプル:成功(デモ)

できた!!できたよ!!!!

求めていたのはまさにこれ!

たったに行のコードを追加しただけで解決しました!


8/23追記

mask-image を使わなくても親要素の .boxz-index を指定してあげたらマスクがかかるようです。

【参考】

http://codepen.io/geckotang/pen/NAVXmQ

http://codepen.io/geckotang/pen/XKwkAr

GeckoTang

ご指摘ありがとうございました!


振り返り

今回の一件で、今まで要素にマスクをかける方法がoverflow:hiddenのみだと思っていたが、

mask-imageという新たな引き出しを得ることが出来た。

しかも、これだと画像で要素がくり抜けるので、いろんなことにも応用が効きそう!

さらに色々調べていくと、svgを使ってマスクをかけることも出来るみたい(http://qiita.com/C058/items/25f0c5e362ba7a5e99e3 )なので、

今度はこちらも試してみたい!