パス、シェイプ、クリッピング、マスキング

HTML レンダリングはボックスモデルに基づいて構築されていますが、人生(とウェブデザイン)は長方形だけではありません。CSS では、要素のどの領域をレンダリングするかを変更する複数の方法がサポートされているため、デベロッパーはあらゆる形状やサイズに対応したデザインを自由に作成できます。クリッピングでは幾何学的な形状を使用できますが、マスキングではピクセル単位で可視性に影響します。

パスとシェイプ

CSS では、関数を使用してシェイプを定義します。関数に関する一般的な情報については、CSS 関数モジュールをご覧ください。このセクションでは、CSS で図形を作成する方法について説明します。次の例ではすべて、clip-path プロパティで作成したシェイプを使用しています。これにより、表示領域がシェイプの内側のみに縮小されます。これにより、要素を要素のボックスとは視覚的に異なるものにできます。クリッピングについては、後で詳しく説明します。

CSS で定義されるシェイプは、基本シェイプ(円、長方形、ポリゴンなど)またはパス(複雑な複合シェイプを定義できる)のいずれかになります。

基本的な図形

circle()ellipse()

circle() 関数と ellipse() 関数は、要素に対する相対的な半径を持つ円形と楕円形の形状を定義します。circle() 関数は、引数として単一のサイズまたは割合を受け取ります。デフォルトでは、どちらの関数も要素の中心を基準にシェイプを配置します。どちらも at キーワードの後にオプションの位置を受け入れます。位置は長さ、パーセンテージ、位置キーワードで表すことができます。

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: circle(50%);
}

circle() 関数に 50% の引数を渡すと、完全な円がレンダリングされます。

前の例は、circle() 関数を使用した円形のクリッピング パスを示しています。半径を 50% にすると、要素の幅いっぱいの円が作成されます。ellipse() 関数は、図形の水平方向と垂直方向の半径を表す 2 つの引数を受け取ります。

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: ellipse(50% 25%);
}

ellipse() 関数は、パーセンテージ引数で楕円を生成します。引数に 50% と 25% を指定すると、X 軸の半径が Y 軸の半径の 2 倍になる楕円が生成されます。

上記の例は、ellipse() 関数を使用した楕円形のクリッピング パスを示しています。半径を 50% にすると、要素の幅いっぱいの楕円が作成されます。次の例は、要素の上部の中央に配置された同じ楕円を表示します。

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: ellipse(50% 25% at center top);
}

rect()inset()

rect() 関数と inset() 関数は、要素の辺に対する辺の位置を設定することで、長方形を定義するさまざまな方法を提供します。これにより、要素のデフォルトのボックスとは視覚的に異なる長方形を作成できます。オプションで round キーワードを受け取り、border-radius 短縮プロパティと同じ構文を使用して角丸の長方形を作成します。

rect() 関数は、長方形の上辺と下辺の位置を要素の上辺を基準に定義し、左辺と右辺の位置を要素の左辺を基準に定義します。この関数は、上、右、下、左の辺を定義する引数として、4 つのサイズまたはパーセンテージの単位を受け取ります。要素のサイズが変更されても拡大縮小されない長方形や、要素のサイズが変更されても同じ比率を維持する長方形が必要な場合は、rect() 関数を選択します。

.my-element {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: rect(15px 75px 45px 10px);
}

rect() 関数は、長方形のサイズを定義する 4 つの引数を受け取ります。この場合、引数は 15px、75px、45px、10px です。

上記の例は、rect() 関数を使用して定義された長方形のクリッピング パスを示しています。図に示すように、ディメンションは要素の上端と左端からの相対値です。

inset() 関数は、要素の各辺からの内側の距離によって、長方形の辺の位置を定義します。この関数は、1 ~ 4 個のサイズ単位またはパーセンテージ単位を引数として受け取り、複数の辺を一度に定義できます。要素に合わせて拡大縮小する長方形や、要素の端から一定の距離を保つ長方形が必要な場合は、inset() 関数を使用します。

.my-element {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px);
}

inset() 関数は、要素の固有サイズから減算できます。この図のこの関数の引数は、15px、5px、15px、10px です。

上記の例は、inset() 関数を使用して定義された長方形のクリッピング パスを示しています。寸法は要素の辺を基準としています。

rect() 関数と inset() 関数は、round キーワードをオプションで受け取り、border-radius 短縮プロパティと同じ構文を使用して角丸の長方形を作成します。次の例は、前に示した長方形の角を丸めたバージョンを示しています。

.rounded-rect {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px round 5px);
}

.rounded-inset {
  width: 80px;
  height: 60px;
  background: blue;
  clip-path: inset(15px 5px 15px 10px round 5px);
}

polygon()

三角形、五角形、星形などの他の図形の場合、polygon() 関数を使用すると、複数の点を直線で結んで図形を作成できます。polygon() 関数は、2 つの長さまたはパーセンテージ単位で構成されるペアのリストを受け入れます。各ペアは、ポリゴンの点を表します。最初の値は要素の左端からの距離、2 番目の値は要素の上端からの距離です。最後のポイントと最初のポイントが接続されるため、ポリゴンを閉じる必要はありません。

.my-element {
  width: 60px;
  height: 60px;
  background: blue;
  clip-path: polygon(
    50% 0,
    0 100%,
    100% 100%
  );
}

polygon() 関数は、複雑な図形を描画するために可変数の引数を受け取ります。この場合、三角形が作成されるように引数が作成されます。

上記の例では、3 つの点を定義して三角形のクリッピング パスを作成しています。

デフォルトでは、polygon() 関数は重なり合う領域を塗りつぶしとしてレンダリングします。この動作は、塗りつぶしルールと呼ばれるオプションの最初の引数で変更できます。塗りつぶされた領域と塗りつぶされていない領域を交互に表示するには、塗りつぶしルールを evenodd に設定します。デフォルトの塗りつぶしルールを使用するには、nonzero に設定します。

前の例では、正多角形と星形を作成するために三角関数とともに polygon() 関数を使用しています。これは、要素内に収まる最大の正多角形を作成したり、その正多角形を中央に配置したりするものではありません。それについては、読者の皆様がご自身で試してみてください。この例の星形は、nonzeroevenodd の塗りつぶしルールも示しています。

複雑な図形

基本的な図形関数では複雑な図形を記述できない場合、CSS ではより高度な構文を使用して曲線や線などの特徴を記述する関数が用意されています。これらの関数は、複合シェイプ(複数のシェイプで構成されるシェイプ。穴の開いた円など)にも役立ちます。

path()

path() 関数は、形状を記述する SVG パス構文の文字列を受け取ります。これにより、図形を構成する線や曲線を記述する指示を使用して、複雑な図形を作成できます。SVG 構文を直接編集するのは複雑になる可能性があるため、path() 関数で図形を作成する際は、構文をエクスポートできる専用のビジュアル エディタの使用を検討することをおすすめします。

path() 関数は CSS サイズ単位を使用せず、すべての値はピクセルとして解釈されます。つまり、path 関数で作成されたシェイプは、要素やコンテナのサイズに反応しません。path() は、サイズが固定されているシェイプでのみ使用することをおすすめします。

shape()

shape() 関数は、path() 関数と同様に、コマンド構文を使用して図形を記述します。ただし、shape() 関数コマンドはネイティブ CSS であり、CSS サイズ単位を使用できます。これにより、shape() 関数を使用して定義されたシェイプをレスポンシブにサイズ設定できます。

上記の例では、path() 関数と shape() 関数を使用して、ハート型と中央に穴のある円を定義しています。この例では、両方の関数で同じピクセル値を使用していますが、shape() 関数では、パーセンテージやコンテナ相対単位などの他の CSS サイズ単位も使用できます。

クリッピング

クリッピングは、雑誌から画像を切り抜くように、要素のどの領域を表示するかを定義します。clip-path プロパティは、クリップ領域の定義に使用されるパスを設定します。

前のセクションの例で見たように、基本的なシェイプ関数またはパス関数は clip-path として使用できます。clip-path プロパティは、SVG の clipPath 要素で定義されたパスもサポートしています。このパスは、埋め込みにすることも、別のファイルにすることもできます。

クリッピングが画像に与える影響: この画像では、子猫の写真が円と、子猫全体を囲む複雑なクリップパスの両方でクリッピングされています。

上の図は、画像要素に clip-path を追加すると、画像の表示領域がどのように変化するかを示しています。上のクリップパスは circle() 関数を使用し、下のクリップパスは SVG の clipPath を使用しています。circle() 関数を使用して作成された円は、デフォルトで要素の中央に配置されます。

clip-path プロパティは単一のパスのみを受け入れます。重ならない複数のシェイプで要素をクリップするには、path() 関数または shape() 関数を使用して複合パスを定義するか、SVG clipPath を使用します。複雑なシナリオでは、クリッピングの代わりにマスキングを使用することもできます。これについては、後のセクションで説明します。

シェイプでクリッピングする

基本的な図形関数またはパス関数を使用してクリップするには、前の例のように、clip-path プロパティを関数から返された値に設定します。各関数は、要素に対するクリッピング形状の位置を異なる方法で設定します。各関数のリファレンスを参照してください。

上記の例では、.clipped クラスを使用して 2 つの要素に円形の clip-path が適用されています。clip-path は各要素に対して相対的に配置され、clip-path 内のテキストは形状に合わせて再フローされません。

クリッピング パスの参照ボックス

デフォルトでは、要素のクリッピング パスには要素の枠線が含まれます。基本シェイプ関数を使用する場合、クリップパスの参照ボックスを、要素の境界内の領域のみを含むように設定できます。参照ボックスの有効な値は、stroke-box(デフォルト)と fill-box(境界線の内側の領域のみを含める)です。

前の例では、20px 境界線を持つ要素が示されています。各要素は inset() 関数を使用して clip-path を設定しています。要素の枠線に対してクリップする要素は、枠線の一部をまだ表示しています。枠線内の領域を基準にクリップされる要素は、同じインセット値でも枠線が表示されず、小さくなります。

グラフィックを使用したクリッピング

クリッピング パスは、HTML ドキュメントに埋め込まれているか、外部から参照されている SVG ドキュメントで定義できます。これは、グラフィック プログラムで作成された複雑なクリッピング パスや、複数のシェイプを組み合わせたクリッピング パスを定義する場合に便利です。

<img id="kitten" src="kitten.png">

<svg>
  <defs>
    <clipPath id="kitten-clip-shape">
      <circle cx="130" cy="175" r="100" />
    </clipPath>
  </defs>
</svg>

<style>
  #kitten {
    clip-path: url(#kitten-clip-shape);
  }
</style>

上記の例では、idkitten-clip-shapeclipPath<img> 要素に適用されます。この場合、SVG ドキュメントは HTML に埋め込まれます。SVG ドキュメントが kitten-clipper.svg という名前の外部ファイルである場合、clipPathurl(kitten-clipper.svg#kitten-clip-shape) として参照されます。

マスキング

マスキングは、要素のどの領域を表示または非表示にするかを定義する別の方法です。クリッピングでは基本的な図形やパスを使用しますが、マスキングでは画像やグラデーションのピクセルを使用して可視性を決定します。クリッピングとは異なり、マスキングでは要素の領域を部分的に透明にすることができます。要素に複数のマスク画像を適用して、さまざまな効果を生み出すことができます。

マスクを適用するには、mask-image プロパティを設定します。このプロパティは、SVG ドキュメント内の 1 つ以上の画像、グラデーション、または <mask> 要素への参照を受け入れます。複数のマスク画像を適用する場合は、カンマで区切ります。

.my-element {
  mask-image: url(my-mask.png),
              linear-gradient(black 0%, transparent 100%);
}

前の例では、PNG 画像と線形グラデーションを使用して .my-element をマスクしています。複数のマスクはデフォルトで加算され、最終的なマスクが作成されます。

上の例は、1 つ以上のマスクが適用された画像を示しています。各マスクを切り替えて、マスクがどのように組み合わされて最終的な効果を生み出すかを確認します。

アルファ マスクと輝度マスク

画像の alpha または luminance を使用してマスクを適用できます。alpha に基づいてマスキングを行う場合、マスク画像の各ピクセルの透明度が要素に適用され、そのピクセルの色情報は無視されます。luminance に基づいてマスキングを行うと、各ピクセルの透明度と値(明るさや暗さ)の両方が要素に適用されます。輝度によるマスキングでは、明るい色は表示され、暗い色は非表示になります。

マスキング モードを設定するには、mask-mode プロパティを使用します。デフォルトでは、mask-mode プロパティは match-source に設定されており、マスク画像のタイプに基づいてモードを設定します。画像とグラデーションの場合、デフォルトは alpha になります。SVG マスクの場合、<mask> 要素の mask-type プロパティの値、または mask-type が定義されていない場合は luminance がデフォルト値になります。

上記の例では、さまざまな色とアルファ値を示すテストパターンがマスクとして使用されています。mask-mode を切り替えると、alpha モードが透明度に基づいているのに対し、luminance モードは色の明るさと透明度の両方に基づいていることがわかります。

その他のマスキング プロパティ

CSS には、マスクの動作を微調整するための追加のプロパティが用意されています。各プロパティは、値のカンマ区切りリストを受け入れます。このリストは、mask-image プロパティで設定されたマスクのリストと照合されます。値の数がマスクの数より少ない場合、各マスクに値が設定されるまでリストが繰り返されます。値がマスクより多い場合、余分な値は破棄されます。

プロパティ 説明
mask-clip

要素マスクのどの参照ボックスを適用するかを設定します。デフォルトは border-box. です

mask-composite

同じ要素に複数のマスクが適用されている場合に、マスク間の相互作用を設定します。デフォルトは add です。

mask-origin

マスクの原点として機能する参照ボックスを設定します。デフォルトは border-box です。これは background-origin と同様に動作し、同じキーワードを受け入れます。

mask-position

mask-origin に対するマスクの相対的な位置を設定します。topcenter などの位置キーワードの値、パーセンテージ、サイズ単位、位置キーワードに関連する値を受け入れます。これは background-position と同様に動作し、同じ引数型を受け入れます。

mask-repeat

マスクされた要素がマスクより大きい場合に、マスクを繰り返す方法を設定します。デフォルトは repeat です。これは background-repeat と同様に動作し、同じ引数型を受け入れます。

mask-size

マスクされた要素のサイズに対するマスクのサイズ変更方法を設定します。デフォルトは auto です。これは background-size と同様に動作し、同じ引数型を受け入れます。

マスクの省略形

マスクのショートハンドを使用すると、複数のマスク プロパティを一度に設定できます。これにより、各マスクのすべてのプロパティをグループ化して、複数のマスクの設定を簡素化できます。マスクのショートハンドは、mask-imagemask-modemask-positionmask-sizemask-repeatmask-originmask-clipmask-composite の順にプロパティを設定することと同じです。すべてのプロパティを含める必要はなく、含まれていないプロパティは初期値にリセットされます。マスクごとに最大 8 つのプロパティをサポートしているため、完全なリファレンスを用意しておくと便利です。

.longhand {
  mask-image: linear-gradient(white, black),
              linear-gradient(90deg, black, transparent);
  mask-mode: luminance, alpha;
  mask-position: bottom left, top right;
  mask-size: 50% 50%, 30% 30%;
}

.shorthand {
  mask: linear-gradient(white, black) luminance bottom left / 50% 50%,
        linear-gradient(90deg, black, transparent) alpha top right / 30% 30%;
}

上記の例では、各クラスに 2 つのマスクが適用されています。1 つ目は個々のプロパティを使用し、2 つ目は mask ショートハンドを使用します。どちらのスタイルも同等です。

フロート要素の周りのフローテキスト

要素をクリップまたはマスクすると、そのボックス内の表示領域のみが変更されますが、ボックス自体は変更されません。つまり、フロート要素は、要素の表示部分ではなく、元のバウンディング ボックスに基づいてドキュメント フローに影響します。要素の周りのフローを定義するには、クリップパスとともに shape-outside プロパティを使用します。

shape-outside プロパティは、コンテンツが要素の周りを流れる形状を定義します。このシェイプは、基本的なシェイプ関数にすることができますが、path() 関数または shape() 関数を使用して定義されたシェイプや、SVG ドキュメントで定義された clipPath にすることはできません。

shape-outside プロパティは、画像またはグラデーションも受け入れます。マスキングと同様に、シェイプの境界線は画像またはグラデーションの透明度によって決まります。shape-image-threshold プロパティは、図形の内側と見なされる透明度のレベルを設定します。

アニメーションの図形

clip-path のアニメーション化

clip-path プロパティをアニメーション化して、シェイプからシェイプへのブレンドを行うことができます。スムーズなアニメーションを作成するには、各キーフレームに同じシェイプ関数を使用する必要があります。polygon() 関数または shape() 関数を使用する場合は、各キーフレームで同じ数のポイントを使用する必要があります。

上記の例では、要素の clip-pathpolygon() 関数を使用して定義された五角形と星形の形状の間で遷移します。この例では、evenodd 塗りつぶしルールを使用して、アニメーション ポイントが重複する領域を作成する方法を示しています。

offset-path を使用したアニメーション

これらのシェイプ関数で作成されたパスに沿って要素をアニメーション化することもできます。offset-path プロパティはパスとして使用する形状を設定し、offset-distance はそのパスに沿った位置を設定します。ray() 関数と offset-path プロパティを使用して、直線上をアニメーション化することもできます。

上記の例では、clip-pathoffset-path の両方に同じポリゴンを使用しています。アニメーションでは、offset-distance を使用して、大きな星が clip-path として使用する同じポリゴンに沿って小さな星を移動します。

理解度を確認する

有効なシェイプ関数は次のうちどれですか?

circle()
正解です。
square()
不正解です。
hexagon()
不正解です。
polygon()
正解です。
rectangle()
不正解です。
inset()
正解です。

正誤問題: path() 関数で定義されたシェイプは、パーセンテージを使用して定義できます

正しい
不正解です。
誤り
正解です。

正誤問題: 要素のクリッピング パスを設定しても、要素の周りのテキストのフローは変更されない

正しい
正解です。
誤り
不正解です。

クリッピング パスとして使用できるのは次のうちどれですか?

基本的な形状
正解です。
SVG clipMask 要素
正解です。
ビットマップ画像
不正解です。
グラデーション
不正解です。

次のうち、マスクとして使用できるものはどれですか?

ビットマップ画像
正解です。
グラデーション
正解です。
SVG マスク要素
正解です。
circle()rect() などの基本図形
不正解です。