diff --git a/app/modules/cafe24/templates/cafe24/_editor.html b/app/modules/cafe24/templates/cafe24/_editor.html index a19b20d..5e71d05 100644 --- a/app/modules/cafe24/templates/cafe24/_editor.html +++ b/app/modules/cafe24/templates/cafe24/_editor.html @@ -69,13 +69,11 @@ 줄바꿈을 하지 않고(wrap=off) 가로로 스크롤하므로 줄 번호가 항상 맞는다. 두 요소의 폰트·여백이 다르면 글자가 어긋난다 — CSS 에서 함께 관리한다. #}
특성).
if (ta.value.length > HL_LIMIT) hl.textContent = ta.value + "\n";
else hl.innerHTML = paintHtml(ta.value) + "\n";
renderGutter(ta.value.split("\n").length);
- // 크기는 가 정하고 textarea 가 그 위를 덮는다. 다시 칠하는 사이
- // 내부 스크롤이 생겼으면 되돌려 두 층의 정렬을 유지한다.
- ta.scrollTop = 0;
- ta.scrollLeft = 0;
+ sync();
}
function refresh() {
- // 짧은 소스는 바로 칠해야 줄 번호·상자 크기가 즉시 따라온다.
+ // 짧은 소스는 바로 칠해야 줄 번호가 즉시 따라온다.
if (ta.value.length < 50000) { repaint(); return; }
clearTimeout(timer);
timer = setTimeout(repaint, 80);
}
+ ta.addEventListener("scroll", sync);
ta.addEventListener("input", function () { dirty = true; refresh(); });
// Tab 은 포커스 이동이 아니라 들여쓰기로 쓴다.
ta.addEventListener("keydown", function (e) {
diff --git a/app/modules/cafe24/templates/cafe24/schedules.html b/app/modules/cafe24/templates/cafe24/schedules.html
index dfb77c4..e62501a 100644
--- a/app/modules/cafe24/templates/cafe24/schedules.html
+++ b/app/modules/cafe24/templates/cafe24/schedules.html
@@ -1,7 +1,7 @@
{% extends "erp_base.html" %}
{% block head_extra %}
-
+
{% endblock %}
{% block content %}
diff --git a/app/modules/cafe24/templates/cafe24/system.html b/app/modules/cafe24/templates/cafe24/system.html
index ce59fce..33a7c4d 100644
--- a/app/modules/cafe24/templates/cafe24/system.html
+++ b/app/modules/cafe24/templates/cafe24/system.html
@@ -1,7 +1,7 @@
{% extends "erp_base.html" %}
{% block head_extra %}
-
+
{% endblock %}
{% block content %}
diff --git a/app/static/cafe24.css b/app/static/cafe24.css
index 8a3d8b0..fdf3649 100644
--- a/app/static/cafe24.css
+++ b/app/static/cafe24.css
@@ -260,30 +260,30 @@
않는다. 아래 두 선택자에 붙은 속성을 바꿀 때는 반드시 함께 바꿀 것.
외부 라이브러리를 쓰지 않는다(자체 호스팅 원칙 + CDN 의존 제거).
════════════════════════════════════════════════════════════ */
+/* 스크롤은 **textarea 가** 담당하고, 색칠 층과 줄 번호가 transform 으로 따라간다.
+ 폭·높이를 계산해 맞추는 방식은 flex 안에서 `width: max-content` 가 기대대로
+ 동작하지 않아 실패했다 — 긴 줄이 있으면 textarea 만 내부 스크롤되고 색칠 층은
+ 제자리에 남아, 커서 위치와 보이는 글자가 어긋났다(실측 706 vs 686).
+ 스크롤 동기화 방식은 크기 계산이 아예 필요 없어 어긋날 여지가 없다. */
.cf24-code {
position: relative;
flex: 1 1 auto;
min-height: 340px;
- overflow: auto; /* 가로·세로 스크롤을 여기서 담당 */
+ overflow: hidden;
border: 1px solid var(--color-subtle-ash, #e5e5e5);
border-radius: var(--r-lg, 10px);
background: var(--color-canvas-white, #fff);
}
-.cf24-code-rows {
- display: flex;
- align-items: stretch;
- min-width: max-content; /* 가장 긴 줄에 맞춰 넓어진다(줄바꿈 없음) */
- min-height: 100%;
-}
-
-/* 줄 번호 — 가로로 스크롤해도 왼쪽에 붙어 있게 sticky */
+/* 줄 번호 — 코드 영역 왼쪽에 고정된 별도 칸(가로 스크롤과 무관) */
.cf24-gutter {
- position: sticky;
+ position: absolute;
left: 0;
- z-index: 2;
- flex: 0 0 auto;
- padding: var(--sp-12, 12px) var(--sp-8, 8px);
+ top: 0;
+ bottom: 0;
+ width: 42px;
+ overflow: hidden;
+ padding: var(--sp-12, 12px) var(--sp-8, 8px) 0 0;
text-align: right;
background: var(--color-ghost-gray, #f6f8fa);
border-right: 1px solid var(--color-subtle-ash, #e5e5e5);
@@ -292,9 +292,17 @@
white-space: pre;
}
+.cf24-gutter-inner {
+ will-change: transform; /* 세로 스크롤을 따라 움직인다 */
+}
+
.cf24-code-body {
- position: relative; /* textarea 의 기준 박스 — 크기는 가 정한다 */
- flex: 1 0 auto;
+ position: absolute;
+ left: 43px; /* 줄 번호 칸 + 경계선 */
+ right: 0;
+ top: 0;
+ bottom: 0;
+ overflow: hidden;
}
/* 두 층의 글자가 정확히 겹치려면 아래 속성이 전부 같아야 한다.
@@ -318,15 +326,19 @@
overflow-wrap: normal;
}
-/* 가 흐름에 남아 본문 칸의 크기를 결정한다. */
+/* 색칠 층 — textarea 의 스크롤량만큼 transform 으로 이동한다. */
.cf24-code-hl {
+ position: absolute;
+ top: 0;
+ left: 0;
width: max-content;
min-width: 100%;
pointer-events: none;
color: var(--color-rich-black, #0a0a0a);
+ will-change: transform;
}
-/* textarea 는 그 위를 정확히 덮는다(크기 계산을 JS 로 하지 않아도 어긋나지 않음). */
+/* textarea 가 실제 스크롤 주체다. */
.cf24-code-input {
position: absolute;
top: 0;
@@ -338,7 +350,7 @@
color: transparent;
caret-color: var(--color-rich-black, #0a0a0a);
resize: none;
- overflow: hidden;
+ overflow: auto;
}
.cf24-code-input:focus {