안녕하세요! 프론트엔드 강사입니다.
오늘은 CSS Shapes의 꽃이라고 할 수 있는 '이미지를 활용한 셰이프 만들기(Shapes from images)'에 대해 MDN 문서를 통해 자세히 알아보겠습니다.
이전 시간에 기본 도형(circle, polygon 등)으로 글씨를 밀어내는 방법을 배웠다면, 오늘은 배경이 투명한 PNG 이미지나 심지어 CSS 그라데이션 자체를 '틀(틀)'로 삼아서 그 모양 그대로 텍스트가 감싸도록 만드는 마법 같은 기법을 배울 거예요. 복잡한 다각형의 좌표를 일일이 계산할 필요가 없어서 실무에서 디자이너의 독특한 요구사항을 맞출 때 정말 유용하게 쓰인답니다!
이 가이드에서는 알파 채널(투명도)이 있는 이미지 파일이나 심지어 CSS 그라데이션(Gradient)을 사용하여 어떻게 도형을 생성할 수 있는지 살펴볼 것입니다. 이것은 도형을 만드는 매우 유연하고 편리한 방법입니다. CSS에서 복잡한 다각형(polygon())의 패스를 좌표로 일일이 그리는 대신, 그래픽 프로그램(포토샵, 일러스트레이터 등)에서 원하는 모양을 만든 다음, 특정 임계값(threshold)보다 덜 투명한 픽셀들이 만들어내는 형태를 그대로 가져다 쓸 수 있습니다.
이미지를 사용해 도형을 만들려면, 그 이미지는 반드시 완전히 불투명하지 않은 영역, 즉 '알파 채널(Alpha Channel)'을 가지고 있어야 합니다. (대표적으로 배경이 투명한 PNG나 WebP 파일이 여기에 속합니다.)
이때 shape-image-threshold 속성을 사용하여 이 투명도에 대한 '임계값(기준점)'을 설정하게 됩니다. 우리가 설정한 이 값보다 '더 불투명한(more opaque)' 픽셀들만이 도형의 면적을 계산하는 데 사용됩니다. (나머지 투명한 부분으로는 텍스트가 파고들어 가게 되죠.)
아래 예제를 보면, 빨간색으로 꽉 찬 영역과 완전히 투명한 영역으로 이루어진 별 모양의 이미지가 있습니다. 이 이미지 파일의 경로를 shape-outside 속성의 값으로 사용하면, 콘텐츠(텍스트)가 별 모양의 가장자리를 따라 예쁘게 감싸게 됩니다.
<div class="box">
<img
alt="A red star"
src="[https://mdn.github.io/shared-assets/images/examples/star-shape.png](https://mdn.github.io/shared-assets/images/examples/star-shape.png)" />
<p>
One November night in the year 1782, so the story runs, two brothers sat...
</p>
</div>
body {
font: 1.2em / 1.5 sans-serif;
}
img {
float: left; /* 도형을 만들려면 무조건 float이 필요합니다! */
/* 이미지의 불투명한 별 모양을 따라 글씨를 밀어냅니다. */
shape-outside: url("[https://mdn.github.io/shared-assets/images/examples/star-shape.png](https://mdn.github.io/shared-assets/images/examples/star-shape.png)");
}
또한, shape-margin 속성을 사용하면 생성된 도형과 텍스트 사이에 마진(여백)을 주어 텍스트를 도형으로부터 조금 더 멀리 밀어낼 수 있습니다.
img {
float: left;
shape-outside: url("[https://mdn.github.io/shared-assets/images/examples/star-shape.png](https://mdn.github.io/shared-assets/images/examples/star-shape.png)");
shape-margin: 20px; /* 별 모양과 글자 사이에 20px의 안전거리를 만듭니다 */
}
이미지로 도형을 만들 때 여러분이 반드시 부딪히게 될 중요한 문제가 하나 있습니다. 바로 여러분이 사용하는 이미지가 반드시 CORS 호환성 (CORS compatible)을 만족해야 한다는 것입니다.
여러분의 웹사이트와 동일한 도메인(Same-origin)에 호스팅된 이미지라면 문제없이 잘 작동합니다. 하지만, CDN이나 외부 이미지 호스팅 서버 등 다른 도메인에 있는 이미지를 불러와서 사용한다면, 해당 서버가 도형 생성에 이미지를 사용할 수 있도록 올바른 CORS 헤더(Access-Control-Allow-Origin)를 보내주고 있는지 확인해야 합니다.
이러한 CORS 호환성 요구사항 때문에, 로컬 웹 서버(localhost)를 띄우지 않고 단순히 컴퓨터에 있는 HTML 파일을 브라우저로 열어서(file:// 프로토콜) 테스트할 경우에는 도형 기능이 작동하지 않습니다.
브라우저의 개발자 도구(DevTools)가 CORS 에러를 식별하는 데 큰 도움을 줍니다. Chrome의 경우, 개발자 도구의 콘솔(Console) 창에 CORS 문제에 대한 경고가 빨간색으로 뜹니다. Firefox의 경우, 요소를 검사(Inspect)해 보면 해당 이미지를 로드할 수 없다는 알림이 표시됩니다. 이를 통해 여러분은 "아하, CORS 정책 때문에 이 이미지를 도형의 소스로 쓸 수 없구나!"라고 원인을 파악할 수 있습니다.
👨🏫 강사님의 꿀팁:
실무에서 진짜 많이 겪는 에러입니다. 이미지는 화면에 멀쩡히 잘 보이는데 유독shape-outside만 안 먹히거든요. 그 이유는 브라우저가 화면에 이미지를 '단순히 그리는 것'은 허용하지만, 자바스크립트나 CSS가 픽셀 데이터를 '읽어서 분석하는 것(도형의 투명도 계산 등)'은 해킹의 위험이 있어서 CORS 정책으로 엄격하게 막아두었기 때문입니다. 외부 이미지라면 서버 세팅을 꼭 확인하세요!
shape-image-threshold 속성을 사용하면 완전히 투명하지 않은 반투명한 영역으로부터도 도형을 생성해 낼 수 있습니다.
shape-image-threshold의 값이 (기본값인) 0.0이라면, 도형 밖으로 텍스트가 파고들기 위해서는 해당 영역이 '완전히 100% 투명'해야만 합니다. 1.0이라면, 영역이 '완전히 100% 불투명'해야만 도형의 뼈대로 인정받습니다. 아래 예제를 보면, 그래픽 프로그램에서 별의 배경을 완전히 투명하게 지우지 않고 20%의 불투명도를 남겨두었습니다. 이 상태에서 shape-image-threshold를 0.2 이상의 값으로 설정하면 그 20%의 옅은 배경이 무시되고 별 모양이 드러나지만, 0.2보다 작은 값(예: 0.1)으로 설정하면 20%의 배경조차도 도형으로 인식되어 글자가 파고들지 못하고 그냥 네모난 모양으로 감싸게 됩니다.
img {
float: left;
shape-outside: url("[https://mdn.github.io/shared-assets/images/examples/star-red-20.png](https://mdn.github.io/shared-assets/images/examples/star-red-20.png)");
/* 이미지의 불투명도가 20% 이하인 부분은 다 깎아내고(투명 취급),
그보다 진한 부분만 도형으로 인정합니다 */
shape-image-threshold: 0.2;
}
위의 예제들에서는 shape-outside의 값으로 이미지를 사용함과 동시에, HTML의 <img> 태그를 이용해 그 이미지를 화면에 실제로 출력했습니다. 많은 데모 예제들이 우리가 텍스트를 감싸려고 하는 도형의 모양을 시각적으로 보여주기 위해 이렇게 구성합니다.
하지만, shape-outside 속성은 화면에 실제로 표시되는 이미지와 직접적인 연관이 없습니다! 즉, 이미지를 기반으로 도형의 '틀(길)'을 만들기 위해 반드시 그 이미지를 화면에 띄울 필요는 없다는 뜻입니다.
도형을 적용하기 위해 무언가 '플로팅(float)'되는 요소는 반드시 필요합니다. 하지만 아래 예제처럼 화면에 보이지 않는 생성된 콘텐츠 (generated content, 가상 요소)를 활용할 수 있습니다. 저는 가상 요소를 플로팅 시키고 커다란 별 이미지를 사용해서 콘텐츠의 모양을 잡았지만, 정작 그 별 이미지는 화면 그 어디에도 보이지 않도록 만들었습니다.
.box::before {
content: ""; /* 가상 요소 생성 */
float: left; /* 모양을 만들려면 float 필수! */
width: 400px;
height: 300px;
/* 화면엔 안 보이지만, 텍스트를 별 모양으로 밀어내는 '투명한 방어막'을 만듭니다. */
shape-outside: url("[https://mdn.github.io/shared-assets/images/examples/star-shape.png](https://mdn.github.io/shared-assets/images/examples/star-shape.png)");
shape-image-threshold: 0.3;
}
👨🏫 강사님의 꿀팁:
이 테크닉은 "글씨가 구불구불한 뱀 모양을 따라 흘러가게 해 주세요" 같은 디자이너의 무리한(?) 요구를 받았을 때 구세주가 됩니다. 구불구불한 투명 PNG 라인을 그려서 가상 요소에shape-outside로 먹여놓고 화면엔 숨기면 텍스트만 기가 막히게 휘어지는 연출을 할 수 있어요!
CSS 그라데이션(CSS gradient) 역시 내부적으로는 하나의 '이미지'로 취급됩니다. 따라서 그라데이션의 일부분을 투명하거나 반투명하게 만들면, 그 그라데이션을 사용해서 도형(shape)을 생성해 낼 수 있습니다.
다음 예제에서는 가상 요소를 사용했습니다. 이 가상 요소를 플로팅시키고, background-image로 선형 그라데이션(linear gradient)을 주었습니다. 그리고 똑같은 그라데이션 값을 shape-outside의 값으로도 사용했죠.
이 선형 그라데이션은 보라색에서 시작해서 점점 투명해집니다. 여기서 shape-image-threshold 값을 조절하면, 픽셀이 얼마나 투명해졌을 때부터 글자가 파고들게 할지 그 경계선을 마음대로 정할 수 있습니다. 값을 바꿔보시면 대각선 경계가 그라데이션을 따라 어떻게 이동하는지 확인하실 수 있습니다.
(물론 background-image 속성을 아예 지워버리고, 그라데이션을 오직 텍스트를 밀어내는 '투명한 대각선 벽' 용도로만 사용할 수도 있습니다.)
.box::before {
content: "";
float: left;
height: 250px;
width: 400px;
/* 시각적으로 보이는 배경 그라데이션 */
background-image: linear-gradient(
to bottom right,
rebeccapurple,
transparent
);
/* 글씨를 밀어내는 방어막용 그라데이션 */
shape-outside: linear-gradient(to bottom right, rebeccapurple, transparent);
shape-image-threshold: 0.3; /* 이 수치를 바꾸면 글씨가 파고드는 각도가 달라집니다! */
}
다음 예제는 방사형 그라데이션(radial gradient)과 타원형(ellipse)을 사용했으며, 마찬가지로 그라데이션의 투명한 부분을 활용해 도형을 만들었습니다.
.box::before {
content: "";
float: left;
height: 250px;
width: 400px;
background-image: radial-gradient(
ellipse closest-side,
rebeccapurple,
blue 50%,
transparent
);
shape-outside: radial-gradient(
ellipse closest-side,
rebeccapurple,
blue 50%,
transparent
);
shape-image-threshold: 0.3;
}
제공해 드린 라이브 예제들에서 수치를 직접 요리조리 바꿔보시면, 그라데이션의 형태가 변함에 따라 텍스트가 밀려나는 도형의 형태도 어떻게 함께 변하는지 확실하게 감을 잡으실 수 있을 겁니다!
이 페이지가 도움이 되었나요? (Was this page helpful to you?)
[예 (Yes)]
[아니요 (No)]
이 페이지는 MDN 기여자들에 의해 2025년 11월 7일에 마지막으로 수정되었습니다.
오늘 학습은 여기까지입니다! 이제 투명한 배경을 가진 이미지나 그라데이션만 있으면 그 어떤 복잡한 형태의 텍스트 레이아웃도 척척 만들어내실 수 있을 거예요. 실무에 적용해 보시고 더 궁금한 점이 생기면 언제든 질문해 주세요!