From 75685e41da7c038089c22598aba82cb6df72e170 Mon Sep 17 00:00:00 2001 From: 2620227 Date: Fri, 10 Jul 2026 14:05:20 +0900 Subject: [PATCH] =?UTF-8?q?feat(responsive):=20=EB=AA=A8=EB=B0=94=EC=9D=BC?= =?UTF-8?q?=20=EB=8C=80=EC=9D=91=20=E2=80=94=20=EB=8D=B0=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=ED=86=B1=20=EC=9C=A0=EC=A7=80,=20=EB=B0=98=EC=9D=91=ED=98=95?= =?UTF-8?q?=20CSS=20=EB=A7=88=EC=A7=80=EB=A7=89=20=EB=A1=9C=EB=93=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 문제: 기존 반응형 @media 가 base.css(2번째 로드)에 있어, 뒤에 로드되는 components/layout 규칙에 덮여 사실상 무력했음(폰에서 그리드가 안 접힘). - public/css/responsive.css 신설, _header 에서 맨 마지막에 → 미디어쿼리가 데스크톱 규칙을 !important 없이 정상 override - base.css 의 죽은 반응형 블록 제거(responsive.css 로 이관) - @media 640: 헤더 flex-wrap(검색창 둘째 줄 전체폭·숨김 해제), 탭 영역 44px, 크롭 스테이지 aspect-ratio 정사각, 입력 16px(iOS 확대 방지), 좌우 여백/모달 여백 축소, 프로필 히어로 세로 스택 - 데스크톱(>640)은 규칙 미적용 → 기존과 픽셀 동일 Co-Authored-By: Claude Opus 4.8 (1M context) --- public/css/base.css | 12 +------- public/css/responsive.css | 59 +++++++++++++++++++++++++++++++++++++++ views/_header.ejs | 2 ++ 3 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 public/css/responsive.css diff --git a/public/css/base.css b/public/css/base.css index 525e3a8..10812e6 100644 --- a/public/css/base.css +++ b/public/css/base.css @@ -56,14 +56,4 @@ svg { display: block; } @keyframes aidev-fade { from{opacity:0} to{opacity:1} } @keyframes aidev-toast { 0%{transform:translateX(-50%) translateY(12px);opacity:0} 12%{transform:translateX(-50%) translateY(0);opacity:1} 88%{transform:translateX(-50%) translateY(0);opacity:1} 100%{transform:translateX(-50%) translateY(8px);opacity:0} } -/* 반응형 */ -@media (max-width: 900px) { - .tools-grid { grid-template-columns: repeat(2, 1fr); } - .myproj-grid { grid-template-columns: repeat(2, 1fr); } - .feed-grid { grid-template-columns: 1fr; } - .brand-sub { display: none; } -} -@media (max-width: 560px) { - .tools-grid, .myproj-grid { grid-template-columns: 1fr; } - .hdr-search { display: none; } -} +/* 반응형 규칙은 public/css/responsive.css 로 이동(로드 순서상 마지막이어야 실제 적용됨). */ diff --git a/public/css/responsive.css b/public/css/responsive.css new file mode 100644 index 0000000..fc6c385 --- /dev/null +++ b/public/css/responsive.css @@ -0,0 +1,59 @@ +/* 반응형(모바일) — 데스크톱 규칙을 덮어써야 하므로 반드시 다른 CSS 이후 마지막에 로드한다. + (_header.ejs 의 순서가 바뀌면 미디어쿼리가 무력화됨. 특히 헤더 검색창 재노출이 로드 순서에 의존.) + 데스크톱(>640px 등)은 아래 규칙이 적용되지 않아 기존과 완전히 동일하다. */ + +/* ===================== 그리드 단계 축소 ===================== */ +/* (기존 base.css 에 있었으나 로드 순서 때문에 무력했던 규칙 — 여기로 옮겨 실제 작동) */ +@media (max-width: 900px) { + .tools-grid { grid-template-columns: repeat(2, 1fr); } + .myproj-grid { grid-template-columns: repeat(2, 1fr); } + .feed-grid { grid-template-columns: 1fr; } + .brand-sub { display: none; } +} +@media (max-width: 560px) { + .tools-grid, .myproj-grid { grid-template-columns: 1fr; } +} + +/* ===================== 모바일 레이아웃 · 터치 다듬기 ===================== */ +@media (max-width: 640px) { + /* 헤더: 고정 높이 해제 → 줄바꿈 허용. 검색창은 둘째 줄 전체 폭으로. */ + .hdr-inner { flex-wrap: wrap; height: auto; min-height: 56px; padding: 8px 16px; row-gap: 8px; } + .brand { flex: 1 1 auto; min-width: 0; } + .hdr-right { margin-left: auto; } /* 브랜드와 같은 첫 줄, 우측 정렬 유지 */ + .hdr-search { display: flex; order: 10; flex-basis: 100%; max-width: none; } /* base 의 display:none 을 로드순서로 이김 → 둘째 줄 */ + + /* 터치 영역 ≥44px */ + .icon-btn, .modal-close { width: 44px; height: 44px; } + .hdr-link, .usermenu-btn { min-height: 44px; } + .profile-bio-edit { width: 40px; height: 40px; } /* 배지형이라 44는 과함 */ + .profile-avatar-edit { width: 36px; height: 36px; } + .filter-tab, .sort-tab, .vis-opt, .react-btn, .readme-btn, + .toggle-share-btn, .share-mini-btn, .new-proj-btn, .feed-star-btn, + .comment-link, .modal-action, .btn { min-height: 44px; } + + /* 크롭 스테이지 정사각 유지(profile.js 의 clientWidth==clientHeight 가정 충족) */ + .crop-stage { width: 100%; height: auto; aspect-ratio: 1 / 1; } + + /* 입력창 16px — iOS 포커스 시 자동확대 방지 */ + .hdr-search input, .share-input, .share-input.mono, + .comment-input, .profile-bio-form input { font-size: 16px; } + + /* 좌우 여백 축소 (24px → 16px) */ + .main { padding: 20px 16px 48px; } + .detail-wrap { padding: 20px 16px 48px; } /* project.ejs 단독 상세 */ + .footer-inner { padding: 16px; } + + /* 줄바꿈 / 프로필 히어로 세로 스택 */ + .section-head, .feed-head, .feed-head-right { flex-wrap: wrap; } + .profile-hero { flex-direction: column; align-items: center; text-align: center; gap: 14px; } + .profile-idline, .profile-metaline, .profile-bio-row, .profile-bio-form { justify-content: center; } + + /* 모달 여백 축소 */ + .modal-overlay { padding: 16px 12px; } + .modal-head { padding: 16px 16px 14px; } + .modal-body { padding: 14px 16px 4px; } + .modal-foot { padding: 12px 16px 18px; } + .modal-foot-actions{ padding: 12px 16px; } + .share-head, .share-body, .crop-body { padding: 16px; } + .crop-head { padding: 14px 16px; } +} diff --git a/views/_header.ejs b/views/_header.ejs index 515ab7f..d7597d2 100644 --- a/views/_header.ejs +++ b/views/_header.ejs @@ -12,6 +12,8 @@ + +