카드 가장자리 밖으로 튀어나온 이미지 주위로 문단 텍스트를 감싸려면 이미지에 float을 적용하고 바깥쪽 여백을 음수로 설정하세요. 곡선 윤곽을 만들려면 shape-outside를 추가하세요. 이 튜토리얼에서는 Mac의 Safari에서 열 수 있는 완전한 로컬 예제를 만듭니다.
이미지가 컨테이너와 겹칠 때 텍스트가 감싸도록 하려면 어떻게 해야 하나요?
이미지가 문단의 float 레이아웃에 참여해야 합니다. CSS float는 요소를 컨테이너 한쪽에 배치하고 인접한 텍스트가 그 옆을 따라 흐르게 합니다. 이 예제에서는 오른쪽 float을 적용해 텍스트가 이미지 왼쪽과 아래로 흐르도록 합니다. MDN: float.
결과를 제어하는 요소는 세 가지입니다. float은 텍스트가 감싸는 동작을 만들고, 음수 오른쪽 여백은 이미지가 컨테이너 밖으로 튀어나오게 하며, shape-outside은 주변 텍스트가 따라갈 윤곽을 정의합니다. 일반 float은 직사각형 모양으로 텍스트를 감싸고, 도형을 사용하면 각 줄이 원을 따라가게 할 수 있습니다. MDN: shape-outside.
이미지를 시각적으로 이동하는 것만으로는 충분하지 않습니다. 절대 위치가 지정된 이미지는 일반 흐름에서 공간을 차지하지 않으므로 주변 요소는 이미지가 없는 것처럼 동작합니다. 변환은 일반 문서 흐름을 재배치하지 않은 채 렌더링된 위치를 바꿉니다. 따라서 position: absolute 또는 transform: translateX(...)로 배치한 이미지가 텍스트를 덮을 수 있습니다. MDN: position, MDN: CSS 변환 사용하기.
여기서 다루는 작업은 구체적입니다. 원형 이미지 하나가 텍스트 카드의 오른쪽 가장자리를 넘어가고, 카드의 문단은 원의 왼쪽 윤곽을 따라갑니다. 이미지와 문단은 같은 텍스트 감싸기 영역에 속합니다.
Mac에서 완전한 예제 만들기
일반 텍스트 코드 편집기에서 overlap-wrap.html라는 파일을 만드세요. 아래의 전체 문서를 붙여 넣고 저장한 다음 Safari에서 여세요. 예제에는 데이터 URL로 포함된 추상 SVG 이미지가 있으므로 설치해야 할 이미지 파일, 패키지 또는 빌드 도구가 없습니다.
float이 적용된 이미지는 영향을 주어야 할 문단보다 앞에 옵니다. float의 위치는 문서에서 앞서 나오는 콘텐츠의 영향을 받으므로 이 배치가 중요합니다. 제목을 float보다 앞에 두면 제목이 카드의 전체 텍스트 너비를 사용할 수 있습니다. W3C: 시각적 형식 지정 모델.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Overlapping image and paragraph wrapping</title>
<style>
* { box-sizing: border-box; }
body {
margin: 0;
padding: 32px 96px 32px 32px;
background: #eef1f5;
color: #243247;
font: 18px/1.65 system-ui, sans-serif;
}
.card {
display: flow-root;
width: 100%;
max-width: 640px;
margin: 0 auto;
padding: 24px;
background: white;
box-shadow: 0 0 0 1px #cbd3df;
overflow: visible;
}
.card h2 {
margin: 0 0 16px;
font-size: 26px;
line-height: 1.25;
}
.card p { margin: 0 0 16px; }
.card p:last-child { margin-bottom: 0; }
.art {
display: block;
float: right;
width: 240px;
height: 240px;
margin: 0 -88px 16px 16px;
border-radius: 50%;
shape-outside: circle(50%) border-box;
shape-margin: 16px;
}
@media (max-width: 760px) {
body { padding: 16px; }
.art {
float: none;
width: min(240px, 100%);
height: auto;
margin: 0 auto 24px;
shape-outside: none;
}
}
</style>
</head>
<body>
<article class="card">
<h2>Study A: circles and spacing</h2>
<img class="art" width="240" height="240" alt=""
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240' viewBox='0 0 240 240'%3E%3Crect width='240' height='240' fill='%233a628b'/%3E%3Ccircle cx='90' cy='85' r='60' fill='%23b9d8eb'/%3E%3Ccircle cx='165' cy='170' r='45' fill='%238db5cc'/%3E%3C/svg%3E">
<p>Panel A pairs a circular graphic with a continuous passage of
sample text. Follow the right edge of this paragraph as each
line approaches the curved outline. Near the widest part of
the circle, the available space becomes narrower.</p>
<p>Panel B continues the same passage with a second paragraph.
The graphic extends into the outer gutter while the words
remain inside the white card. As the contour curves inward,
later lines can use more of the available width.</p>
<p>Panel C provides enough additional text to show the transition
below the graphic. Once the passage continues beyond the
wrapping region, its lines return to the full content width.
Resize the window to compare the desktop arrangement with
the stacked layout used in a narrower window.</p>
</article>
</body>
</html>
뷰포트 너비가 760px보다 크면 원형 그래픽이 오른쪽 거터로 튀어나오고 문단 줄이 그래픽 왼쪽을 따라가는 것이 의도된 결과입니다. 760px 이하에서는 이미지가 문단 위에 가운데 정렬된 블록으로 표시됩니다. 이 중단점은 설명을 위한 디자인 선택입니다. @media는 쿼리가 일치할 때 중괄호 안의 선언을 적용합니다. MDN: @media.
예제 그래픽은 장식용이므로 이미지 요소에 alt=""을 사용합니다. 정보 전달 기능이 있는 그래픽으로 바꾼다면 적절한 텍스트 대체 항목을 제공하세요. WHATWG는 장식용 이미지와 정보를 텍스트로 대체해야 하는 이미지를 구분합니다. WHATWG: 이미지의 대체 텍스트 제공 요건.
겹치는 부분과 텍스트 간격은 어떻게 정하나요?
먼저 이미지 위치를 정한 다음 윤곽을 조정하세요. 오른쪽 float은 여백 상자를 기준으로 배치됩니다. 이 예제에서는 음수 오른쪽 여백으로 이미지의 오른쪽 가장자리를 카드 콘텐츠 가장자리보다 88px 더 바깥에 배치합니다. 카드의 오른쪽 패딩은 24px이므로 이미지가 흰색 배경 밖으로 튀어나오는 길이는 64px입니다. 이는 CSS 픽셀 단위로 측정한 이 예제의 계산된 치수입니다. W3C: float 배치.
| 항목 | 예시 값 | 계산 또는 용도 |
|---|---|---|
| 이미지 너비 | 240px |
표시되는 원의 지름 |
| 콘텐츠 가장자리에서 바깥쪽으로 이동한 거리 | 88px |
음수 오른쪽 여백의 크기 |
| 카드 패딩 | 24px |
콘텐츠 가장자리와 배경 가장자리 사이의 간격 |
| 배경 밖으로 보이는 부분 | 64px |
88 − 24 |
| 콘텐츠 영역 안에 남는 이미지 너비 | 152px |
240 − 88 |
| 직사각형 대체 레이아웃에서 확보하는 공간 | 168px |
왼쪽 여백을 포함한 240 − 88 + 16 |
레이아웃을 직접 만들 때는 원하는 튀어나온 길이에 컨테이너의 오른쪽 패딩을 더해 음수 여백의 크기를 계산하세요. 예를 들어 패딩이 24px이고 이미지가 40px 튀어나오게 하려면 오른쪽 여백을 -64px로 설정합니다. 이미지를 키우거나 컨테이너 너비를 줄일 때마다 텍스트가 들어갈 너비를 다시 확인하세요.
원형 버전은 도형의 기하 형태가 정사각형 이미지 상자를 따르도록 shape-outside: circle(50%) border-box를 사용합니다. 비대칭 여백이 여백 상자를 바꾸므로 여기서는 border-box을 명시적으로 선택하는 것이 유용합니다. 기준 상자를 명시하지 않으면 기본 도형은 margin-box을 기준으로 합니다. MDN: shape-outside를 사용한 기본 도형.
shape-margin: 16px는 텍스트가 감싸는 윤곽 주위에 간격을 추가합니다. 양수 왼쪽 여백은 텍스트와 맞닿는 쪽에 그 간격을 위한 공간을 제공합니다. 도형과 도형 여백은 float의 여백 상자 안으로 잘리므로 shape-margin만 늘려도 텍스트 감싸기 영역을 무한히 확장할 수는 없습니다. 음수 오른쪽 여백은 바깥쪽에서 도형을 자르지만, 이 예제에서는 그쪽에 문단 텍스트가 없습니다. W3C: CSS Shapes Module Level 1.
직사각형 이미지의 경우 border-radius를 0로, shape-outside을 none로, shape-margin을 0로 바꾸세요. float과 여백은 그대로 둡니다. 그러면 같은 바깥쪽 배치를 유지하면서 직선으로 텍스트를 감쌉니다. 원형 자르기는 유지하고 도형만 제거하면 그림은 원형이지만 텍스트가 확보하는 공간은 직사각형입니다.
텍스트 감싸기에 영향을 주는 컨테이너 경계는 무엇인가요?
카드에 display: flow-root를 사용하면 float을 세로 방향으로 포함하는 블록 서식 맥락이 만들어집니다. 따라서 텍스트가 짧더라도 카드 높이에 이미지가 반영됩니다. 또한 이 텍스트 감싸기 영역을 외부 float과 분리합니다. MDN: 블록 서식 맥락.
문단은 해당 영역 안에서 일반 블록 흐름을 유지하세요. 이미지가 flex 또는 grid의 직접 자식이면 float으로 이와 같은 문단 텍스트 감싸기 레이아웃을 만들 수 없습니다. 마찬가지로 별도의 문단 래퍼에 자체 블록 서식 맥락을 만들면 외부 float이 해당 래퍼의 콘텐츠에 영향을 주지 않습니다. 바깥쪽 grid로 카드 전체를 배치하더라도 카드 내부에는 흐름 레이아웃을 사용할 수 있습니다. MDN: 블록 서식 맥락.
잘림 여부도 따로 확인하세요. 예제에서는 튀어나온 부분이 표시되도록 overflow를 visible로 둡니다. float을 포함하기 위해 overflow를 사용하면 잘림이나 스크롤 막대가 생길 수 있습니다. flow-root를 사용하면 그런 선택 없이도 float을 포함할 수 있습니다. 이미지가 조상 요소의 가장자리에서 정확히 사라진다면 상위 컴포넌트도 확인하세요. MDN: 내부 float 포함하기.
CSS Shapes에는 방향에 따른 경계도 있습니다. 오른쪽 float은 왼쪽에서 텍스트를 감싸고, 왼쪽 float은 오른쪽에서 텍스트를 감쌉니다. float 하나로 가운데 이미지 양쪽에 텍스트가 흐르는 통로를 만들 수는 없습니다. 이 작업에는 가장자리 float이 적합한 배치입니다. W3C: CSS Shapes와 float 동작.
Tailwind CSS에서도 이 방법을 사용할 수 있나요?
네. 기존 Tailwind 프로젝트에서 float-right은 float: right를 적용하고, float-none은 float을 제거합니다. 이 유틸리티는 Tailwind가 제공하며 텍스트 레이아웃은 브라우저가 처리합니다. Tailwind CSS: float.
윤곽 선언에는 Tailwind의 임의 속성 문법으로 [shape-outside:circle(50%)_border-box]과 [shape-margin:16px]를 표현할 수 있습니다. 밑줄은 border-box 앞의 공백을 나타냅니다. 이 코드는 이미 설정된 Tailwind 프로젝트에 사용하는 클래스 이름 일부이며, 위의 전체 문서를 대체하지 않습니다. 이를 적용할 때도 같은 치수, 여백, 컨테이너 레이아웃과 좁은 창에서의 초기화 설정을 유지하세요. Tailwind CSS: 사용자 지정 스타일 추가하기.
텍스트 감싸기가 이상하게 보일 때는 어떻게 진단하나요?
로컬 예제를 기준으로 삼고 기존 스타일을 한 번에 하나씩 적용해 보세요. 다음 순서로 레이아웃을 좌우하는 조건을 확인할 수 있습니다.
- 먼저 직사각형 감싸기를 확인하세요.
shape-outside: none을 임시로 설정합니다. 텍스트가 여전히 그림 아래로 흐르면 이미지가 float인지, 절대 위치인지, 아니면 flex/grid의 직접 자식인지 확인하세요. - 문서 순서를 확인하세요. 감싸기가 필요한 문단 앞에 float을 배치합니다.
- 텍스트 감싸기 영역을 확인하세요. float과 문단 콘텐츠가 같은 블록 서식 맥락 안에 있도록 하고, 문단 래퍼에 불필요하게 별도의 맥락을 만드는 설정은 제거하세요.
- 윤곽을 확인하세요. 원형 도형과 명시적인
border-box기준 상자를 복원합니다. 원형으로 자르기 전에 표시할 이미지가 정사각형인지 확인하세요. - 거터를 확인하세요. 뷰포트 너비를 늘리고 카드나 조상 요소에서 잘리는지 살펴봅니다. 페이지 바깥쪽 공간이 튀어나온 부분을 수용하기에 충분한지 확인하세요.
- 좁은 레이아웃을 확인하세요. 예제의 중단점을 지나도록 크기를 조절하고 float과 음수 여백이 모두 초기화되는지 확인하세요.
이 확인 방법은 float 배치, 서식 맥락, 도형 기준 상자의 문서화된 규칙에 따릅니다. 특정 줄을 수정하려고 수동 줄바꿈을 추가하지 마세요. 그러면 한 가지 창 크기에만 맞는 문단이 됩니다.
MDN에 따르면 shape-outside은 널리 사용할 수 있지만, 일부 구문은 지원 여부가 다를 수 있습니다. 이 예제에서는 문서화된 circle() 형식을 사용합니다. 지원하려는 Mac 브라우저에서 페이지를 비교하되 줄바꿈이 완전히 같을 필요는 없으며 여백과 가독성을 살펴보세요. 도형 선언을 사용할 수 없는 환경에서도 float은 직사각형으로 텍스트를 감쌉니다. MDN: shape-outside.
완성된 레이아웃에서는 이미지 크기와 튀어나온 길이를 함께 정하고, 문단이 들어갈 너비를 충분히 확보하며, 세로로 쌓이는 대체 레이아웃을 유지하세요. 치수가 맞으면 도형으로 이미지 주위 간격을 다듬으세요. 이렇게 하면 텍스트나 사용 가능한 너비가 바뀌어도 문단이 다시 흐릅니다.
출처
- float CSS 속성 — MDN Web Docs.
- shape-outside CSS 속성 — MDN Web Docs.
- position CSS 속성 — MDN Web Docs.
- CSS 변환 사용하기 — MDN Web Docs.
- 시각적 형식 지정 모델 — W3C.
- @media CSS at 규칙 — MDN Web Docs.
- HTML 표준: 이미지 — WHATWG.
- shape-outside를 사용한 기본 도형 — MDN Web Docs.
- CSS Shapes Module Level 1 — W3C.
- 블록 서식 맥락 — MDN Web Docs.
- float — Tailwind CSS.
- 사용자 지정 스타일 추가하기 — Tailwind CSS.