결과가 두 배로 커지거나, 확대하면 뭉개지거나, 아래에 빈 공간이 붙는 문제는 대부분 한 지점에서 갈라집니다. 레이아웃을 계산하는 단위와 이미지에 저장되는 단위가 다르기 때문입니다.

1. CSS 픽셀과 이미지 픽셀은 다릅니다

폭 입력란에 적는 숫자는 CSS 픽셀 단위의 브라우저 창 폭입니다. 1000을 넣는 것은 가로 1000px 창에서 페이지를 여는 것과 같고, 미디어 쿼리와 %, rem, vw가 이 좌표계 위에서 계산됩니다.

반면 캡처 단계의 픽셀 밀도는 2입니다. CSS 픽셀 한 칸이 가로세로 2개씩의 실제 픽셀로 기록되므로, 결과 PNG의 가로는 항상 설정 폭의 정확히 두 배가 됩니다.

설정 폭 1000 CSS px × 2 = 출력 PNG 가로 2000 px 문서 높이 800 CSS px × 2 = 출력 PNG 세로 1600 px 저장되는 픽셀 수: 1000 × 800 이 아니라 2000 × 1600 (= 4배)

레이아웃은 1000px 기준을 유지한 채 픽셀 격자만 촘촘해지므로 글자 획과 1px 테두리가 더 많은 픽셀로 그려집니다.

그런데도 흐릿하다면

텍스트와 CSS 도형은 그 밀도로 다시 그려지지만, <img>로 넣은 사진과 로고는 원본 비트맵을 확대할 뿐입니다. 300px로 표시할 이미지는 출력에서 600px을 차지하므로, 표시 크기의 2배 이상 해상도인 원본을 CSS로 줄여 써야 합니다. 글자 모양 자체가 의도한 서체와 다르게 나오는 것은 해상도가 아니라 서체 문제이며, 한글 폰트가 깨지는 이유와 해결 방법에서 따로 다룹니다.

2배 밀도를 역이용하기

렌더링 시점의 devicePixelRatio는 2이고, (min-resolution: 2dppx)-webkit-min-device-pixel-ratio: 2 미디어 쿼리가 모두 참이 됩니다. 즉 브라우저는 이 페이지를 고밀도 화면으로 인식합니다. 그래서 srcset에 밀도 서술자를 붙여 두면 캡처할 때 2배 이미지가 자동으로 선택되고, 표시 크기는 밀도로 나눈 값이 되어 레이아웃은 그대로 유지됩니다.

<img src="https://example.com/logo.png"
     srcset="https://example.com/logo.png 1x,
             https://example.com/logo@2x.png 2x"
     width="300" alt="브랜드 로고">

CSS 배경 이미지에는 image-set()이 같은 역할을 합니다. 어느 쪽이든 주소는 모두 절대 https:// 주소여야 합니다. HTML 옆에 둔 파일을 가리키는 상대 경로는 변환 서버에서 열리지 않습니다.

2. 높이는 입력값이 아니라 계산 결과입니다

캡처는 전체 페이지 방식(fullPage)이라 문서 전체를 한 장에 담습니다. 그래서 세로 길이는 입력란이 아니라 렌더링이 끝난 뒤 문서가 실제로 차지한 높이에서 나옵니다. 기준이 되는 것은 body가 아니라 문서 루트인 html의 스크롤 높이입니다. 자식의 margin이 body 바깥으로 빠져나가는 경우처럼 둘이 어긋나는 상황이 있는데, 이미지에 반영되는 쪽은 언제나 바깥쪽입니다. 폭 600에 문서 높이 900 CSS px이면 결과는 1200 × 1800 PNG입니다.

세로에는 하한이 있습니다

여기에 잘 알려지지 않은 제약이 하나 있습니다. 렌더링을 시작할 때의 창 높이가 800 CSS px이고, 문서의 스크롤 높이는 창 높이보다 작아질 수 없습니다. 그래서 내용이 300 CSS px밖에 안 되는 작은 배지를 만들어도 문서는 800 CSS px으로 계산되고, 결과 PNG의 세로는 1600px이 됩니다. html이나 bodyheight: 300px을 명시해도 달라지지 않습니다.

출력 세로(px) = max(문서 스크롤 높이, 800) × 2 문서 높이 300 CSS px → max(300, 800) = 800 → 1600 px 문서 높이 801 CSS px → max(801, 800) = 801 → 1602 px 문서 높이 900 CSS px → max(900, 800) = 900 → 1800 px

즉 이 도구에서 세로 1600px보다 짧은 PNG는 나오지 않습니다. 더 작은 아이콘이 필요하면 아래 여백을 감안하고 받은 뒤 잘라 쓰십시오. 800을 한 번 넘긴 뒤부터는 1 CSS px 단위가 그대로 반영되므로 계산은 오히려 단순해집니다.

3. 문서가 예상보다 길어지는 네 가지 원인

문서가 이미 800 CSS px을 넘겼는데도 예상보다 길다면, 그것은 오류가 아니라 브라우저가 정말 그만큼 긴 문서라고 계산한 결과입니다. 원인은 대개 이 넷입니다.

① 마진 상쇄(margin collapsing)

부모에 padding이나 border가 없으면 첫 자식의 margin-top과 마지막 자식의 margin-bottom이 밖으로 빠져나가 문서 높이에 더해져 이미지 위아래의 흰 띠가 됩니다. 부모에 display: flow-root를 주거나 margin 대신 padding을 쓰면 해결됩니다.

② 본문 끝에 남은 <br>과 텍스트 조각

닫는 태그 앞의 <br>, 지우다 만 마침표 한 글자처럼 실제 문자가 들어 있는 텍스트 노드는 한 줄 높이의 줄 상자를 만듭니다. 16px 글꼴에 line-height 1.7이면 27 CSS px, 출력으로는 54px입니다.

반면 흔한 오해와 달리, 태그와 태그 사이의 줄바꿈이나 들여쓰기 공백은 높이를 늘리지 않습니다. 블록 요소 사이의 공백만 있는 텍스트는 렌더링 대상이 아니어서, 보기 좋게 정렬한 HTML이 이미지 아래 여백의 원인이 되는 일은 없습니다. 주석도 마찬가지입니다. 코드를 한 줄로 붙여 쓸 필요는 없습니다.

min-height: 100vh

vh는 최종 이미지 높이가 아니라 초기 창 높이 800 CSS px 기준입니다. min-height: 100vh를 준 요소는 내용이 무엇이든 정확히 800 CSS px이 되는데, 여기에 body의 padding이나 요소의 margin이 조금이라도 더해지면 문서는 800을 넘어가고 그 초과분이 그대로 아래 빈 띠로 남습니다. 화면에서는 딱 맞아 보이던 레이아웃이 이미지에서만 어긋나는 전형적인 경우입니다.

④ 흐름에서 벗어난 요소

position: absolute로 아래에 놓은 장식 요소는 문서의 스크롤 영역을 늘립니다. 반대로 transform: translateY(-40px)처럼 시각적으로만 끌어올린 요소는 원래 자리의 높이를 남깁니다.

이를 피한 캡처용 뼈대입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<style>
  html, body { margin: 0; padding: 0; background: #ffffff; }

  .sheet {
    display: flow-root;   /* 자식 margin 이 밖으로 빠져나가지 않음 */
    padding: 48px 40px;   /* 바깥 margin 대신 안쪽 padding 으로 여백 */
    box-sizing: border-box;
  }
  .sheet > *:last-child { margin-bottom: 0; }
</style>
</head>
<body>
  <div class="sheet">
    <h1>제목</h1>
    <p>본문 내용</p>
  </div>
</body>
</html>

display: flow-root가 자식의 margin을 상자 안에 가두고, 마지막 자식의 margin-bottom을 0으로 눌러 두면 아래 여백은 padding이 정한 값 하나로 확정됩니다. 내용이 늘거나 줄어도 위아래 여백이 흔들리지 않습니다. 이미지 전용 HTML의 전체 뼈대는 이미지로 내보낼 HTML 템플릿 작성 가이드에서 더 자세히 다룹니다.

4. vh, vw, position: fixed가 어긋나는 이유

전체 페이지 캡처에는 화면이라는 개념이 없습니다. vh는 초기 창 높이 800 CSS px 기준으로 계산되므로 height: 100vh는 폭을 300으로 하든 2000으로 하든 항상 800 CSS px(출력 1600px)입니다. 화면에서 보던 비율이 어긋나는 대표적 원인입니다.

반대로 vw는 입력한 폭이 기준이라 예측 가능합니다. 폭이 800이면 1vw는 8px이지만, 폭을 바꾸면 글자 크기도 변합니다.

position: fixed 요소는 흐름에서 빠져 높이에 기여하지 않고 한 위치에만 그려집니다. 고정 헤더가 본문에 겹쳐 찍히기 쉬우므로 static이나 relative로 바꾸십시오.

화면 한 장 크기 카드는 100vh 대신 픽셀 높이나 비율로 지정하십시오.

/* 방법 A — 높이를 픽셀로 확정 (하한 800 위로 잡습니다) */
.card { width: 100%; height: 1000px; box-sizing: border-box; }

/* 방법 B — 폭에 대한 비율로 지정 (4:5 세로형) */
.card { width: 100%; aspect-ratio: 4 / 5; box-sizing: border-box; }

방법 A에 폭 600을 넣으면(앞 뼈대처럼 body 여백이 0일 때) 문서 높이 1000 CSS px, 결과는 1200 × 2000 PNG입니다.

방법 B에서는 800 CSS px 하한을 함께 따져야 합니다. 폭 600이면 카드 높이가 750 CSS px이라 하한에 미치지 못해, 결과는 1200 × 1500이 아니라 1200 × 1600이 되고 아래 50 CSS px(출력 100px)만큼 배경이 남습니다. 비율을 정확히 지키려면 카드 높이가 800 CSS px을 넘도록 폭을 잡으십시오. 같은 aspect-ratio: 4 / 5라도 폭 700이면 높이가 875 CSS px이라 하한을 넘어, 결과는 1400 × 1750으로 정확히 4:5가 됩니다.

5. 목표 픽셀 폭에서 설정값 역산하기

가로는 항상 정확히 2배이므로 계산은 나눗셈 한 번입니다. 가로 1200px 이미지가 필요하면 600을 넣습니다.

세로는 문서 높이 × 2이며, 어떤 경우에도 1600px 아래로는 내려가지 않습니다.
설정 폭 (CSS px)출력 PNG 가로 (px)참고
300600좁은 폭 요소
50010001000px 결과물
60012001200px 결과물
8001600문서형 이미지
10002000폭을 비웠을 때의 기본값
12002400PC 화면 기준으로 만든 HTML
40008000허용되는 최대 폭

다만 설정 폭은 배율 손잡이가 아니라 레이아웃이 계산되는 좌표계입니다. 1200px 화면을 전제로 만든 HTML에 600을 넣으면 출력 폭은 맞지만, 좁은 화면용 미디어 쿼리가 켜지고 16px 본문이 커 보이며 가로 배치가 무너질 수 있습니다.

그래서 원칙은 HTML이 전제한 폭을 그대로 넣고 결과가 크면 받은 PNG를 축소하는 것입니다. %rem으로 유연하게 짰다면 목표의 절반을 넣습니다.

폭이 비어 있거나 숫자로 해석되지 않으면 1000이 쓰이고, 100 미만과 4000 초과 값은 각각 100과 4000으로 조정됩니다.

6. PNG로만 출력되는 이유

출력은 PNG로 고정입니다. PNG는 무손실이라 원본 픽셀값이 보존되고, 텍스트 가장자리·단색 배경·1px 구분선처럼 고대비 경계가 많은 그래픽에서 차이가 큽니다.

JPEG는 사진의 완만한 색 변화를 압축하도록 설계된 손실 형식이라, 흰 배경 위 검은 글씨처럼 급격한 경계 주변에 잔물결 같은 얼룩이 남습니다. 품질을 높여도 사라지지 않고, 2배 해상도에서는 오히려 더 잘 보입니다.

투명 배경은 나오지 않습니다

PNG 형식 자체는 투명도를 지원하지만 이 도구의 출력에는 알파 채널이 들어가지 않습니다. 배경을 지정하지 않은 HTML은 투명이 아니라 흰색으로 채워져 저장됩니다. 대신 body에 준 배경색은 콘텐츠가 끝난 뒤 남는 영역까지 캔버스 전체를 채웁니다. 배경색을 안쪽 카드에만 주면 그 바깥이 흰색으로 드러나므로, 색은 html이나 body에 지정하는 편이 안전합니다.

대가는 용량입니다. 픽셀 수가 4배인 데다 사진이나 그라디언트가 넓으면 압축 효율이 떨어져 파일이 크게 불어납니다. 다음이면 받은 뒤 직접 변환하십시오.

  • 대부분이 사진이고 글자는 몇 줄뿐일 때
  • 업로드할 곳에 용량 제한이 있을 때
  • 웹 게시용이라 로딩 속도가 중요할 때 (WebP도 좋습니다)

순서도 중요합니다. 먼저 최종 표시 크기로 축소한 다음 JPEG나 WebP로 바꾸십시오. 축소하면서 픽셀이 평균화되어 손실 흔적이 훨씬 덜 눈에 띕니다.

7. 30000px 높이 제한과 분할

문서 높이가 30000 CSS px을 넘으면 위에서부터 30000 CSS px까지만 캡처되고 나머지는 담기지 않습니다. 메모리 부족으로 변환 자체가 실패하는 것을 막는 안전장치입니다. 이 한계에 걸린 결과물도 2배 밀도가 적용되어 세로 60000px이 되므로, 폭이 1000이면 2000 × 60000짜리 PNG 한 장입니다.

문제는 그보다 먼저 옵니다. 세로가 수만 픽셀인 이미지는 미리보기가 느리고 뷰어에 따라 열리지 않습니다. 긴 상세 페이지라면 처음부터 나눠 만드십시오.

  • 한 조각을 1만 CSS px(출력 2만 px) 안쪽으로 잡습니다.
  • 표나 문단 중간이 아니라 섹션 경계에서 끊습니다.
  • 공통 스타일은 각 파일의 <style>에 복사합니다. 옆에 둔 외부 CSS는 함께 올라가지 않습니다.
  • 이름을 page-01.html, page-02.html처럼 지으면 순서가 유지됩니다.

원하는 규격이 안 나올 때 확인할 것

  • 세로가 1600px 밑으로 안 내려가거나, 짧은 내용인데 아래가 넓게 빔 → 문서 높이 하한 800 CSS px 때문입니다.
  • 충분히 긴 문서인데도 아래가 빔 → margin 상쇄, 남은 <br>이나 텍스트 조각, min-height: 100vh, 아래쪽에 놓인 position: absolute 요소 순으로 확인하십시오.
  • 비율이 다름 → vh가 800 CSS px로 계산됐거나, 목표 높이가 하한에 미치지 못한 것입니다.
  • 사진만 뭉개짐 → 원본이 표시 크기의 2배 미만입니다.
  • 모바일 레이아웃으로 찍힘 → 설정 폭이 미디어 쿼리 분기점 아래입니다.
  • 헤더가 본문 위에 겹침 → position: fixed입니다. static으로 바꾸십시오.

이미지나 CSS가 아예 나오지 않는다면 크기가 아니라 경로 문제입니다. 업로드된 HTML은 서버의 임시 위치에서 열려 같은 폴더에 두었던 상대 경로 파일을 찾지 못합니다. 절대 https:// 주소나 base64를 쓰십시오. 원인을 하나씩 좁히는 방법은 이미지와 CSS가 안 나올 때 — 경로와 리소스 처리에 정리해 두었습니다.