모양 컷아웃

웹 기능: 마스크

개요

CSS 마스킹을 사용하면 카드에 노치를 추가하거나 모양이 있는 테두리를 만드는 등 요소를 맞춤 도형으로 클리핑할 수 있습니다. 복잡한 레이아웃을 위해 도형을 결합할 때는 요소에 포함된 콘텐츠 유형에 따라 마스킹 전략을 선택합니다.

마스킹 전략 지원 기기 텍스트 효과
직접 요소 SVG 마스킹 이미지, 아이콘, 장식용 도형, 복잡한 도형 권장하지 않음 (텍스트가 잘릴 수 있음)
인접 요소 SVG 마스킹 텍스트가 포함된 카드, 중요한 콘텐츠 텍스트를 완전히 읽을 수 있음
순수 CSS 그라데이션 간단한 기하학적 도형 권장하지 않음 (텍스트가 잘릴 수 있음)

구현

모양 컷아웃을 구현하려면 다음 단계를 따르세요.

SVG 마스크 사용

SVG 마스크를 사용하면 흰색 (표시) 및 검은색 (숨기기) 채우기를 사용하여 표시 영역에서 빼거나 더하는 도형을 정의할 수 있습니다.

휘도와 알파 마스킹: SVG 마스크는 기본적으로 휘도 (밝기) 모드로 설정되어 있으므로 fill="white"를 사용하여 영역을 표시하고 fill="black"를 사용하여 영역을 잘라냅니다. 색상 대신 SVG의 투명도 (알파 채널)를 사용하려면 CSS에서 mask-type: alpha;를 설정하거나 SVG <mask> 요소에서 mask-type="alpha"를 설정하면 됩니다.

직접 요소 SVG 마스킹

요소 내에 텍스트가 없는 경우 (예: 프로필 아바타, 제품 이미지, 일러스트레이션) SVG 마스크를 요소에 직접 적용할 수 있습니다.

SVG 마스크 내에서 maskContentUnits="objectBoundingBox"를 사용하면 마스크가 적용되는 모든 요소의 너비와 높이에 맞게 자동으로 조정됩니다.

<!-- 1. Define the mask in SVG (hidden from view) -->
<svg width="0" height="0" style="position: absolute;" aria-hidden="true">
  <defs>
    <!-- objectBoundingBox makes the mask scale from 0 to 1 along the element's borders -->
    <mask id="splat-mask" maskContentUnits="objectBoundingBox">
      <!-- Organic Bezier path defining an artistic paint splat shape -->
      <path d="M 0.5 0.05 C 0.58 0.05, 0.58 0.21, 0.67 0.18 C 0.76 0.15, 0.79 0.08, 0.85 0.15 C 0.91 0.22, 0.83 0.32, 0.89 0.38 C 0.95 0.44, 1.03 0.45, 0.99 0.55 C 0.95 0.65, 0.82 0.62, 0.8 0.72 C 0.78 0.82, 0.89 0.92, 0.8 0.97 C 0.71 1.02, 0.64 0.88, 0.55 0.93 C 0.46 0.98, 0.44 1.06, 0.35 1.01 C 0.26 0.96, 0.31 0.81, 0.22 0.79 C 0.13 0.77, 0.01 0.88, 0.01 0.77 C 0.01 0.66, 0.16 0.62, 0.14 0.52 C 0.12 0.42, -0.02 0.39, 0.03 0.29 C 0.08 0.19, 0.23 0.27, 0.29 0.19 C 0.35 0.11, 0.3 0.01, 0.4 0.01 C 0.5 0.01, 0.42 0.05, 0.5 0.05 Z" fill="white" />
    </mask>
  </defs>
</svg>

<!-- 2. Apply the mask to the image element -->
<img src="avatar.jpg" alt="User Profile" class="shaped-avatar">

<style>
.shaped-avatar {
  width: 200px;
  height: 200px;
  object-fit: cover;
  
  /* Apply the SVG mask ID with standard and webkit-prefixed properties */
  -webkit-mask-image: url(#splat-mask);
  mask-image: url(#splat-mask);
}
</style>

인접 요소 SVG 마스킹

텍스트가 포함된 상위 요소가 아닌 인접한 요소에 마스크를 적용합니다. 이렇게 하면 텍스트가 잘리지 않고 읽을 수 있는 상태로 유지됩니다.

이 문제를 해결하려면 구성요소를 두 부분으로 구성된 레이아웃으로 구성합니다.

  1. 읽을 수 있는 모든 콘텐츠를 위한 안전하고 마스킹되지 않은 텍스트 컨테이너 (.card-body)
  2. 맞춤 SVG 마스크를 수신하는 빈 장식용 div (.card-accent)가 옆에 배치됩니다.

두 부분에 동일한 배경 색상을 할당하면 시각적으로 하나의 맞춤형 구성요소로 병합됩니다.

<!-- 1. Define the SVG mask (hidden from view) -->
<svg width="0" height="0" style="position: absolute;" aria-hidden="true">
  <defs>
    <!-- Use objectBoundingBox to make the mask scale with the element -->
    <mask id="accent-stencil" maskContentUnits="objectBoundingBox">
      <!-- Fill the entire area with white (fully visible) -->
      <rect width="1" height="1" fill="white" />
      <!-- Draw a black shape to cut out a concave curve. Extending the path to x=1.1 guarantees it fully clears the right edge, preventing subpixel lines -->
      <path d="M 1.1,0 C 0.4,0.1 0.4,0.9 1.1,1 L 1.1,0 Z" fill="black" />
    </mask>
  </defs>
</svg>

<!-- 2. Create the unified card layout -->
<div class="unified-card">
  <!-- The text-bearing element remains unmasked and perfectly rectangular -->
  <div class="card-body">
    <h3>Premium Membership</h3>
    <p>Get exclusive weekly updates on modern web standards and premium UI designs.</p>
  </div>
  <!-- The empty accent element next to it is masked to form the custom shape -->
  <div class="card-accent"></div>
</div>

<style>
.unified-card {
  display: flex;
  width: 400px;
}

.card-body {
  flex: 1;
  background-color: #1e293b; /* Elegant slate color */
  color: #f8fafc;
  padding: 24px;
  border-top-left-radius: 16px;
  border-bottom-left-radius: 16px;
}

.card-accent {
  width: 60px;
  background-color: #1e293b; /* Same background color so they merge visually without seams */
  border-top-right-radius: 16px;
  border-bottom-right-radius: 16px;

  /* Reference the SVG mask */
  -webkit-mask-image: url(#card-accent-mask);
  mask-image: url(#card-accent-mask);
}
</style>

간단한 컷아웃에 단일 CSS 그라데이션 사용

반원형 상단 노치, 측면 들여쓰기, 직선 대각선 절단과 같은 간단한 기하학적 컷아웃만 필요한 경우 외부 SVG를 작성하거나 참조할 필요가 없습니다. 대신 mask-image 속성 내에서 직접 CSS 방사형 또는 선형 그래디언트를 정의할 수 있습니다.

<div class="gradient-masked-card">
  <h3>Notched Coupon Card</h3>
  <p>This card uses a pure CSS radial gradient to cut out a semi-circular notch along its top edge.</p>
</div>

<style>
.gradient-masked-card {
  background: linear-gradient(135deg, #3b82f6, #1d4ed8);
  color: white;
  padding: 40px 24px 24px 24px; /* Extra top padding ensures content clears the notch */
  border-radius: 16px;
  text-align: center;

  /* radial-gradient places a circle at 50% (horizontal center) and 0% (top edge), cutting out a 20px transparent notch */
  -webkit-mask-image: radial-gradient(circle at 50% 0%, transparent 20px, black 21px);
  mask-image: radial-gradient(circle at 50% 0%, transparent 20px, black 21px);
}
</style>

대체 전략

브라우저가 mask-image 또는 접두사가 붙은 버전을 지원하지 않는 경우:

  • 모양이 있는 이미지: 요소가 점진적으로 저하되어 기본 대체 스타일이 적용된 일반 직사각형 요소로 표시됩니다.
  • 모양이 있는 카드의 경우: 인접한 장식용 .card-accent 요소는 마스크되지 않은 단색 직사각형으로 유지됩니다. 텍스트 컨테이너와 동일한 배경 색상을 공유하므로 전체 카드가 깔끔한 표준 직사각형 컨테이너로 렌더링됩니다.
  • 점진적 개선: 텍스트 레이어를 마스크 외부에 완전히 유지하면 이전 브라우저에서도 콘텐츠를 완전히 읽을 수 있고 구조화되며 액세스할 수 있습니다.