즉방형 "버튼이 멀쩡한데 클릭이 안 돼요" click-blocked
문장
코드
범인 1순위: 투명한 요소가 위를 덮고 있음. 그라디언트 장식, 닫힌 줄 알았던 오버레이
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>"버튼이 멀쩡한데 클릭이 안 돼요" · CSS 증상 사전</title>
<!--
증상: "버튼이 멀쩡한데 클릭이 안 돼요" (click-blocked) · 유형: 즉방형
범인: 투명한 요소가 위를 덮고 있음. 그라디언트 장식, 닫힌 줄 알았던 오버레이 / 쌓임 순서 경쟁에서 밀림
처방: 장식용 덮개에는 pointer-events: none: 보이되 클릭은 통과시킨다.
AI에게: 이 버튼이 클릭이 안 돼. 위를 덮고 있는 요소를 찾아서 알려주고, 장식용이면 pointer-events none을 줘서 클릭이 통과되게 해줘.
확인: 버튼 전체 어디를 눌러도 반응하면 성공.
-->
<style>
* { box-sizing: border-box; }
body { margin: 0; font-family: -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; color: #17171b; font-size: 13px; background: #fff; word-break: keep-all; }
.duo { display: grid; grid-template-columns: 1fr 1fr; }
.pane { min-width: 0; }
.pane + .pane { border-left: 1px solid #e8e8ee; }
.tag { font-size: 11px; font-weight: 800; padding: 7px 12px; }
.bad .tag { background: #fbf1ef; color: #c4372b; }
.good .tag { background: #eff6f1; color: #1f7a4d; }
.stage { background: #f6f7f9; padding: 12px; position: relative; overflow: hidden; }
@media (max-width: 430px) {
.duo { grid-template-columns: 1fr; }
.pane + .pane { border-left: 0; border-top: 1px solid #e8e8ee; }
}
.card { background: #fff; border: 1px solid #e4e4ea; border-radius: 10px; padding: 10px 13px; box-shadow: 0 1px 4px rgba(23,23,27,.05); }
.bar { background: #ececf1; border-radius: 4px; height: 10px; }
.mut { color: #9a9aa4; font-size: 12px; }
.btn { display: inline-block; border: 0; border-radius: 9px; background: #17171b; color: #fff; font-size: 12.5px; padding: 9px 16px; cursor: pointer; font-family: inherit; }
.chk { font-size: 11.5px; color: #55555f; padding: 8px 12px; border-top: 1px solid #f0f0f4; background: #fff; }
.chk b { color: #17171b; }
</style>
</head>
<body>
<div class="duo">
<section class="pane bad"><div class="tag">✗ 깨진 그대로</div><div class="stage" style="height:150px">
<div style="height:100%;display:flex;align-items:center;justify-content:center">
<div style="position:relative;display:inline-block">
<button class="btn" onclick="this.querySelector('b').textContent=+this.querySelector('b').textContent+1">담기 <b style="color:#ffb3a0">0</b></button>
<div style="position:absolute;inset:-26px;background:linear-gradient(transparent,rgba(240,80,50,.06))"></div>
</div>
</div>
</div></section>
<section class="pane good"><div class="tag">✓ 고친 그대로</div><div class="stage" style="height:150px">
<div style="height:100%;display:flex;align-items:center;justify-content:center">
<div style="position:relative;display:inline-block">
<button class="btn" onclick="this.querySelector('b').textContent=+this.querySelector('b').textContent+1">담기 <b style="color:#8fe3b6">0</b></button>
<div style="position:absolute;inset:-26px;background:linear-gradient(transparent,rgba(240,80,50,.06));pointer-events:none"></div>
</div>
</div>
</div></section>
</div>
<div class="chk"><b>고쳐졌는지 확인:</b> 버튼 전체 어디를 눌러도 반응하면 성공.</div>
<script>
document.addEventListener('click', function (e) {
var a = e.target.closest('a[href="#"]');
if (a) e.preventDefault();
});
</script>
</body>
</html>
코드 복사
분기형 "팝업이 다른 것 뒤에 깔려요" stacking-context
문장
코드
갈림길: 숫자 경쟁 (같은 층에서 밀림) / 조상에 transform·filter·opacity가 있어서 그 안에 갇힘
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>"팝업이 다른 것 뒤에 깔려요" · CSS 증상 사전</title>
<!--
증상: "팝업이 다른 것 뒤에 깔려요" (stacking-context) · 유형: 분기형
범인: 쌓임 순서(z-index) 문제는 두 종류, 단순 숫자 경쟁이거나, 조상이 만든 '층' 안에 갇혔거나
갈림길: [숫자 경쟁 (같은 층에서 밀림)] → 화면 전체의 층 규칙을 정리 (헤더 10, 드롭다운 100, 모달 1000처럼) · [조상에 transform·filter·opacity가 있어서 그 안에 갇힘] → 숫자를 올려도 소용없음. 팝업을 문서 최상위로 이동(portal)
AI에게: 팝업이 헤더 뒤에 깔려. z-index 숫자만 올리지 말고, 조상 때문에 층 안에 갇힌 건지 먼저 확인해서 알려주고, 갇혔으면 팝업을 문서 최상위로 옮겨줘.
확인: 팝업이 항상 모든 것 위에 뜨면 성공.
-->
<style>
* { box-sizing: border-box; }
body { margin: 0; font-family: -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; color: #17171b; font-size: 13px; background: #fff; word-break: keep-all; }
.duo { display: grid; grid-template-columns: 1fr 1fr; }
.pane { min-width: 0; }
.pane + .pane { border-left: 1px solid #e8e8ee; }
.tag { font-size: 11px; font-weight: 800; padding: 7px 12px; }
.bad .tag { background: #fbf1ef; color: #c4372b; }
.good .tag { background: #eff6f1; color: #1f7a4d; }
.stage { background: #f6f7f9; padding: 12px; position: relative; overflow: hidden; }
@media (max-width: 430px) {
.duo { grid-template-columns: 1fr; }
.pane + .pane { border-left: 0; border-top: 1px solid #e8e8ee; }
}
.card { background: #fff; border: 1px solid #e4e4ea; border-radius: 10px; padding: 10px 13px; box-shadow: 0 1px 4px rgba(23,23,27,.05); }
.bar { background: #ececf1; border-radius: 4px; height: 10px; }
.mut { color: #9a9aa4; font-size: 12px; }
.btn { display: inline-block; border: 0; border-radius: 9px; background: #17171b; color: #fff; font-size: 12.5px; padding: 9px 16px; cursor: pointer; font-family: inherit; }
.chk { font-size: 11.5px; color: #55555f; padding: 8px 12px; border-top: 1px solid #f0f0f4; background: #fff; }
.chk b { color: #17171b; }
</style>
</head>
<body>
<div class="duo">
<section class="pane bad"><div class="tag">✗ 깨진 그대로</div><div class="stage" style="height:170px">
<div style="height:100%;position:relative">
<div style="position:absolute;top:0;left:0;right:0;z-index:10;background:#17171b;color:#fff;font-size:12px;padding:8px 12px;border-radius:8px 8px 0 0">고정 헤더 (z-index 10)</div>
<div style="position:absolute;inset:0;transform:translateZ(0)">
<div style="position:absolute;left:50%;top:38%;transform:translateX(-50%);z-index:9999;width:160px" class="card">
<b>팝업 (z-index 9999)</b>
<p class="mut" style="margin:4px 0 0">그래도 헤더 뒤에 깔림: 조상 transform이 만든 층 안</p>
</div>
</div>
</div>
</div></section>
<section class="pane good"><div class="tag">✓ 고친 그대로</div><div class="stage" style="height:170px">
<div style="height:100%;position:relative">
<div style="position:absolute;top:0;left:0;right:0;z-index:10;background:#17171b;color:#fff;font-size:12px;padding:8px 12px;border-radius:8px 8px 0 0">고정 헤더 (z-index 10)</div>
<div style="position:absolute;left:50%;top:8px;transform:translateX(-50%);z-index:1000;width:160px" class="card">
<b>팝업 (문서 최상위로 이동)</b>
<p class="mut" style="margin:4px 0 0">층 밖으로 꺼내면 숫자가 다시 통함</p>
</div>
</div>
</div></section>
</div>
<div class="chk"><b>고쳐졌는지 확인:</b> 팝업이 항상 모든 것 위에 뜨면 성공.</div>
<script>
document.addEventListener('click', function (e) {
var a = e.target.closest('a[href="#"]');
if (a) e.preventDefault();
});
</script>
</body>
</html>
코드 복사
즉방형 "겹친 글자 뒤가 비쳐 보여요" no-backdrop
문장
코드
범인 1순위: 떠 있는 요소에 배경색이 없음. 뒤 내용이 그대로 비침
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>"겹친 글자 뒤가 비쳐 보여요" · CSS 증상 사전</title>
<!--
증상: "겹친 글자 뒤가 비쳐 보여요" (no-backdrop) · 유형: 즉방형
범인: 떠 있는 요소에 배경색이 없음. 뒤 내용이 그대로 비침
처방: 떠 있는 요소에는 배경을 반드시 명시한다.
AI에게: 이 떠 있는 요소에 배경색을 줘서 뒤 내용이 비치지 않게 해줘.
확인: 뒤 내용이 전혀 안 비치면 성공.
-->
<style>
* { box-sizing: border-box; }
body { margin: 0; font-family: -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; color: #17171b; font-size: 13px; background: #fff; word-break: keep-all; }
.duo { display: grid; grid-template-columns: 1fr 1fr; }
.pane { min-width: 0; }
.pane + .pane { border-left: 1px solid #e8e8ee; }
.tag { font-size: 11px; font-weight: 800; padding: 7px 12px; }
.bad .tag { background: #fbf1ef; color: #c4372b; }
.good .tag { background: #eff6f1; color: #1f7a4d; }
.stage { background: #f6f7f9; padding: 12px; position: relative; overflow: hidden; }
@media (max-width: 430px) {
.duo { grid-template-columns: 1fr; }
.pane + .pane { border-left: 0; border-top: 1px solid #e8e8ee; }
}
.card { background: #fff; border: 1px solid #e4e4ea; border-radius: 10px; padding: 10px 13px; box-shadow: 0 1px 4px rgba(23,23,27,.05); }
.bar { background: #ececf1; border-radius: 4px; height: 10px; }
.mut { color: #9a9aa4; font-size: 12px; }
.btn { display: inline-block; border: 0; border-radius: 9px; background: #17171b; color: #fff; font-size: 12.5px; padding: 9px 16px; cursor: pointer; font-family: inherit; }
.chk { font-size: 11.5px; color: #55555f; padding: 8px 12px; border-top: 1px solid #f0f0f4; background: #fff; }
.chk b { color: #17171b; }
</style>
</head>
<body>
<div class="duo">
<section class="pane bad"><div class="tag">✗ 깨진 그대로</div><div class="stage" style="height:130px">
<div style="height:100%;position:relative">
<p style="margin:0;font-size:12px;line-height:1.8;color:#55555f">주문 내역을 확인하시려면 마이페이지로 이동해 주세요. 배송은 결제 후 2일 이내에 시작됩니다. 교환·환불 규정은 고객센터에서 안내합니다.</p>
<div style="position:absolute;left:20px;top:26px;padding:6px 12px;font-size:12px;font-weight:700">떠 있는 라벨 (배경 없음)</div>
</div>
</div></section>
<section class="pane good"><div class="tag">✓ 고친 그대로</div><div class="stage" style="height:130px">
<div style="height:100%;position:relative">
<p style="margin:0;font-size:12px;line-height:1.8;color:#55555f">주문 내역을 확인하시려면 마이페이지로 이동해 주세요. 배송은 결제 후 2일 이내에 시작됩니다. 교환·환불 규정은 고객센터에서 안내합니다.</p>
<div style="position:absolute;left:20px;top:26px;padding:6px 12px;font-size:12px;font-weight:700;background:#fff;border:1px solid #e4e4ea;border-radius:8px;box-shadow:0 3px 10px rgba(23,23,27,.1)">떠 있는 라벨 (배경 세트)</div>
</div>
</div></section>
</div>
<div class="chk"><b>고쳐졌는지 확인:</b> 뒤 내용이 전혀 안 비치면 성공.</div>
<script>
document.addEventListener('click', function (e) {
var a = e.target.closest('a[href="#"]');
if (a) e.preventDefault();
});
</script>
</body>
</html>
코드 복사
즉방형 "그림자가 잘려요" clipped-shadow
문장
코드
범인 1순위: 부모의 overflow hidden이 그림자까지 자름
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>"그림자가 잘려요" · CSS 증상 사전</title>
<!--
증상: "그림자가 잘려요" (clipped-shadow) · 유형: 즉방형
범인: 부모의 overflow hidden이 그림자까지 자름 / 그림자가 퍼질 여백 없이 경계에 꽉 붙음
처방: 자르는 부모를 찾아서 풀거나, 그림자가 퍼질 여백을 확보한다.
AI에게: 카드 그림자가 잘려. 잘라먹는 부모를 찾아서 알려주고, 그림자가 온전히 보이게 고쳐줘.
확인: 그림자 네 방향이 모두 자연스럽게 보이면 성공.
-->
<style>
* { box-sizing: border-box; }
body { margin: 0; font-family: -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; color: #17171b; font-size: 13px; background: #fff; word-break: keep-all; }
.duo { display: grid; grid-template-columns: 1fr 1fr; }
.pane { min-width: 0; }
.pane + .pane { border-left: 1px solid #e8e8ee; }
.tag { font-size: 11px; font-weight: 800; padding: 7px 12px; }
.bad .tag { background: #fbf1ef; color: #c4372b; }
.good .tag { background: #eff6f1; color: #1f7a4d; }
.stage { background: #f6f7f9; padding: 12px; position: relative; overflow: hidden; }
@media (max-width: 430px) {
.duo { grid-template-columns: 1fr; }
.pane + .pane { border-left: 0; border-top: 1px solid #e8e8ee; }
}
.card { background: #fff; border: 1px solid #e4e4ea; border-radius: 10px; padding: 10px 13px; box-shadow: 0 1px 4px rgba(23,23,27,.05); }
.bar { background: #ececf1; border-radius: 4px; height: 10px; }
.mut { color: #9a9aa4; font-size: 12px; }
.btn { display: inline-block; border: 0; border-radius: 9px; background: #17171b; color: #fff; font-size: 12.5px; padding: 9px 16px; cursor: pointer; font-family: inherit; }
.chk { font-size: 11.5px; color: #55555f; padding: 8px 12px; border-top: 1px solid #f0f0f4; background: #fff; }
.chk b { color: #17171b; }
</style>
</head>
<body>
<div class="duo">
<section class="pane bad"><div class="tag">✗ 깨진 그대로</div><div class="stage" style="height:140px">
<div style="overflow:hidden;height:90px;padding:0">
<div class="card" style="margin:0;box-shadow:0 10px 24px rgba(23,23,27,.28)"><b>카드</b><p class="mut" style="margin:3px 0 0">부모의 overflow hidden이 그림자를 반듯하게 자름</p></div>
</div>
</div></section>
<section class="pane good"><div class="tag">✓ 고친 그대로</div><div class="stage" style="height:140px">
<div style="height:90px;padding:6px">
<div class="card" style="margin:0;box-shadow:0 10px 24px rgba(23,23,27,.28)"><b>카드</b><p class="mut" style="margin:3px 0 0">자르는 부모를 풀고 여백 확보, 그림자가 온전함</p></div>
</div>
</div></section>
</div>
<div class="chk"><b>고쳐졌는지 확인:</b> 그림자 네 방향이 모두 자연스럽게 보이면 성공.</div>
<script>
document.addEventListener('click', function (e) {
var a = e.target.closest('a[href="#"]');
if (a) e.preventDefault();
});
</script>
</body>
</html>
코드 복사
즉방형 "목차 누르면 제목이 헤더에 가려요" anchor-under-header
문장
코드
범인 1순위: 고정 헤더 높이만큼 내려서 멈추라는 지시(scroll-margin)가 없음
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>"목차 누르면 제목이 헤더에 가려요" · CSS 증상 사전</title>
<!--
증상: "목차 누르면 제목이 헤더에 가려요" (anchor-under-header) · 유형: 즉방형
범인: 고정 헤더 높이만큼 내려서 멈추라는 지시(scroll-margin)가 없음
처방: 이동 목적지에 scroll-margin-top을 헤더 높이만큼 준다.
AI에게: 페이지 안에서 이동할 때 고정 헤더에 제목이 가리지 않게, 이동 지점에 헤더 높이만큼 여유를 줘.
확인: 목차를 눌렀을 때 제목이 헤더 아래로 온전히 보이면 성공.
-->
<style>
* { box-sizing: border-box; }
body { margin: 0; font-family: -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; color: #17171b; font-size: 13px; background: #fff; word-break: keep-all; }
.duo { display: grid; grid-template-columns: 1fr 1fr; }
.pane { min-width: 0; }
.pane + .pane { border-left: 1px solid #e8e8ee; }
.tag { font-size: 11px; font-weight: 800; padding: 7px 12px; }
.bad .tag { background: #fbf1ef; color: #c4372b; }
.good .tag { background: #eff6f1; color: #1f7a4d; }
.stage { background: #f6f7f9; padding: 12px; position: relative; overflow: hidden; }
@media (max-width: 430px) {
.duo { grid-template-columns: 1fr; }
.pane + .pane { border-left: 0; border-top: 1px solid #e8e8ee; }
}
.card { background: #fff; border: 1px solid #e4e4ea; border-radius: 10px; padding: 10px 13px; box-shadow: 0 1px 4px rgba(23,23,27,.05); }
.bar { background: #ececf1; border-radius: 4px; height: 10px; }
.mut { color: #9a9aa4; font-size: 12px; }
.btn { display: inline-block; border: 0; border-radius: 9px; background: #17171b; color: #fff; font-size: 12.5px; padding: 9px 16px; cursor: pointer; font-family: inherit; }
.chk { font-size: 11.5px; color: #55555f; padding: 8px 12px; border-top: 1px solid #f0f0f4; background: #fff; }
.chk b { color: #17171b; }
</style>
</head>
<body>
<div class="duo">
<section class="pane bad"><div class="tag">✗ 깨진 그대로</div><div class="stage" style="height:170px">
<div style="height:100%;position:relative;background:#fff;border:1px solid #e4e4ea;border-radius:10px;overflow:hidden">
<div style="position:absolute;top:0;left:0;right:0;background:rgba(255,255,255,.92);border-bottom:1px solid #e4e4ea;padding:8px 12px;font-size:12px;z-index:2"><b>고정 헤더</b></div>
<div style="padding:22px 12px 12px">
<b style="font-size:14px;color:#c4372b">2. 결제 방법</b> <span class="mut">← 이동 직후, 헤더에 반쯤 가림</span>
<div style="display:grid;gap:8px;margin-top:10px"><div class="bar"></div><div class="bar" style="width:80%"></div><div class="bar"></div></div>
</div>
</div>
</div></section>
<section class="pane good"><div class="tag">✓ 고친 그대로</div><div class="stage" style="height:170px">
<div style="height:100%;position:relative;background:#fff;border:1px solid #e4e4ea;border-radius:10px;overflow:hidden">
<div style="position:absolute;top:0;left:0;right:0;background:rgba(255,255,255,.92);border-bottom:1px solid #e4e4ea;padding:8px 12px;font-size:12px;z-index:2"><b>고정 헤더</b></div>
<div style="padding:48px 12px 12px">
<b style="font-size:14px;color:#1f7a4d">2. 결제 방법</b> <span class="mut">← scroll-margin으로 헤더 아래 착지</span>
<div style="display:grid;gap:8px;margin-top:10px"><div class="bar"></div><div class="bar" style="width:80%"></div><div class="bar"></div></div>
</div>
</div>
</div></section>
</div>
<div class="chk"><b>고쳐졌는지 확인:</b> 목차를 눌렀을 때 제목이 헤더 아래로 온전히 보이면 성공.</div>
<script>
document.addEventListener('click', function (e) {
var a = e.target.closest('a[href="#"]');
if (a) e.preventDefault();
});
</script>
</body>
</html>
코드 복사