Skip to content

fix: 修复移动端代码块横向滚动崩坏问题#39

Closed
one-ea wants to merge 5 commits into
mainfrom
dev
Closed

fix: 修复移动端代码块横向滚动崩坏问题#39
one-ea wants to merge 5 commits into
mainfrom
dev

Conversation

@one-ea

@one-ea one-ea commented Apr 19, 2026

Copy link
Copy Markdown
Owner

问题描述

移动端浏览文章时,代码块内容左右无法滑动查看,代码被截断显示。

根本原因(三层叠加)

  1. code-line 用了 display: inline-block + min-width: 100%
    在移动端,100% 按父容器可视宽度计算,导致代码行不会撑开横向滚动区域,内容被直接截断而非触发滚动。

  2. pre / code 缺少 white-space: pre 强制不换行声明
    移动端浏览器在某些情况下会尝试对 display: block 的代码行内容换行而非横向溢出。

  3. .code-block-wrapper 缺少 -webkit-overflow-scrolling: touch
    iOS Safari 的惯性横向滑动未启用,用户体感上就是"完全滑不动"。

修复内容

位置 修改
.code-block-wrapper 增加 -webkit-overflow-scrolling: touch
.code-block-wrapper pre(移动端) 增加 width: max-content; min-width: 100%,确保 pre 可超出 wrapper 宽度
.code-block-wrapper pre 增加 white-space: pre,强制不换行
.prose-monolith pre code 增加 width: max-content; min-width: 100%; white-space: pre
.code-line display: inline-block 改为 display: block + width: max-content
pre:not(.hljs)(兜底) 同步增加 -webkit-overflow-scrolling: touchwhite-space: pre

测试要点

  • 移动端(iOS Safari / Android Chrome)长代码块可左右横向滑动
  • 桌面端代码块显示正常,行号、高亮、diff 颜色无变化
  • 亮色/暗色模式均正常

one-ea added 4 commits April 19, 2026 08:25
Critical/High:
- Sanitize custom_header/footer through DOMPurify before injection,
  forbid inline scripts, only allow external script src (fixes #1)
- Add security headers: X-Content-Type-Options, X-Frame-Options,
  Referrer-Policy, Permissions-Policy, HSTS (fixes #5)
- Remove authorEmail from public comment API, use DiceBear avatars
  based on nickname instead of Gravatar hash (fixes #2, #14)
- Add login rate limiting: 5 attempts per 15 min per IP (fixes #3)
- Reflect request Origin in CORS instead of wildcard (fixes #4)
- Add SSRF protection for WebDAV backup and image localization:
  only allow https://, block private/internal IPs (fixes #6, #13)
- Filter javascript: URIs in markdown link renderer (fixes #7)

Medium:
- Replace hardcoded reaction salt with REACTION_SALT env var (fixes #9)
- Add .env.* to .gitignore, remove .env.production from tracking (fixes #10)
- Disable source maps in production build (fixes #11)
- Remove infrastructure details from health endpoint (fixes #15)
…PR notice

- Add CookieConsent component: bottom banner with accept/reject,
  stores consent in localStorage, fires 'cookie-consent-accepted'
  event for third-party script injection gating
- Add /privacy route with full privacy policy page (bilingual)
- Gate custom_header/footer script injection behind cookie consent:
  scripts only load after user accepts; non-script HTML injects
  immediately as before
- Add GDPR warning in admin settings 'Extensions & Injection' tab
- Add PRIVACY.md to repo root
- Add privacy page link in cookie consent banner
- code-block-wrapper 增加 -webkit-overflow-scrolling: touch(iOS 惯性滚动)
- pre 和 code 元素增加 white-space: pre 强制不换行,内容真实撑开 wrapper
- 移动端 pre 增加 width: max-content + min-width: 100% 确保可超出容器宽度
- code-line 从 display: inline-block 改为 display: block,避免 min-width: 100%
  在移动端按父容器宽度错误计算导致代码不撑开横向滚动区域
- 兜底 pre:not(.hljs) 同步修复
@coderabbitai

coderabbitai Bot commented Apr 19, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@one-ea has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 37 minutes and 13 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 37 minutes and 13 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f807ff29-d145-4182-9d59-6240e4b13883

📥 Commits

Reviewing files that changed from the base of the PR and between 4185e93 and a36ddd9.

📒 Files selected for processing (1)
  • client/src/globals.css
📝 Walkthrough

Walkthrough

更新了代码块 CSS 样式,改进水平滚动和移动端自适应。调整了 padding 值、overflow 行为和宽度约束,增加了 iOS 惯性滚动支持,并优化了行号显示的尺寸和间距。

Changes

Cohort / File(s) Summary
代码块样式优化
client/src/globals.css
调整代码块容器的 padding(桌面端 16px 20px → 14px 24px,移动端 12px 16px);添加 -webkit-overflow-scrolling: touch 支持 iOS 惯性滚动;设置 code-block-wrapper pre 和独立 pre codeoverflow-x: visiblewhite-space: pre;在移动端强制 width: max-contentmin-width: 100% 以由容器控制滚动;调整代码行显示方式从 inline-block 改为 block;优化行号宽度(32px → 28px)和右间距(16px → 12px)。

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Suggested labels

frontend, bug, styles

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR标题遵循Conventional Commits格式(fix: + 描述),清晰准确描述了主要变更内容——修复移动端代码块横向滚动问题。
Description check ✅ Passed PR描述详尽阐明了问题原因(3层根本原因分析)、修复方案(6处CSS改动)和测试要点,与changeset完全对应,信息充分。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added bug Something isn't working frontend 前端 (React/Vite) 相关变更 styles CSS/UI 样式调整 labels Apr 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
client/src/globals.css (1)

459-470: width: max-content 作用域过宽,建议限定在块级代码场景

选择器 .prose-monolith pre code 会对所有 prose 内的 pre > code 生效,包括独立 pre:not(.hljs) 以及未来可能出现的其它 pre 变体。虽然当前独立 pre 也设置了 overflow-x: auto(Line 450)配合工作,但把 width: max-content 作为通用声明会让此 code 元素永远参与横向布局计算:

  • 内容很短时 min-width: 100% 可兜底,问题不大;
  • 但如果后续在 pre 上加入换行/软换行样式(例如 white-space: pre-wrap),width: max-content 会抵消换行效果,导致“看起来可以换行,实际强制撑开”的 bug。

建议要么在选择器上限定上下文(例如 .code-block-wrapper pre codepre:not(.hljs) code 分开处理),要么在注释中明确声明这是“与 white-space: pre 强耦合”的前提。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/globals.css` around lines 459 - 470, The `.prose-monolith pre
code` rule is too broad because `width: max-content` forces horizontal layout
even when other `pre` variants may later use wrapping; narrow its scope by
applying `width: max-content` only to block-code scenarios (e.g., change the
selector to target `.code-block-wrapper pre code` or `pre:not(.hljs) code`) or
add a clarifying comment that this rule is intentionally paired with
`white-space: pre` and will break `pre-wrap` behavior; update the selector in
the stylesheet and/or add the comment near the `.prose-monolith pre code` rule
so future edits don’t inadvertently enable wrapping while `max-content` remains
active.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/src/globals.css`:
- Around line 419-441: The pre element inside .prose-monolith
.code-block-wrapper currently holds horizontal padding which is lost when
content overflows and the wrapper scrolls; update styles so the scroll container
(.code-block-wrapper) provides the left/right padding instead of the inner pre
(or alternatively add padding-right to the overflowing inner element such as the
code tag or a right-side box-shadow on code). Concretely: remove or reduce
horizontal padding from .prose-monolith .code-block-wrapper pre and apply
equivalent padding to .code-block-wrapper (and for mobile adjust the wrapper
padding to match 12px/16px), or add a padding-right on the inner code element
(the element using width: max-content) so the visual right gutter remains when
scrolled to the end.
- Around line 662-671: The current .code-line uses display: block with width:
max-content and min-width calc(100% + 8px), which causes multi-line highlights
(.line-highlight, .diff-add, .diff-del) to right-align unevenly when lines have
different lengths; to fix, make the code container align highlight widths by
changing the parent code element to display: table (so rows can share a common
width) or change .code-line to display: table-row and keep its inner content as
table-cell, ensuring min-width behavior is preserved; update the CSS selectors
touching .code-line and the parent code element accordingly and verify visually
on mobile with multi-line diffs and horizontal scrolling.

---

Nitpick comments:
In `@client/src/globals.css`:
- Around line 459-470: The `.prose-monolith pre code` rule is too broad because
`width: max-content` forces horizontal layout even when other `pre` variants may
later use wrapping; narrow its scope by applying `width: max-content` only to
block-code scenarios (e.g., change the selector to target `.code-block-wrapper
pre code` or `pre:not(.hljs) code`) or add a clarifying comment that this rule
is intentionally paired with `white-space: pre` and will break `pre-wrap`
behavior; update the selector in the stylesheet and/or add the comment near the
`.prose-monolith pre code` rule so future edits don’t inadvertently enable
wrapping while `max-content` remains active.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9a05148d-3eee-4420-9e08-9b671d31ad34

📥 Commits

Reviewing files that changed from the base of the PR and between 3aaa008 and 4185e93.

📒 Files selected for processing (1)
  • client/src/globals.css
📜 Review details
⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: ESLint 安全扫描
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (1)
client/src/globals.css

⚙️ CodeRabbit configuration file

client/src/globals.css: 全局样式和 CSS 变量系统。审查时请关注: 1. [data-theme="light"] 和默认暗色主题的变量是否配对 2. OKLCH 色值的明度/色度是否合理 3. 是否有遗漏的选择器未覆盖亮色模式

Files:

  • client/src/globals.css
🔇 Additional comments (1)
client/src/globals.css (1)

416-416: iOS 惯性滚动补丁 LGTM

-webkit-overflow-scrolling: touch 配合 overflow-x: auto 是 iOS Safari 解决横向惯性滑动的标准做法,注释也写清了意图。同样的声明在独立 pre:not(.hljs)(Line 451)处也补上,覆盖一致。

Comment thread client/src/globals.css
Comment on lines 419 to 441
.prose-monolith .code-block-wrapper pre {
margin: 0;
padding: 16px 20px;
padding: 14px 24px;
border-radius: 0;
border: none;
/* 不在 pre 层裁剪,由 wrapper 统一负责横向滚动 */
overflow-x: visible;
/* 强制不换行,让内容真实撑开 wrapper */
white-space: pre;
font-size: 13px;
line-height: 1.85;
letter-spacing: 0;
font-family: ui-monospace, "SF Mono", "Cascadia Code", "Fira Code", Consolas, monospace;
}

/* 移动端代码块右侧留白增强 */
@media (max-width: 768px) {
.prose-monolith .code-block-wrapper pre {
padding-right: 24px;
padding: 12px 16px;
/* 移动端:确保 pre 宽度可以超出 wrapper,由 wrapper 滚动 */
width: max-content;
min-width: 100%;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

滚动末端右内边距丢失的潜在视觉问题

.code-block-wrapper 负责横向滚动,而子 pre 设置了 padding: 14px 24px(移动端 12px 16px)。由于内部 codewidth: max-content 会让内容溢出 pre,滚动容器是 wrapper,滚到最右端时 pre 的右内边距不会跟随内容出现在视口末尾——末行右侧会紧贴 wrapper 边缘,缺少 24px/16px 的呼吸空间。这是 overflow-x: auto 容器 + 内部盒 padding 的经典问题。

如果希望右侧保留一致的留白,可以把横向 padding 从 pre 移到 wrapper,或者在 code 上使用 padding-right / box-shadow 兜住末端。示意:

♻️ 一种可选修正(任选其一即可)
 .prose-monolith .code-block-wrapper pre {
   margin: 0;
-  padding: 14px 24px;
+  padding: 14px 0;
   ...
 }
+.prose-monolith .code-block-wrapper pre code {
+  padding-right: 24px;
+}

桌面端与亮/暗色模式下行为一致,不影响主题变量配对。可按需采用。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/globals.css` around lines 419 - 441, The pre element inside
.prose-monolith .code-block-wrapper currently holds horizontal padding which is
lost when content overflows and the wrapper scrolls; update styles so the scroll
container (.code-block-wrapper) provides the left/right padding instead of the
inner pre (or alternatively add padding-right to the overflowing inner element
such as the code tag or a right-side box-shadow on code). Concretely: remove or
reduce horizontal padding from .prose-monolith .code-block-wrapper pre and apply
equivalent padding to .code-block-wrapper (and for mobile adjust the wrapper
padding to match 12px/16px), or add a padding-right on the inner code element
(the element using width: max-content) so the visual right gutter remains when
scrolled to the end.

Comment thread client/src/globals.css
Comment on lines 662 to 671
.prose-monolith pre code .code-line {
display: inline-block;
min-width: 100%;
/* 改为 block,避免 inline-block + min-width:100% 在移动端错误计算宽度 */
display: block;
padding: 0 4px;
margin: 0 -4px;
border-radius: 2px;
/* 高亮/diff 背景需要撑满整行 */
width: max-content;
min-width: calc(100% + 8px); /* 补偿 -4px 的双侧 margin */
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# 首先查看globals.css文件的662-671行及周围上下文
cat -n client/src/globals.css | sed -n '655,680p'

Repository: one-ea/Monolith

Length of output: 817


🏁 Script executed:

# 搜索相关的选择器定义
rg -n "\.code-line|\.line-highlight|\.diff-add|\.diff-del" client/src/globals.css -B2 -A2

Repository: one-ea/Monolith

Length of output: 1484


🏁 Script executed:

# 查找主题变量定义
rg -n "\[data-theme|--.*-bg|--.*-highlight" client/src/globals.css | head -20

Repository: one-ea/Monolith

Length of output: 1377


🏁 Script executed:

# 搜索所有包含 .code-line 的选择器定义
rg -n "\.code-line" client/src/globals.css -A3

Repository: one-ea/Monolith

Length of output: 350


🏁 Script executed:

# 检查是否有其他暗色主题下但未在亮色主题中定义的选择器
rg -n "\.prose-monolith pre code" client/src/globals.css | grep -v "data-theme" | head -30

Repository: one-ea/Monolith

Length of output: 304


🏁 Script executed:

# 检查亮色主题下 .prose-monolith pre code 相关的所有定义
rg -n "\[data-theme=\"light\"\].*\.prose-monolith.*code" client/src/globals.css -A2

Repository: one-ea/Monolith

Length of output: 2197


.code-line 改为 block 解决了移动端宽度计算问题,但需注意多行高亮的右端对齐

inline-block 改为 block,结合 width: max-contentmin-width: calc(100% + 8px) 的方案正确。需留意当 .line-highlight / .diff-add / .diff-del 跨越多行且各行长度不等时,高亮背景右边缘会根据每行自身内容宽度参差不齐——短行的高亮仅被 min-width 拉伸到容器宽度,长行超出时高亮只会铺到行末尾。横向滚动时视觉可能产生"断层感"。

如需统一对齐到最宽行,可考虑在父级 code 使用 display: table 或在 .code-linedisplay: table-row,但需权衡改动范围。

亮色主题的高亮颜色(.line-highlight / .diff-add / .diff-del)已完整覆盖,OKLCH 色值合理。建议在移动设备上用包含多行差异代码的块实测高亮背景效果。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/globals.css` around lines 662 - 671, The current .code-line uses
display: block with width: max-content and min-width calc(100% + 8px), which
causes multi-line highlights (.line-highlight, .diff-add, .diff-del) to
right-align unevenly when lines have different lengths; to fix, make the code
container align highlight widths by changing the parent code element to display:
table (so rows can share a common width) or change .code-line to display:
table-row and keep its inner content as table-cell, ensuring min-width behavior
is preserved; update the CSS selectors touching .code-line and the parent code
element accordingly and verify visually on mobile with multi-line diffs and
horizontal scrolling.

code-line 改回 display: inline-block,移除 width: max-content 和
min-width: calc(100%+8px) 的循环依赖写法(该写法导致移动端代码
内容完全消失)。pre 的 white-space: pre 已足够阻止换行,
wrapper 的 overflow-x: auto 负责横向滚动。
@one-ea one-ea closed this Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working frontend 前端 (React/Vite) 相关变更 styles CSS/UI 样式调整

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant