From 7ed53050b79e65eb2801629b026d7d0683f9ac8f Mon Sep 17 00:00:00 2001 From: Le Date: Sat, 4 Jul 2026 11:48:54 +0700 Subject: [PATCH] Fix global CSS bug silently disabling all Tailwind margin/padding utilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit index.css had a hand-written reset (`*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }`) left over from before Tailwind was added, sitting outside any `@layer` block. Per the CSS Cascade Layers spec, unlayered rules always beat layered rules regardless of selector specificity — since every Tailwind utility class lives inside `@layer utilities`, this one `*`-selector rule was silently overriding every single margin/padding utility (p-*, m-*, mx-auto, etc.) across the entire app. Other properties (colors, borders, gap) weren't affected, which is why this went unnoticed through the whole Tailwind migration — only spacing/centering was silently broken, not colors or general layout. Tailwind's own preflight (already loaded via `@import "tailwindcss"`, correctly placed inside `@layer base`) provides the identical reset, so the duplicate unlayered copy was simply deleted. Also fixed two smaller, related issues found while investigating: an inline `style={{ maxWidth: '100vw' }}` on Login/Register's auth-card overrode its CSS class's `max-width: 400px`, stretching it to near full viewport width on screens wider than ~400px (invisible on mobile, obvious on laptop/desktop — probably what originally looked like "responsive wasn't fixed"). And BacktestPage.tsx, unlike every other page, rendered its `mx-auto`-centered container as a direct child of #root (which has `display: flex; flex-direction: column`), so flexbox's default align-items: stretch overrode the centering; wrapped it in the same min-h-screen container pattern every other page already uses. Verified via direct getComputedStyle()/getBoundingClientRect() measurement (screenshots in this environment don't reliably reflect true layout) — margin-inline resolved to 0px before the fix, 183px (correctly centered) after. Frontend build clean, 170 backend tests unaffected (CSS-only change). Co-Authored-By: Claude Sonnet 5 --- frontend/src/features/auth/LoginPage.tsx | 2 +- frontend/src/features/auth/RegisterPage.tsx | 2 +- .../src/features/backtest/BacktestPage.tsx | 4 +- frontend/src/index.css | 15 ++-- theo_doi_trading-portal_v9.md | 79 +++++++++++++++++++ 5 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 theo_doi_trading-portal_v9.md diff --git a/frontend/src/features/auth/LoginPage.tsx b/frontend/src/features/auth/LoginPage.tsx index 837ca6b..df07d04 100755 --- a/frontend/src/features/auth/LoginPage.tsx +++ b/frontend/src/features/auth/LoginPage.tsx @@ -29,7 +29,7 @@ export default function LoginPage() { return (
-
+

{t('login.title')}

{t('login.subtitle')}

{error &&
{error}
} diff --git a/frontend/src/features/auth/RegisterPage.tsx b/frontend/src/features/auth/RegisterPage.tsx index a19eb35..9bbcd10 100755 --- a/frontend/src/features/auth/RegisterPage.tsx +++ b/frontend/src/features/auth/RegisterPage.tsx @@ -31,7 +31,7 @@ export default function RegisterPage() { return (
-
+

Trading Portal

Create Account

{error &&
{error}
} diff --git a/frontend/src/features/backtest/BacktestPage.tsx b/frontend/src/features/backtest/BacktestPage.tsx index 796c3aa..db0feb2 100755 --- a/frontend/src/features/backtest/BacktestPage.tsx +++ b/frontend/src/features/backtest/BacktestPage.tsx @@ -161,7 +161,8 @@ export default function BacktestPage() { }, [exchange]); return ( -
+
+

📊 {t('Backtest')}

@@ -181,6 +182,7 @@ export default function BacktestPage() { symbols={symbols} tradeSize={tradeSize} setTradeSize={setTradeSize} /> )}
+
); } diff --git a/frontend/src/index.css b/frontend/src/index.css index 3219de4..39774cf 100755 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -64,14 +64,13 @@ background-color: var(--bg-primary); } -/* --- Global Reset --- */ -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - padding: 0; -} +/* Global box-sizing/margin/padding reset is handled by Tailwind's own + preflight (inside @layer base, from `@import "tailwindcss"` above). + A hand-written unlayered copy of the same reset used to live here — + CSS Cascade Layers give ANY unlayered rule priority over ALL layered + rules regardless of selector specificity, so that unlayered `* { margin: + 0; padding: 0 }` was silently overriding every single Tailwind margin/ + padding utility class (p-*, m-*, mx-auto, etc.) app-wide. Removed. */ html { height: 100%; diff --git a/theo_doi_trading-portal_v9.md b/theo_doi_trading-portal_v9.md new file mode 100644 index 0000000..14e63cb --- /dev/null +++ b/theo_doi_trading-portal_v9.md @@ -0,0 +1,79 @@ +# Theo dõi đánh giá dự án Trading Portal — v9 + +> **Ngày đánh giá gốc:** 2026-07-03 +> **Cập nhật v1-v8:** xem các file `theo_doi_trading-portal_v1.md`…`v8.md` +> **Cập nhật v9 (lần này):** 2026-07-04 — sửa 1 bug CSS toàn cục nghiêm trọng khiến **toàn bộ class margin/padding của Tailwind trên cả app bị vô hiệu hóa âm thầm**, cộng 2 bug nhỏ hơn liên quan (login/register card giãn to trên desktop, BacktestPage không canh giữa) +> **Người thực hiện:** Claude (Sonnet 5), theo yêu cầu của tien.a.le@accenture.com +> **Quy ước đặt tên:** Mỗi lần có thay đổi lớn → tạo bản mới `theo_doi_trading-portal_v10.md`, ... giữ nguyên các bản cũ làm lịch sử. + +--- + +## 1. Tổng quan dự án + +(Không đổi — xem [theo_doi_trading-portal_v2.md](theo_doi_trading-portal_v2.md) mục 1.) + +--- + +## 2. Bối cảnh + +Người dùng phản ánh: "giao diện trên laptop to quá chừng" — nghi ngờ việc rà soát responsive ở v6 (mục 3, task #34) chưa thực sự đầy đủ. Kiểm tra trực tiếp bằng trình duyệt ở độ phân giải laptop thực tế (1366×768) thay vì chỉ dựa vào ảnh chụp màn hình, phát hiện **3 vấn đề riêng biệt**, xếp theo mức độ nghiêm trọng tăng dần khi đào sâu: + +### 2.1 Bug nhỏ: `LoginPage`/`RegisterPage` có inline style thừa + +`
` — inline style luôn thắng CSS class, nên `max-width: 100vw` đè lên `max-width: 400px` của class `.auth-card`, khiến khung đăng nhập giãn gần hết chiều rộng màn hình ở độ phân giải lớn (ẩn ở mobile vì 100vw ở đó vốn đã nhỏ, nên không ai để ý). `box-sizing: border-box` trong cùng inline style cũng thừa (đã có reset toàn cục). **Đã xóa cả 2 inline style** ở cả `LoginPage.tsx` và `RegisterPage.tsx`. + +### 2.2 Bug nhỏ: `BacktestPage.tsx` không canh giữa + +Trang này là trang **duy nhất** trong số các trang dùng pattern `mx-auto max-w-[Npx]` mà không có div bọc ngoài (không giống `AnalyticsPage`/`ProfilePage`/`AdminPage`/`AuditLogPage` đều có nav bar + wrapper `min-h-screen` bên ngoài). Vì `#root` có `display:flex; flex-direction:column`, div `mx-auto` trở thành flex item trực tiếp của `#root`, và `align-items` mặc định (`normal`→`stretch`) làm nó giãn full-width thay vì canh giữa. **Đã bọc thêm 1 div `min-h-screen bg-bg-primary` bên ngoài**, đúng theo pattern các trang khác. + +### 2.3 Bug lớn — nghiêm trọng nhất: CSS reset viết tay đè lên toàn bộ Tailwind margin/padding utilities + +Khi đào sâu tìm hiểu tại sao `mx-auto` "không hoạt động" ngay cả sau khi đã bọc div đúng cách ở mục 2.2, phát hiện: `index.css` có đoạn reset viết tay từ trước khi thêm Tailwind: + +```css +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} +``` + +Đoạn này nằm **ngoài mọi `@layer`** của Tailwind (không nằm trong `@layer base/components/utilities`). Theo đặc tả CSS Cascade Layers: **style không thuộc layer nào luôn thắng mọi style thuộc layer nào đó, bất kể độ đặc hiệu (specificity) selector**. Vì TOÀN BỘ utility class của Tailwind (`.p-5`, `.mx-auto`, `.mb-5`, `.px-4`, v.v.) đều nằm trong `@layer utilities`, đoạn reset viết tay này (dù chỉ dùng selector `*` — độ đặc hiệu thấp nhất có thể) vẫn **đè lên và vô hiệu hóa TẤT CẢ margin/padding utility của Tailwind trên toàn bộ ứng dụng**. + +**Vì sao không ai nhận ra ngay:** các thuộc tính khác (màu nền, viền, `gap` giữa các phần tử flex/grid, font, border-radius...) không bị ảnh hưởng (không phải margin/padding), nên giao diện vẫn "trông tạm ổn" ở cái nhìn thoáng qua — chỉ khi kiểm tra kỹ khoảng cách/canh giữa mới lộ ra. Đây chính xác là loại lỗi tạo cảm giác "giao diện to quá, không đúng chỗ" mà người dùng mô tả — hàng trăm chỗ dùng `p-*`/`m-*` xuyên suốt 14 file đã chuyển sang Tailwind đều bị ảnh hưởng. + +**Cách sửa:** Tailwind v4's preflight (bên trong `@layer base`, tự động có sẵn từ `@import "tailwindcss"`) **đã cung cấp sẵn đúng loại reset y hệt** (`box-sizing:border-box; margin:0; padding:0` cho `*, ::before, ::after`), chỉ khác là nó nằm ĐÚNG trong layer, nên các utility trong `@layer utilities` (khai báo sau `base` trong thứ tự layer) mới override đúng theo thiết kế. → **Xóa hẳn đoạn reset viết tay trùng lặp** trong `index.css`, để Tailwind's preflight tự lo, không cần viết lại. + +### 2.4 Kiểm chứng + +Đo trực tiếp trong trình duyệt (không chỉ dựa vào ảnh chụp — ảnh chụp của công cụ preview trong phiên làm việc này không phản ánh chính xác layout thật, đã xác nhận qua đối chiếu với `getBoundingClientRect()`/`getComputedStyle()`): + +| Trước khi sửa | Sau khi sửa | +|---|---| +| `.mx-auto` (BacktestPage): `margin-left/right: 0px`, giãn full 1366px | `margin-left/right: 183px`, đúng 1000px canh giữa | +| `.p-5`: `padding: 0px` | `padding: 20px` (đúng `5 × 4px` theo thang spacing Tailwind) | +| `.auth-card` (Login, sau fix 2.1): full width ~1268px | đúng 400px, canh giữa cả ngang lẫn dọc | + +Build frontend sạch, 170 test backend vẫn pass (thay đổi chỉ ở CSS, không đụng logic). + +--- + +## 3. Toàn bộ nhược điểm & rủi ro — bổ sung mới trong v9 + +| # | Vấn đề | Trạng thái | +|---|---|---| +| ee | (mới) Inline style `maxWidth:'100vw'` đè `.auth-card`'s `max-width:400px` trên Login/Register | ✅ Đã sửa (mục 2.1) | +| ff | (mới) `BacktestPage.tsx` thiếu wrapper, bị flex-stretch của `#root` làm mất canh giữa | ✅ Đã sửa (mục 2.2) | +| gg | (mới, **nghiêm trọng**) CSS reset viết tay không nằm trong `@layer`, vô hiệu hóa toàn bộ margin/padding utility của Tailwind app-wide | ✅ Đã sửa (mục 2.3) | + +**Bài học quy trình:** việc rà soát responsive ở v6 (mục "Review UI end-to-end", task #34) dựa nhiều vào ảnh chụp màn hình ở kích thước mobile/tablet — bug này chỉ lộ rõ ở kích thước **laptop/desktop** (1280px+) và cần đo trực tiếp `getComputedStyle()`/`getBoundingClientRect()` mới phát hiện được, vì ảnh chụp không đáng tin cậy để kiểm tra chính xác khoảng cách/kích thước (đúng như mô tả của chính công cụ preview_screenshot). Từ nay nếu nghi ngờ vấn đề layout tinh vi, nên ưu tiên `preview_eval` + `getComputedStyle` thay vì chỉ nhìn ảnh chụp. + +--- + +## 4. Lịch sử phiên bản + +| Phiên bản | Ngày | Thay đổi | +|---|---|---| +| v0-v7 | 2026-07-03 — 2026-07-04 | Xem file tương ứng | +| v8 | 2026-07-04 | Wire ADX/regime vào bộ lọc tín hiệu dùng chung, hợp nhất 2 hệ thống regime. 170 test pass. | +| v9 | 2026-07-04 | Sửa bug CSS toàn cục: reset viết tay không nằm trong `@layer` vô hiệu hóa toàn bộ margin/padding utility Tailwind app-wide (gg) — nguyên nhân chính khiến giao diện "to quá" trên laptop. Kèm 2 bug nhỏ: inline style đè max-width trên Login/Register (ee), BacktestPage thiếu wrapper mất canh giữa (ff). Build sạch, 170 test pass (không đổi logic). |