見出し画像

#75 CSSのmaskについて

なんとなくmaskが苦手なので、勉強してみる。
マスクって覆い隠すって意味かと思ってたのに、フォトショとかCSSだと
くり抜くって意味に転化するあたりで、すでに混乱気味。

一番単純なmask clip-pathで円を作る

まずは、HTMLにimgタグを書いて、class名を付ける

<img src="sample.jpg" class="mask_circle">

次に、CSSでclip-pathを記述

clip-path: circle(120px at 200px);

上記の意味は見たところ、半径120pxの円 
at 200pxは、左端から円の中心までの距離
at center にすると、中央寄せになる

clip-path で楕円を作る

.mask_ellipse {
  clip-path: ellipse(140px 100px at 30% 50%);
}

縦の半径140px 横の半径100pxの楕円(ellipse)、
場所は左上から30% 50%の位置

clip-pathで多角形を作る

.mask_polygon {
  clip-path: polygon(40% 0, 90% 50%, 60% 90%, 0 50%);
}

多角形(polygon)の上の位置(左から40% 上から0%)
右の位置(左から90% 上から50%)
下の位置(左から60% 上から90%)
右の位置(左から0% 上から50%)

<参考>

clip-pathで SVGの形にくり抜く

  1. imgタグの下にSVGのpathを貼る

  2. imgタグにsvgを呼び出す用のクラスを付ける

  3. pathの上下を<clipPath>タグで囲む

  4. clipPathタグにSVG用のidを付ける

<img src="sample.jpg" class="mask_svg">
  
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.52 128.12">
  <clipPath id="clip_heart">
    <path class="cls-1" d="M75.94,120.48S20.19,105.27,5.94,75.48C-5.06,52.48,.94,20.48,20.94,18.48s38,19,40,18c4-12,1.1-30.49,23-35,34-7,41,25,43,45s-35,81-35,81l-16-7Z"/>
  </clipPath>
</svg>

CSS側では、imgタグのクラスで、clipPathのidを呼び出す。
ただ、この場合マスク図形の位置をどうやって指定するのかがわからない。
あぁ、なるほどviewBoxの座標位置に依るのかな。

.mask_svg {
  clip-path: url(#clip_heart);
}

<参考>

mask-imageを使って、SVGの形にくり抜く

まずimgタグにclass名を付ける

<img src="./img/park.jpg" class="mask_svg">

CSSはこちら

.mask_svg {
  mask-image: url('./img/star.svg');
  mask-repeat: no-repeat;
  mask-position: 80% 0;
  mask-size: auto 40%;
  -webkit-mask-image: url('./img/star.svg');
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: 80% 0;
  -webkit-mask-size: auto 40%;
}

しかし、codepenでも表示されず、htmlファイルをChromeにドラッグしてfileスキームで見てもmaskは表示されなかった。

さらに、コンソールを開くと、コンソールエラーが出ている。

Access to image at '/img/star.svg' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.

コンソールエラーのログ

<訳>
オリジンがnullだから、CORS(クロスオリジンリソースシェアリング)ポリシーによってブロックしたよ。
クロスオリジンリソースは、http, data, isolated-app, chrome-extension, chrome, https, chrome-untrustedスキームでだけサポートするよ。

まずオリジンとは
URLのスキーム(https://)、ホスト(example.com)、ポート番号(443)の
3つを組み合わせたもの。
ポート番号はhttpsが443、httpは80が既定で既定の番号なら省略可能

CORSポリシーとは、あるオリジンで動いているWeb アプリケーションに対して、異なるオリジンとのデータ交換を可能にするセキュリティ上の仕組み。
もう少しひも解くと、Webサーバに特殊なHTTPヘッダ項目を追加することで、送り出したWebページ上のスクリプトがWebブラウザから別のサーバへアクセスできるようにすること。

ふむふむ。chromeのネットワークタブで、star.svgのリクエストヘッダーを見てみると、Origin:nullが入っていました。imgタグの場合はorigin項目そのものがリクエストヘッダーに無いのに、mask-imageプロパティは、originをリクエストするらしい。

mask-imageに設定したstar.svgのリクエストヘッダー

で、fileスキームでは、ドメイン名がないからnullだし、CORSポリシーでブロックされたのかな。

と、いうことでサーバにアップしたら無事に表示されました。
デモ
mask-image…表示するのに2時間くらいかかった。

<参考>

さらに、maskとcssアニメーションを組み合わせてみた。
後述のグラデーションマスクだと背景が透過でできなかったけれど、これなら背景が写真の場合も、透過でできる。

デモその1

デモその2

maskプロパティは下記の通り、backgroundプロパティに似てる

  mask-image: url('./img/star.svg');
  mask-repeat: no-repeat;
  mask-position: 80% 0;
  mask-size: auto 40%;

ショートハンドはこんな感じ

mask: url('./img/star.svg') no-repeat 80% 0 / auto 40%;

↑は、画像url、繰り返し、位置(X軸方向 Y軸方向) / サイズ(幅 高さ)

mask-imageを使って、グラデーションマスクをかける

linear-gradient や radial-gradientもかけられる

<div class="mask_svg">
 <img src="./img/park.jpg">
</div>
background: #FFF;
mask-image: linear-gradient(321deg, black, black 60%, transparent 100%);
-webkit-mask-image: linear-gradient(321deg, black, black 60%, transparent 100%);

<参考>

これでmaskの使い方の基礎くらいは、わかったような。

mask-imageとCSSアニメーションを組み合わせてみた。

mask(black)の範囲を100%から0%にするアニメーション

@keyframes mask_anime {
  0%{
    mask-image: linear-gradient(321deg, black, black 100%, transparent 100%);
-webkit-mask-image: linear-gradient(321deg, black, black 100%, transparent 100%);
  }
  100%{
    mask-image: linear-gradient(321deg, black, black 0%, transparent 100%);
-webkit-mask-image: linear-gradient(321deg, black, black 0%, transparent 100%);
  }
}

呼び出し側はこんな感じ

animation: mask_anime 4s cubic-bezier(1,-0.02, 0, 0.94) 0s both infinite;

デモ

でもやはり、動きがぎこちないから、グラデーションマスクより、ただのマスクを変化させるほうが、動きが滑らかかもしれない。
デモ

ヘッダー画像は、ダンテ・ゲイブリウル・ロセッティの「旧約聖書の窓のデザイン」

この記事が気に入ったらサポートをしてみませんか?