이미지가 될 HTML은 웹페이지와 목적이 다릅니다. 스크롤도 클릭도 화면 크기 대응도 필요 없고 단 한 장면이 전부입니다. 이 전제를 코드에 반영해 두면 결과가 어긋나는 원인 대부분이 생기지 않습니다.
변환할 때 입력하는 폭은 서버가 페이지를 여는 브라우저 창의 가로 크기입니다. 그 창에서 렌더링된 문서가 그대로 이미지가 되므로 디자인 기준 폭과 변환 폭은 같아야 합니다.
미디어 쿼리는 필요 없을 뿐 아니라 위험합니다. 기준 폭이 분기점 아래면 의도하지 않은 모바일 레이아웃이 캡처됩니다.
가장 바깥 상자를 width: 860px으로 못 박으면 변환 폭을 1000으로 넣었을 때 오른쪽 140px이 빈 배경으로 남습니다. 반대로 600을 넣으면 내용이 잘릴 것 같지만 그렇지 않습니다. 캡처는 창 밖으로 넘친 부분까지 모두 담기 때문에, 지정한 600이 아니라 넘친 폭 860을 기준으로 저장됩니다. 어느 쪽이든 입력한 폭과 결과가 어긋나 여러 장의 규격이 제각각이 됩니다. 래퍼를 width: 100%로 두면 이런 일이 생기지 않습니다. 안쪽 여백과 글자 크기는 px로 고정하고, 기준 폭은 문서 맨 위에 주석으로 남기십시오.
창 높이는 폭과 달리 지정할 수 없고 항상 800px에서 출발합니다. 그래서 100vh는 최종 이미지 높이가 아니라 800px이고, @media (min-height: …)처럼 높이를 조건으로 거는 규칙도 늘 800px 기준으로 판정됩니다. 세로는 화면 단위 대신 px로 적으십시오(해상도와 크기 가이드).
캡처는 문서 전체 높이를 한 장에 담지만 스크롤은 하지 않으므로, 스크롤해야 보이는 것은 담기지 않습니다.
표나 긴 목록을 스크롤 상자에 넣으면 첫 화면만 남고 나머지는 사라집니다. 상자가 길어져도 문제없으니 스크롤을 걸 이유가 없습니다.
높이를 함께 지정한 상자에 걸면 넘친 내용이 잘린 채 확정됩니다. 글이 들어가는 상자에는 높이를 지정하지 말고 내용이 밀어내게 두십시오. height를 정해 둔 대표 이미지의 모서리를 둥글게 자르는 용도라면 안전합니다.
고정 요소는 완성될 이미지가 아니라 높이 800px짜리 임시 창을 기준으로 자리를 잡습니다. top: 0인 헤더는 이미지 맨 위에 한 번 그려져 본문 첫머리를 덮고, bottom: 0인 하단 바는 이미지 맨 아래가 아니라 위에서 800px 되는 지점, 즉 긴 이미지의 한가운데에 떠 버립니다. 스크롤이 없는 정지 화면에 고정 요소는 의미가 없으니 일반 흐름으로 되돌리십시오.
스티키는 스크롤이 있어야 붙는 속성이라 캡처에서는 아무 일도 일어나지 않습니다. 화면을 망가뜨리지는 않지만 상단에 붙어 있으리라 기대한 요소가 원래 흐름상의 자리에 그려집니다. 붙은 모습이 필요하면 그 자리에 직접 배치하십시오.
세로 길이는 입력값이 아니라 렌더링이 끝난 문서의 실제 높이입니다. 눈에 띄지 않는 여백 규칙이 그대로 이미지 크기가 됩니다.
브라우저는 body에 8px 여백을 기본으로 줍니다. 초기화하지 않으면 사방에 8px 띠가 생기고 문서 높이가 16px 늘어납니다. 2배 해상도라 결과 이미지에서는 32px입니다.
부모에 padding이나 border가 없으면 첫 자식의 margin-top과 마지막 자식의 margin-bottom이 부모 밖으로 빠져나가 문서 높이에 더해집니다. 위아래에 알 수 없는 띠가 생기는 원인입니다. 래퍼에 padding을 주면 막히고, display: flow-root를 함께 걸면 padding을 0으로 바꿔도 안전합니다. 섹션 간격은 margin보다 padding이나 gap이 안전합니다.
출력이 2배 해상도라 실제 픽셀 격자는 0.5 CSS px 단위입니다. font-size: 15px에 line-height: 1.65를 주면 한 행이 24.75px이 되는데, 이런 값은 격자에 맞지 않아 그릴 때 가장 가까운 눈금으로 당겨집니다. 요소 경계가 계산값과 최대 0.25px 어긋나는 셈이라, 한두 줄은 몰라도 표의 행이나 같은 높이를 반복하는 카드에서는 위치가 조금씩 밀립니다. 칸을 정확히 맞춰야 하는 곳은 계산 결과가 0.5의 배수로 떨어지게 잡으십시오. font-size: 16px에 line-height: 1.5는 24px입니다. 원형 배지처럼 지름과 세로 중앙 정렬이 함께 걸린 요소는 height와 line-height를 같은 정수로 두면 어긋나지 않습니다.
결과가 볼 때마다 달라 보인다면 브라우저 기본값에 맡긴 부분이 있는 것입니다. 다음은 항상 명시하십시오.
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html, body { background: #ffffff; }
body {
font-family: "Noto Sans CJK KR", "NanumGothic", sans-serif;
color: #16171a;
line-height: 1.65;
}배경색은 body에 지정하십시오. 아무것도 적지 않았을 때 빈 곳은 투명이 아니라 흰색으로 채워집니다. 문제는 어두운 디자인입니다. 배경을 안쪽 래퍼 div에만 주면 그 상자가 끝나는 지점부터 아래가 흰 띠로 남고, 내용이 짧아 이미지가 최소 높이까지 늘어날 때 특히 도드라집니다. body에 준 배경색은 문서 전체 캔버스로 퍼져 이런 흰 띠를 남기지 않고, html에도 함께 적어 두면 다른 규칙이 끼어들어도 색이 흔들리지 않습니다.
폰트 스택을 지정하지 않으면 서버 기본 폰트로 그려집니다. 설치된 것은 Noto Sans/Serif CJK KR, 나눔고딕과 나눔스퀘어, Noto Color Emoji, Liberation 계열뿐입니다. 그 밖의 폰트는 웹폰트로 불러와야 합니다(한글 폰트 가이드).
글자 안티앨리어싱과 text-rendering은 캡처 직전 서버가 모든 요소에 자동으로 넣어 주므로, 템플릿에 적지 않아도 선명합니다.
서버로 올라가는 것은 HTML 파일 자체뿐이라, 파일 옆에 둔 이미지나 CSS는 서버에 존재하지 않습니다. images/main.jpg 같은 상대 경로는 반드시 실패하므로 자산은 https:// 절대 주소나 base64로 심어야 합니다(경로와 리소스 가이드).
캡처는 네트워크 요청이 잦아든 직후의 한 순간을 한 번 찍는 것이라, 그 순간 화면에 없던 것은 결과에도 없습니다.
opacity: 0으로 시작해 화면에 들어올 때 나타나는 연출은 스크롤이 없어 대부분 투명한 채로 남습니다. 다만 전부 사라지지는 않습니다. 임시 창에 이미 들어와 있는 위쪽 800px만 제 모습으로 나타나고 그 아래부터 텅 비는, 더 헷갈리는 형태로 어긋납니다. 이미지 위쪽은 멀쩡한데 중간부터 하얗다면 이 연출을 가장 먼저 의심하십시오.
시간이 걸리는 animation과 transition은 결과가 그때그때 다릅니다. 캡처 순간이 중간에 걸리면 거의 다 나타났지만 색이 미묘하게 옅은 이미지가 남고, 지연을 길게 걸면 아예 시작 상태로 찍힙니다. 같은 결과를 다시 얻을 수 없으니 연출은 지우고 최종 상태를 기본값으로 적으십시오.
.item {
opacity: 0;
transform: translateY(20px);
animation: up .6s .3s forwards;
}.item {
opacity: 1;
transform: none;
}:hover, :focus, :active는 조작하는 사람이 없어 발생하지 않습니다. 강조된 버튼 모습을 담으려면 그 스타일을 클래스로 만들어 직접 붙이십시오.
<video>는 어느 장면에서 멈춰 있을지 보장할 수 없어 포스터 이미지나 빈 상자로 남기 쉽습니다. 보여 주고 싶은 장면을 정지 이미지로 바꿔 넣으십시오. <canvas>와 차트 라이브러리는 로드 직후 한 번에 그리면 대체로 담기지만, 애니메이션이 켜져 있거나 타이머·요청 뒤에 그리면 빈 상자가 나옵니다. 애니메이션 옵션을 끄고 가능하면 SVG로 미리 만들어 두십시오. 로드 후 스크립트가 삽입한 내용도 캡처 시점을 넘기면 담기지 않습니다.
앞의 원칙을 모두 적용한 완성형 템플릿입니다. 외부 파일을 하나도 참조하지 않고 설치된 폰트만 쓰므로, 복사해 붙여넣고 폭을 860으로 변환하면 1720 × 3520px PNG가 나옵니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>상품 상세</title>
<!-- 상품 코드: LTM2410 -->
<style>
/* 1) 초기화 — 브라우저 기본 여백을 남기지 않습니다 */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--ink: #16171a;
--sub: #6b7280;
--line: #e5e7eb;
--point: #1f5eff;
--bg: #ffffff;
--soft: #f6f7f9;
}
/* 2) 배경색과 폰트는 반드시 명시합니다 */
html, body { background: var(--bg); }
body {
font-family: "Noto Sans CJK KR", "NanumGothic", sans-serif;
color: var(--ink);
line-height: 1.65;
letter-spacing: -0.02em;
}
/* 3) 캡처 프레임을 정확히 채우는 래퍼는 하나만 둡니다.
width: 100% 이므로 변환 폭을 무엇으로 넣든 좌우 여백이 생기지 않습니다.
이 디자인은 폭 860 기준으로 맞춰져 있습니다. */
.sheet {
width: 100%;
padding: 60px 56px 64px;
background: var(--bg);
display: flow-root; /* 첫·마지막 자식의 margin 이 밖으로 새는 것을 막습니다 */
}
.brand {
font-size: 14px;
font-weight: 700;
color: var(--point);
letter-spacing: 0.08em;
}
h1 {
margin-top: 10px;
font-size: 40px;
font-weight: 800;
line-height: 1.25;
}
.tagline {
margin-top: 12px;
font-size: 17px;
color: var(--sub);
}
/* 높이가 고정된 장식 상자라서 overflow: hidden 이 안전합니다.
글이 들어가는 상자에는 쓰지 않습니다. */
.hero {
display: flex;
align-items: center;
justify-content: center;
height: 380px;
margin-top: 32px;
border-radius: 20px;
overflow: hidden;
background: linear-gradient(135deg, #dbe4ff 0%, #f4f6ff 55%, #ffe8d9 100%);
color: #8b93a7;
font-size: 15px;
}
/* 사진을 넣을 때 쓰는 규칙입니다. src 는 반드시 https 주소나 base64 여야 합니다. */
.hero img { display: block; width: 100%; height: 100%; object-fit: cover; }
.price {
display: flex;
align-items: baseline;
gap: 14px;
margin-top: 34px;
padding: 26px 28px;
border: 1px solid var(--line);
border-radius: 16px;
background: var(--soft);
font-variant-numeric: tabular-nums;
}
.price .off { font-size: 30px; font-weight: 800; color: #e0342b; }
.price .now { font-size: 34px; font-weight: 800; }
.price .unit { font-size: 18px; font-weight: 700; }
.price .was { font-size: 18px; color: var(--sub); text-decoration: line-through; }
h2 {
margin-top: 44px;
padding-bottom: 12px;
border-bottom: 2px solid var(--ink);
font-size: 22px;
font-weight: 700;
}
.points {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
margin-top: 22px;
}
.point-card {
padding: 24px 20px;
border: 1px solid var(--line);
border-radius: 16px;
}
.point-card .no {
display: block;
width: 30px;
height: 30px;
border-radius: 50%;
background: var(--point);
color: #fff;
font-size: 14px;
font-weight: 700;
line-height: 30px;
text-align: center;
}
.point-card h3 { margin-top: 14px; font-size: 17px; font-weight: 700; }
.point-card p { margin-top: 6px; font-size: 14px; line-height: 1.6; color: var(--sub); }
table {
width: 100%;
margin-top: 22px;
border-collapse: collapse;
font-size: 15px;
}
th, td {
padding: 14px 16px;
border-bottom: 1px solid var(--line);
text-align: left;
vertical-align: top;
}
th {
width: 150px;
background: var(--soft);
color: var(--sub);
font-weight: 600;
}
.notice {
margin-top: 40px;
padding: 22px 24px;
border-left: 4px solid var(--point);
border-radius: 0 12px 12px 0;
background: var(--soft);
font-size: 14px;
color: var(--sub);
}
.notice strong { display: block; margin-bottom: 8px; color: var(--ink); font-size: 15px; }
.notice ul { padding-left: 18px; }
.notice li { margin-top: 4px; }
.foot {
margin-top: 46px;
padding-top: 20px;
border-top: 1px solid var(--line);
font-size: 13px;
color: var(--sub);
text-align: center;
}
</style>
</head>
<body>
<div class="sheet">
<p class="brand">TAYLOR STUDIO</p>
<h1>휴대용 원목 데스크 오거나이저</h1>
<p class="tagline">책상 위 24cm, 필요한 것만 남기는 정리 도구</p>
<div class="hero">
<!-- 사진을 쓸 때는 이 줄을 지우고 <img src="https://내도메인/photo.jpg" alt=""> 를 넣으십시오 -->
대표 이미지 자리 · 748 × 380
</div>
<div class="price">
<span class="off">30%</span>
<span class="now">38,500<span class="unit">원</span></span>
<span class="was">55,000원</span>
</div>
<h2>이런 점이 다릅니다</h2>
<div class="points">
<div class="point-card">
<span class="no">1</span>
<h3>원목 그대로</h3>
<p>도장 없이 천연 오일만 먹여 나뭇결과 손맛이 그대로 남습니다.</p>
</div>
<div class="point-card">
<span class="no">2</span>
<h3>분리형 트레이</h3>
<p>펜, 케이블, 메모지를 나눠 담는 트레이 두 개를 빼서 쓸 수 있습니다.</p>
</div>
<div class="point-card">
<span class="no">3</span>
<h3>미끄럼 방지</h3>
<p>바닥 네 귀퉁이에 실리콘 패드를 넣어 책상이 긁히지 않습니다.</p>
</div>
</div>
<h2>제품 정보</h2>
<table>
<tbody>
<tr><th>소재</th><td>북미산 화이트 오크 원목, 천연 오일 마감</td></tr>
<tr><th>크기</th><td>가로 240 × 세로 150 × 높이 95 (mm)</td></tr>
<tr><th>무게</th><td>약 620 g</td></tr>
<tr><th>구성</th><td>본체 1개, 분리형 트레이 2개, 극세사 천 1장</td></tr>
<tr><th>제조국</th><td>대한민국</td></tr>
</tbody>
</table>
<div class="notice">
<strong>구매 전 확인해 주세요</strong>
<ul>
<li>천연 원목이라 제품마다 나뭇결과 색이 조금씩 다릅니다.</li>
<li>모니터 환경에 따라 실제 색상과 차이가 있을 수 있습니다.</li>
<li>물에 오래 닿으면 변형될 수 있어 마른 천으로 닦아 주십시오.</li>
</ul>
</div>
<p class="foot">TAYLOR STUDIO</p>
</div>
</body>
</html>:root의 변수 여섯 개로 전체 톤이 바뀝니다..hero 안의 안내 문구를 지우고 <img src="https://…" alt="">를 넣습니다. 폭 860 기준에서 .hero의 실제 표시 폭은 좌우 여백 56px씩을 뺀 748px이고 2배로 찍히므로, 원본은 가로 1500px 이상을 쓰는 편이 안전합니다..points의 repeat(3, 1fr)에서 숫자만 고치면 됩니다..sheet의 padding과 글자 크기도 함께 조정하십시오. 래퍼가 100%라 폭만 바꾸면 글자 크기는 그대로입니다.같은 규격의 이미지를 여러 장 만들 때는 골격을 고정하고 내용만 바꾼 파일을 한 번에 업로드하는 것이 가장 빠릅니다. 이때 <style> 블록은 파일마다 복사해 넣어야 합니다. 공통 CSS 파일은 함께 올라가지 않습니다.
HTML 안에 다음 주석을 넣어 두면 그 값이 결과 파일 이름이 되어, 변환 뒤 이름을 일일이 고칠 일이 없습니다.
<!-- 상품 코드: LTM2410 -->인식 규칙은 아래 표와 같습니다.
| HTML 안의 주석 | 결과 파일 이름 |
|---|---|
<!-- 상품 코드: LTM2410 --> | LTM2410.png |
<!-- 상품 코드 : A_02 --> | A_02.png |
<!--상품코드:X1--> | X1.png |
<!-- 상품 코드: 가방01 --> | 가방01.png |
<!-- 상품 코드: LTM-2410 --> | 인식되지 않음 → ltm-원본파일명.png |
| 주석 없음 | ltm-원본파일명.png |
:과 전각 : 둘 다 인식되고, 상품·코드·콜론 사이의 띄어쓰기는 있어도 없어도 됩니다.LTM-01 대신 LTM_01처럼 적으십시오.<head> 안이든 <body> 안이든 상관없습니다.코드를 쓰지 않으면 원본 파일 이름이 반영되므로, 01-메인.html처럼 순서가 드러나게 지어도 됩니다.