안녕하세요! 프론트엔드 강사입니다.
웹 디자인을 하다 보면 텍스트가 항상 네모반듯한 박스 모양으로만 배치되는 것이 지루하게 느껴질 때가 있죠? 잡지나 신문처럼 동그란 이미지나 불규칙한 모양을 따라 글자들이 유려하게 감싸안듯 흐르게 만들고 싶을 때 사용하는 것이 바로 오늘 배울 CSS Shapes(도형) 입니다!
과거에는 이런 레이아웃을 구현하기가 정말 까다로웠지만, 이제는 CSS 모듈 하나로 마법처럼 해결할 수 있어요. 공식 문서를 꼼꼼히 번역하면서, 여러분이 실무에서 바로 써먹을 수 있는 저만의 꿀팁과 주의사항들도 팍팍 넣어드릴 테니 끝까지 재미있게 따라와 주세요!
CSS 도형(Shapes) 모듈은 CSS에서 기하학적 도형을 묘사하는 방법을 정의합니다. 이 문서는 플로팅(floated)된 요소가 반드시 직사각형일 필요 없이, 다양한 도형 모양을 따라 텍스트가 자연스럽게 감싸도록(wrap) 만드는 방법에 대한 개요를 제공합니다.
보통 요소를 왼쪽으로 플로팅(float: left)하면, 텍스트는 그 요소의 오른쪽과 아래쪽을 따라 네모난 직사각형 형태로 감싸게 됩니다. 하지만 CSS 도형(Shapes)을 사용하면, 예를 들어 원형(circle)을 적용했을 때 텍스트가 직사각형이 아닌 원의 곡선을 따라 부드럽게 감싸게 만들 수 있습니다.
이러한 원을 만드는 데는 여러 가지 방법이 있습니다. 이 가이드에서는 CSS Shapes가 어떻게 작동하고 어떻게 사용하는지 자세히 살펴보겠습니다.
👨🏫 강사님의 핵심 꿀팁:
이 CSS Shapes의 가장 중요하고 절대 잊으면 안 되는 대전제가 하나 있습니다! 반드시float속성과 함께 사용해야 한다는 점입니다. 요소에float: left나float: right를 주지 않으면 아무리 예쁜 도형 속성을 줘도 주변 글자들이 도형을 감싸지 않고 그냥 무시해 버려요. 명심하세요!
shape-margin 속성 (The shape-margin property)clip-path와의 관계 (Relationship to clip-path)이 명세서는 다음과 같은 몇 가지 주요 속성을 정의하고 있습니다:
shape-outside — 기본 도형들을 정의할 수 있게 해줍니다. 텍스트가 밀려나는 '바깥쪽 경계'를 만듭니다.shape-image-threshold — 이미지의 투명도(opacity) 임계값을 설정합니다. 이미지를 사용하여 도형을 정의할 때, 설정한 임계값과 같거나 그보다 더 불투명한 부분만 도형의 영역으로 인정됩니다. 나머지 투명한 부분은 무시되어 글자가 파고들 수 있게 되죠.shape-margin — 정의된 도형 주변에 추가적인 여백(마진)을 설정합니다.우리는 shape-outside 속성을 사용해서 도형을 정의할 수 있습니다. 이 속성은 <basic-shape> 데이터 타입에 명시된 다양한 도형을 정의하는 여러 값들을 취할 수 있습니다.
다음 예제에서는 이미지를 왼쪽으로 플로팅 시켰습니다. 그리고 shape-outside 속성에 circle(50%) 값을 적용했죠. 그 결과, 이미지의 네모난 박스 형태를 따르지 않고 둥근 원형의 곡선을 따라 콘텐츠(텍스트)가 자연스럽게 감싸는 것을 볼 수 있습니다.
<div class="box">
<img
alt="An orange hot air balloon as seen from below"
src="[https://mdn.github.io/shared-assets/images/examples/round-balloon.png](https://mdn.github.io/shared-assets/images/examples/round-balloon.png)" />
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney...
</p>
</div>
body {
font: 1.2em / 1.4 sans-serif;
}
img {
float: left;
shape-outside: circle(50%); /* 이미지 박스 안에 50% 크기의 원형 길을 만듭니다 */
}
위에서 우리는 circle() 함수를 사용했는데, 이는 모든 최신 브라우저에서 잘 지원됩니다. 만약 아직 완벽하게 지원되지 않는 아주 최신 형태의 도형 타입을 사용한다면, 해당 기능을 지원하지 않는 브라우저를 쓰는 사용자에게는 그저 이미지가 플로팅 되어 네모난 모양으로 텍스트가 감싸진 형태(기본 상태)로 보이게 됩니다. 즉, CSS Shapes는 브라우저 지원 여부에 따라 더 나은 시각적 효과를 더해주는 '점진적 향상(progressive enhancement)' 기법으로 아주 안전하게 사용할 수 있습니다.
circle(50%)이라는 값은 기본 도형의 한 예시입니다. 명세서에는 다음과 같은 여러 <basic-shape> 값들이 정의되어 있습니다:
circle() : 원형ellipse() : 타원형inset() : 안쪽으로 오프셋을 준 직사각형path() : SVG와 같은 패스 곡선polygon() : 다각형rect() : 직사각형shape() : 자유로운 형태의 도형xywh() : x, y 좌표와 너비(w), 높이(h)를 사용한 직사각형이 중 세 가지 함수(inset, rect, xywh)는 오직 직사각형만을 정의합니다.
inset() 함수를 사용하면 4개의 오프셋 값(상, 우, 하, 좌)을 정의하여, 감싸고 있는 콘텐츠의 라인 박스들이 기본 요소보다 더 안쪽으로 당겨지게 만들 수 있습니다.
rect() 함수는 포함하고 있는 블록의 상단과 좌측 가장자리로부터의 거리를 지정하여 직사각형을 정의합니다.
xywh() 함수는 참조 상자(reference box)의 상단 및 좌측 가장자리로부터의 거리를 지정하고, 그 시작점으로부터 직사각형의 너비(width)와 높이(height)를 설정하여 작동합니다.
앞서 circle()이 어떻게 원형을 만드는지 보셨을 겁니다. ellipse()는 기본적으로 살짝 눌린 형태의 원(타원)입니다. 만약 이런 기본 도형들로 원하는 모양이 나오지 않는다면 polygon() 함수를 사용해 여러 개의 점을 이어 다각형을 만들 수 있습니다. 더 나아가 path()와 shape() 함수를 사용하면 선, 곡선, 이동 명령어 등을 조합해 그 어떤 복잡한 모양이든 다 만들어낼 수 있습니다!
👨🏫 강사님의 보충설명:
다양한 도형 함수들을 어떻게 작성하는지 궁금하시다면, MDN의 기본 도형 가이드 (Guide to Basic Shapes) 문서를 확인해 보세요. 특히polygon()같은 경우는 손으로 좌표를 찍기 어려우니 구글에 'CSS polygon generator'라고 검색해서 툴을 사용하는 것을 강력 추천합니다!
도형은 CSS의 기준 박스(box value)를 따라 생성될 수도 있습니다. 따라서 다음과 같은 속성값을 이용해 도형을 만들 수 있습니다:
border-boxpadding-boxcontent-boxmargin-box아래 예제에서 border-box 값을 다른 허용되는 값들로 바꾸어 보시면, 도형(텍스트가 밀려나는 경계)이 상자에서 어떻게 더 가까워지거나 멀어지는지 확인할 수 있습니다.
<div class="box">
<div class="shape"></div>
<p>
One November night in the year 1782...
</p>
</div>
body {
font: 1.2em / 1.4 sans-serif;
}
.shape {
background-color: rebeccapurple;
height: 150px;
width: 150px;
padding: 20px;
margin: 20px;
border-radius: 50%;
float: left;
shape-outside: border-box; /* 여기서 padding-box나 margin-box로 바꿔보세요! */
}
이 박스 값들에 대해 더 자세히 알아보고 싶으시다면 박스 값으로부터의 도형 (Shapes from box values) 가이드를 참고하세요.
패스(path)를 생성하는 또 다른 아주 흥미로운 방법은 알파 채널(투명도)을 가진 이미지를 사용하는 것입니다. 이렇게 하면 텍스트가 이미지의 '투명하지 않은' 부분을 감싸게 됩니다. 이 방법을 사용하면 텍스트로 둘러싸인 이미지를 오버레이 하거나, 아예 화면에는 보이지 않는 투명한 이미지를 순전히 복잡한 도형(길)을 만들기 위한 용도로만 활용할 수도 있습니다. 다각형의 점들을 일일이 맵핑할 필요가 없어서 매우 편리하죠!
주의: 이 방법으로 사용되는 이미지는 반드시 CORS 호환성을 만족해야 합니다. 그렇지 않으면 shape-outside 속성은 마치 값이 none인 것처럼 행동하여 도형이 전혀 생성되지 않습니다.
👨🏫 강사님의 꿀팁:
이 부분이 실무에서 진짜 많이 나오는 에러입니다! 외부 호스팅된 이미지(예: S3, CloudFront 등)의 투명도를 이용해shape-outside를 썼는데 안 먹힌다면, 십중팔구 서버 쪽에서 CORS 헤더(Access-Control-Allow-Origin: *) 설정을 안 해줘서 브라우저가 보안상 이미지 데이터를 못 읽기 때문입니다. 이럴 때는 로컬에 이미지를 다운받아 상대경로로 쓰거나 서버 설정을 바꿔주어야 합니다.
다음 예제에서는 완전히 투명한 영역이 있는 이미지를 사용했고, 이 이미지의 URL 값을 shape-outside에 지정했습니다. 도형은 불투명한 영역, 즉 열기구 이미지 모양을 따라 생성됩니다.
<div class="box">
<img
alt="An orange hot air balloon as seen from below"
src="[https://mdn.github.io/shared-assets/images/examples/round-balloon.png](https://mdn.github.io/shared-assets/images/examples/round-balloon.png)" />
<p>
One November night in the year 1782...
</p>
</div>
body {
font: 1.2em / 1.4 sans-serif;
}
img {
float: left;
shape-outside: url("[https://mdn.github.io/shared-assets/images/examples/round-balloon.png](https://mdn.github.io/shared-assets/images/examples/round-balloon.png)");
}
shape-image-threshold 속성shape-image-threshold 속성은 이미지를 기반으로 도형의 영역을 정의할 때, 투명도의 '임계값(threshold)'을 설정하는 데 사용됩니다. shape-image-threshold의 값이 (기본값인) 0.0이라면, 도형으로 인식되지 않는 영역은 완벽하게 100% 투명해야만 합니다. 만약 값이 1.0이라면 완전히 불투명한 영역만 도형으로 인정됩니다. 그 사이의 소수점 값을 사용하면 반투명한 영역을 도형의 경계로 설정할 수도 있습니다.
우리가 그라데이션(gradient)을 사용해서 도형을 정의해 보면 이 임계값이 어떻게 작동하는지 쉽게 이해할 수 있습니다. 아래 예제에서 shape-image-threshold 값을 0.1, 0.8 등으로 바꾸어 보면, 선택한 불투명도 수준에 따라 글자가 파고드는 영역(도형의 형태)이 달라지는 것을 확인할 수 있습니다.
<div class="box">
<div class="shape"></div>
<p>
One November night in the year 1782...
</p>
</div>
body {
font: 1.2em / 1.4 sans-serif;
}
.shape {
float: left;
width: 200px;
height: 200px;
/* 대각선 그라데이션: 보라색에서 시작해 80% 지점에서 투명해짐 */
background-image: linear-gradient(
45deg,
rebeccapurple,
transparent 80%,
transparent
);
/* 보이는 이미지와 똑같은 그라데이션을 모양으로 사용 */
shape-outside: linear-gradient(
45deg,
rebeccapurple,
transparent 80%,
transparent
);
shape-image-threshold: 0.4; /* 불투명도가 40% 이상인 곳까지만 글자를 밀어냄 */
}
이미지로부터 도형을 생성하는 방법에 대해 더 알고 싶으시다면 이미지로부터의 도형 (Shapes from images) 가이드를 참고하세요.
shape-margin 속성 (The shape-margin property)shape-margin 속성은 shape-outside에 설정된 도형 주변으로 마진(여백)을 추가합니다. 이렇게 하면 도형을 감싸는 콘텐츠의 라인 박스들이 도형에서 좀 더 멀어지게 되어 답답해 보이지 않습니다.
아래 예제에서는 기본 도형에 shape-margin을 추가했습니다. 마진 값을 변경해 보면서 기본 도형의 패스에서 텍스트가 어떻게 더 멀리 밀려나는지 확인해 보세요.
<div class="box">
<img
alt="An orange hot air balloon as seen from below"
src="[https://mdn.github.io/shared-assets/images/examples/round-balloon.png](https://mdn.github.io/shared-assets/images/examples/round-balloon.png)" />
<p>
One November night in the year 1782...
</p>
</div>
body {
font: 1.2em / 1.4 sans-serif;
}
img {
float: left;
shape-outside: circle(50%);
shape-margin: 5px; /* 글자와 도형 사이에 5px의 숨통을 트여줍니다 */
}
지금까지의 예제에서는 실제 이미지나 눈에 보이는 HTML 요소를 사용하여 도형을 정의했기 때문에 화면에 그 도형이 보였습니다. 하지만 가끔은 네모나지 않은 안 보이지 않는 투명한 선을 따라서 텍스트가 흐르게만 만들고 싶을 때도 있죠. 이를 위해 DOM에 비어있는 <div>나 <span>을 추가한 뒤 플로팅 시키고 안 보이게 만들 수도 있겠지만, 대신에 생성된 콘텐츠(generated content)인 가상 요소(::before, ::after)를 사용하면 HTML을 더럽히지 않고 모든 스타일링 로직을 CSS 안에 깔끔하게 유지하면서 도형을 만들 수 있습니다.
아래 예제에서는 가상 요소를 생성하여 높이와 너비를 150px로 삽입합니다. 그런 다음 기본 도형, 박스 값, 또는 이미지의 알파 채널 등을 사용해 텍스트가 감싸안을 수 있는 투명한 형태의 길을 만들어냅니다.
<div class="box">
<p>
One November night in the year 1782...
</p>
</div>
body {
font: 1.2em sans-serif;
}
.box::before {
content: ""; /* 가짜 요소를 만들어냅니다 */
display: block;
height: 150px;
width: 150px;
padding: 20px;
margin: 20px;
border-radius: 50%;
float: left; /* 반드시 플로팅! */
shape-outside: border-box; /* 가상 요소의 둥근 border-box를 따라 글자가 감싸집니다 */
}
clip-path와의 관계 (Relationship to clip-path)CSS Shapes를 만들 때 사용되는 기본 도형과 박스 값들은 clip-path 속성에 사용되는 값들과 완전히 동일합니다. 따라서, 이미지를 사용해 주변 글자를 밀어내는 도형(shape-outside)을 만들면서 동시에 그 이미지 자체도 똑같은 모양으로 잘라내고(clip-path) 싶다면, 동일한 함수와 값을 재사용할 수 있습니다.
👨🏫 강사님의 꿀팁:
많이 헷갈려 하시는 개념인데요!
shape-outside= 주변의 텍스트(다른 요소들)를 밀어내는 보이지 않는 방어막을 만듭니다. 요소 자체의 모습은 그대로입니다.clip-path= 요소 자체의 모습을 가위로 잘라버립니다. 잘려나간 빈 공간으로 다른 글씨가 파고들진 않습니다.
따라서 이미지를 동그랗게 자르고(clip-path) 글씨도 동그랗게 밀어내고(shape-outside) 싶다면 두 가지를 동시에 써주어야 합니다!
아래 이미지는 원래 파란색 배경을 가진 네모난 이미지입니다. 우리는 shape-outside: ellipse(40% 50%);를 사용해 텍스트를 타원형으로 밀어내는 길을 정의했고, 동시에 clip-path: ellipse(40% 50%);를 사용해 이미지 자체도 도형 길과 똑같은 타원형 모양으로 싹둑 잘라내었습니다.
<div class="box">
<img
alt="An orange hot air balloon as seen from below"
src="[https://mdn.github.io/shared-assets/images/examples/balloon-small.jpg](https://mdn.github.io/shared-assets/images/examples/balloon-small.jpg)" />
<p>
One November night in the year 1782...
</p>
</div>
body {
font: 1.2em / 1.4 sans-serif;
}
img {
float: left;
shape-outside: ellipse(40% 50%); /* 텍스트를 밀어내는 보이지 않는 타원형 방어막 */
clip-path: ellipse(40% 50%); /* 이미지 자체를 타원형으로 자르기 */
}
Firefox 개발자 도구(DevTools)에는 훌륭한 Shape Path Editor (도형 패스 편집기)가 내장되어 있습니다. 이 도구를 사용하면 circle(), inset(), ellipse(), polygon() 값들을 화면 위에서 직접 인스펙트(검사) 할 수 있어요. 만약 여러분이 작성한 다각형 모양이 조금 어긋났다면, 이 Shapes Editor를 마우스로 드래그해서 예쁘게 모양을 다듬은 다음, 완성된 새로운 수치 값을 복사해서 여러분의 CSS 파일에 붙여넣기만 하면 됩니다!
이 가이드에서는 플로팅 된 요소 주변으로 텍스트를 감싸는 기초적인 내용들을 다뤘습니다. CSS 도형 모듈(CSS shapes module)로 이동하시면 도형과 관련된 추가 기능들, 모든 도형 함수, 그리고 상세한 가이드 링크들을 모두 확인하실 수 있습니다.
이 페이지가 도움이 되었나요? (Was this page helpful to you?)
[예 (Yes)]
[아니요 (No)]
이 페이지는 MDN 기여자들에 의해 2025년 12월 16일에 마지막으로 수정되었습니다.
어떠셨나요? 이제 CSS Shapes를 활용해서 천편일률적인 네모 박스 레이아웃에서 벗어나 매거진처럼 감각적이고 유려한 웹 페이지를 만드실 수 있을 거예요! 항상 float 속성과 세트로 다닌다는 점, clip-path와 조합하면 금상첨화라는 점만 잊지 마세요. 질문이 있으시다면 언제든 남겨주세요!