正文图片左缩进导致右侧溢出正文块(text-indent 被继承) #28

Closed
opened 2026-10-27 14:56:53 +00:00 by laoyang · 2 comments
Owner

现象

正文里插入的图片,左边跟着段落一起缩进了,右边却从正文块里溢出去。

用户原话:

第一个是文章中的图,左侧好像和文章段落一样缩进了,导致图片右侧从文章的块里面溢出了。

已实测确认根因(线上真实几何,不是源码推断)

测的是线上文章 /2022/05/set-font-in-latex.html,
用 Chromium 无头浏览器 1440 视口量 getBoundingClientRect():

正文容器 .article .content:  left=95   right=918.33   padding 16px
正文可绘制区(扣掉 padding): left=111  right=902.33   宽 791.33

那张 LaTeX 配图:             left=143  right=934.33   宽 791.33
                            ↑ 左缩进 32px      ↑ 右溢出 32px

父级链:

DIV.content   left=95    right=918.33   text-indent: 0px
  P           left=111   right=902.33   text-indent: 32px   ← 缩进在这里
    A.yang-lb-item  left=143  right=934.33  text-indent: 32px
      IMG       left=143  right=934.33  width=791.33

机理(assets/css/site.css:20):

.article .content p { text-indent: 2em; }   /* 16px 字号 ⇒ 32px */

text-indent 是可继承属性。WordPress 把图片插在 <p> 里时,图片作为行内替换元素
落在段落首行 ⇒ 继承了 32px 缩进,起点右移。

而 max-width: 100%(kratos.css:1087)里的 100% 指的是包含块的内容宽度
(p 的 791.33px),不是"缩进之后剩下的宽度"。所以:

图片宽 = 791.33(全宽)
起点   = 正文左边界 + 32px
右边界 = 正文左边界 + 32 + 791.33 = 正文右边界 + 32

左缩进多少,右侧就溢出多少,二者永远相等 —— 这正是实测的 32px / 32px。

我用注入测试图验证了四种摆放形态,只有「在 p 内 + display:inline」这一种会溢出:

摆放 左缩进 右溢出 width
① <p> 内 + inline(WP 默认) 32px 32px 791.33
② <p> 内 + block 0 0 791.33
③ <p> 外 + block 0 0 791.33
④ <p> 外 + inline 0 0 791.33

用户选定的修法

图片单独一排、左右都不缩进(段落仍然首行缩进两字,这个观感保留)。

不要动 text-indent: 2em 本条规则 —— 它给正文段落的首行缩进是站长期望的效果,
去掉会改变全站所有文章的观感。

要做的改动

给正文里的图片加一条规则,让它不被段落缩进带走、且宽度按可绘制区算:

  • text-indent: 0(切断继承)
  • display: block(自成一行,不参与首行)
  • margin-left: auto; margin-right: auto(居中;若用户想要左对齐,改成 margin: 0 auto 0 0)
  • max-width: 100% 保持

⚠️ 需要同时确认这几类不会被打坏(它们都是 img,但语义不同):

  1. 灯箱链接:图片外面套着 <a class="yang-lb-item">,规则应写成
    .content img(含后代)而不是只看直接子元素,否则 <p><a><img></a></p> 这种量不到
  2. 表情 img.wp-smiley:在正文里是行内的,不能变 block(kratos.css 里有 .wp-smiley 相关规则)
  3. 右浮动小图 .alignright(kratos.css:1082):float:right 的图本来就不该吃 text-indent,
    改成 block 会破坏浮动布局
  4. .aligncenter / .alignleft:同理要保留浮动/居中语义
  5. 评论区的图(.yang-comment-content img):本次不动

验收标准

  1. 打开 /2022/05/set-font-in-latex.html:
    配图左边与正文文字左边界对齐(不再比文字靠右 32px),右边不超出正文块
  2. 几何实测:图片 left 等于正文可绘制区 left(容差 ≤1px),right ≤ 正文可绘制区 right(容差 ≤1px)
  3. 段落首行缩进仍然保留(打开任意文章看第一行是否还缩两字)
  4. 表情图(评论区/正文)不变形、不换行成块
  5. 带 alignright / aligncenter 的图仍保持原位置语义
  6. 灯箱点击仍然正常(点图还能放大)
  7. 手机 390 视口下同样不溢出

涉及文件(预估)

  • assets/css/site.css(新增规则,紧跟现有 text-indent 那条后面,注释写清为什么)
  • 需要重新压 assets/css/kratos.min.css?视规则放在哪个文件而定 —— site.css 是独立文件还是并入 min,按现有构建方式处理
  • style.css 版本号
## 现象 正文里插入的图片,**左边跟着段落一起缩进了,右边却从正文块里溢出去**。 用户原话: > 第一个是文章中的图,左侧好像和文章段落一样缩进了,导致图片右侧从文章的块里面溢出了。 ## 已实测确认根因(线上真实几何,不是源码推断) 测的是线上文章 [`/2022/05/set-font-in-latex.html`](https://yangyq.net/2022/05/set-font-in-latex.html), 用 Chromium 无头浏览器 1440 视口量 `getBoundingClientRect()`: ``` 正文容器 .article .content: left=95 right=918.33 padding 16px 正文可绘制区(扣掉 padding): left=111 right=902.33 宽 791.33 那张 LaTeX 配图: left=143 right=934.33 宽 791.33 ↑ 左缩进 32px ↑ 右溢出 32px ``` 父级链: ``` DIV.content left=95 right=918.33 text-indent: 0px P left=111 right=902.33 text-indent: 32px ← 缩进在这里 A.yang-lb-item left=143 right=934.33 text-indent: 32px IMG left=143 right=934.33 width=791.33 ``` **机理**(`assets/css/site.css:20`): ```css .article .content p { text-indent: 2em; } /* 16px 字号 ⇒ 32px */ ``` `text-indent` 是**可继承属性**。WordPress 把图片插在 `<p>` 里时,图片作为行内替换元素 落在段落首行 ⇒ **继承了 32px 缩进**,起点右移。 而 `max-width: 100%`(`kratos.css:1087`)里的 100% 指的是**包含块的内容宽度** (p 的 791.33px),**不是"缩进之后剩下的宽度"**。所以: ``` 图片宽 = 791.33(全宽) 起点 = 正文左边界 + 32px 右边界 = 正文左边界 + 32 + 791.33 = 正文右边界 + 32 ``` **左缩进多少,右侧就溢出多少,二者永远相等** —— 这正是实测的 32px / 32px。 我用注入测试图验证了四种摆放形态,只有「在 p 内 + display:inline」这一种会溢出: | 摆放 | 左缩进 | 右溢出 | width | |---|---|---|---| | ① `<p>` 内 + inline(WP 默认) | **32px** | **32px** | 791.33 | | ② `<p>` 内 + block | 0 | 0 | 791.33 | | ③ `<p>` 外 + block | 0 | 0 | 791.33 | | ④ `<p>` 外 + inline | 0 | 0 | 791.33 | ## 用户选定的修法 **图片单独一排、左右都不缩进**(段落仍然首行缩进两字,这个观感保留)。 不要动 `text-indent: 2em` 本条规则 —— 它给正文段落的首行缩进是站长期望的效果, 去掉会改变全站所有文章的观感。 ## 要做的改动 给正文里的图片加一条规则,让它不被段落缩进带走、且宽度按可绘制区算: - `text-indent: 0`(切断继承) - `display: block`(自成一行,不参与首行) - `margin-left: auto; margin-right: auto`(居中;若用户想要左对齐,改成 `margin: 0 auto 0 0`) - `max-width: 100%` 保持 ⚠️ 需要同时确认这几类不会被打坏(它们都是 `img`,但语义不同): 1. **灯箱链接**:图片外面套着 `<a class="yang-lb-item">`,规则应写成 `.content img`(含后代)而不是只看直接子元素,否则 `<p><a><img></a></p>` 这种量不到 2. **表情 `img.wp-smiley`**:在正文里是行内的,**不能**变 block(`kratos.css` 里有 `.wp-smiley` 相关规则) 3. **右浮动小图** `.alignright`(`kratos.css:1082`):`float:right` 的图本来就不该吃 text-indent, 改成 block 会破坏浮动布局 4. **`.aligncenter` / `.alignleft`**:同理要保留浮动/居中语义 5. **评论区的图**(`.yang-comment-content img`):本次不动 ## 验收标准 1. 打开 [`/2022/05/set-font-in-latex.html`](https://yangyq.net/2022/05/set-font-in-latex.html): 配图**左边与正文文字左边界对齐**(不再比文字靠右 32px),**右边不超出正文块** 2. 几何实测:图片 `left` 等于正文可绘制区 `left`(容差 ≤1px),`right` ≤ 正文可绘制区 `right`(容差 ≤1px) 3. 段落首行缩进**仍然保留**(打开任意文章看第一行是否还缩两字) 4. 表情图(评论区/正文)不变形、不换行成块 5. 带 `alignright` / `aligncenter` 的图仍保持原位置语义 6. 灯箱点击仍然正常(点图还能放大) 7. 手机 390 视口下同样不溢出 ## 涉及文件(预估) - `assets/css/site.css`(新增规则,紧跟现有 `text-indent` 那条后面,注释写清为什么) - 需要重新压 `assets/css/kratos.min.css`?**视规则放在哪个文件而定** —— site.css 是独立文件还是并入 min,按现有构建方式处理 - `style.css` 版本号
Author
Owner

已发布 3.2.60(commit cca7497)

改了什么

assets/css/site.css 新增两条规则 + 一条让路规则:

.article .content img {
  text-indent: 0;
  display: block;
  margin-left: auto;
  margin-right: auto;
}

/* 🔴 灯箱链接:必须一起清零。它是 inline-block,本身就是参与父级
 *    行内排版的盒子 —— 只清 img 无论用,位置由它决定。 */
.article .content a.yang-lb-item {
  text-indent: 0;
  display: block;
  line-height: 0;
  margin-left: auto;
  margin-right: auto;
}

表情图与对齐类图片各自保留原语义(表情图 display:inline、对齐图交给
kratos 的 float 规则,用 :where() 把新规则特异性降到 0 不参与竞争)。

根因(实测,非源码推断)

现场量到的几何:

正文容器 .article .content:  left=95   right=918.33   padding 16px
正文可绘制区:                left=111  right=902.33   宽 791.33
LaTeX 配图:                  left=143  right=934.33   ← 左缩进 32,右溢出 32

父级链(用 CDP CSS.getMatchedStylesForNode 抓的,不是猜的):

DIV.content       text-indent:0px
  P               text-indent:32px      ← 缩进来源(2em × 16px)
    A.yang-lb-item  inline-block  text-indent:32px   ← 真凶
      IMG           display:block  text-indent:0px

三层机理:

  1. text-indent 是可继承属性,段落那句 text-indent:2em 会遗传下去;
  2. 光给 img 清零不够 —— 灯箱把图包进 <a class="yang-lb-item">,
    那个盒子是 inline-block,本身就是参与父级行内排版的主体,
    盒子起点照样被推走;
  3. max-width:100% 的 100% 是容器内容宽度,不是"缩进后剩下的宽度"
    ⇒ 左缩进多少,右侧就溢出多少,两者永远相等。

验证结果

判据 52 / 0(真实页面 + page.route 拦截替换新 CSS,桌面 1440 / 手机 390 双端面):

PASS A3 桌面1440 右侧不溢出正文块      [right=902.33 ≤ 902.33 (溢出 0.00)]
PASS A3 桌面1440 左侧与正文左边界对齐   [left=111.00 vs 111.00 (偏差 0.00)]
PASS A3 桌面1440 包裹它的灯箱链接已块级化   [a.yang-lb-item display=block]
PASS A3 桌面1440 包裹盒 text-indent 已清零  [text-indent=0px]
PASS A3 手机390  右侧不溢出正文块      [right=359.00 ≤ 359.00 (溢出 0.00)]
PASS A1 段落首行缩进仍保留(32px / 30px)—— 没把段落自己也弄成不缩进

反证 10 / 10 全部抓到(证明判据有牙齿,不是恒绿):

注入 预期 实测
删掉灯箱链接的 text-indent:0 包裹盒被推歪 49/3 ✅
删掉整条灯箱规则(退回 3.2.59) 溢出复现 39/13 ✅
删掉 img 自身的 text-indent:0 CDP 抓到少一条 51/1 ✅
灯箱改回 inline-block 未块级化 41/11 ✅
阴性对照:加一条无关规则 不该报红 52/0 ✅

反证里的两个细节值得记一下(顺手踩到的):

  • Z2 第一版用 document.styleSheets[].cssRules 搜选择器,恒红 ——
    本项目 CSS 全走 CDN 域名,外链表一律 SecurityError 读不到
    (实测 12 张表里只有内联 <style> 可读)。改用 CDP + md5 双证。
  • Z3 的过滤条件写成 p.name && p.value && !p.parsedOk === false
    —— parsedOk 是 undefined,!undefined === false 恒为 false,
    于是一条属性都留不下,判据恒红。否定式断言在 undefined 上是坑。

已上线

https://yangyq.net/theme-update/update.json
{"version":"3.2.60",
 "download_url":".../kratos_yang-3.2.60.zip",
 "details_url":".../readme.html",
 "md5":"6b6c5ff1bdb9be2373801a59d71fdec7"}
  • zip 与本地字节一致:6b6c5ff1bdb9be2373801a59d71fdec7(4824374 字节)
  • 重复打包 md5 相同(zip 内时间戳固定 1980-01-01)
  • readme 已并入 3.2.60 节,历史 50 段完整保留(new.endswith(old) 为真)
  • transient 已清,后台「更新」页可立刻看到 3.2.60

⚠️ 服务器主题目录仍是 3.2.59(红线:只发 zip,不解包覆盖)。
需要你在后台「外观 → 主题」点一次升级,升级后我再补一条确认。

## 已发布 3.2.60(commit `cca7497`) ### 改了什么 `assets/css/site.css` 新增两条规则 + 一条让路规则: ```css .article .content img { text-indent: 0; display: block; margin-left: auto; margin-right: auto; } /* 🔴 灯箱链接:必须一起清零。它是 inline-block,本身就是参与父级 * 行内排版的盒子 —— 只清 img 无论用,位置由它决定。 */ .article .content a.yang-lb-item { text-indent: 0; display: block; line-height: 0; margin-left: auto; margin-right: auto; } ``` 表情图与对齐类图片各自保留原语义(表情图 `display:inline`、对齐图交给 kratos 的 float 规则,用 `:where()` 把新规则特异性降到 0 不参与竞争)。 ### 根因(实测,非源码推断) 现场量到的几何: ``` 正文容器 .article .content: left=95 right=918.33 padding 16px 正文可绘制区: left=111 right=902.33 宽 791.33 LaTeX 配图: left=143 right=934.33 ← 左缩进 32,右溢出 32 ``` 父级链(用 CDP `CSS.getMatchedStylesForNode` 抓的,不是猜的): ``` DIV.content text-indent:0px P text-indent:32px ← 缩进来源(2em × 16px) A.yang-lb-item inline-block text-indent:32px ← 真凶 IMG display:block text-indent:0px ``` 三层机理: 1. `text-indent` 是**可继承**属性,段落那句 `text-indent:2em` 会遗传下去; 2. 光给 `img` 清零不够 —— 灯箱把图包进 `<a class="yang-lb-item">`, 那个盒子是 `inline-block`,**本身就是参与父级行内排版的主体**, 盒子起点照样被推走; 3. `max-width:100%` 的 100% 是**容器内容宽度**,不是"缩进后剩下的宽度" ⇒ 左缩进多少,右侧就溢出多少,**两者永远相等**。 ### 验证结果 判据 **52 / 0**(真实页面 + `page.route` 拦截替换新 CSS,桌面 1440 / 手机 390 双端面): ``` PASS A3 桌面1440 右侧不溢出正文块 [right=902.33 ≤ 902.33 (溢出 0.00)] PASS A3 桌面1440 左侧与正文左边界对齐 [left=111.00 vs 111.00 (偏差 0.00)] PASS A3 桌面1440 包裹它的灯箱链接已块级化 [a.yang-lb-item display=block] PASS A3 桌面1440 包裹盒 text-indent 已清零 [text-indent=0px] PASS A3 手机390 右侧不溢出正文块 [right=359.00 ≤ 359.00 (溢出 0.00)] PASS A1 段落首行缩进仍保留(32px / 30px)—— 没把段落自己也弄成不缩进 ``` 反证 **10 / 10 全部抓到**(证明判据有牙齿,不是恒绿): | 注入 | 预期 | 实测 | |---|---|---| | 删掉灯箱链接的 `text-indent:0` | 包裹盒被推歪 | 49/3 ✅ | | 删掉整条灯箱规则(退回 3.2.59) | 溢出复现 | 39/13 ✅ | | 删掉 `img` 自身的 `text-indent:0` | CDP 抓到少一条 | 51/1 ✅ | | 灯箱改回 `inline-block` | 未块级化 | 41/11 ✅ | | **阴性对照**:加一条无关规则 | 不该报红 | 52/0 ✅ | 反证里的两个细节值得记一下(顺手踩到的): - `Z2` 第一版用 `document.styleSheets[].cssRules` 搜选择器,恒红 —— 本项目 CSS 全走 CDN 域名,外链表一律 `SecurityError` 读不到 (实测 12 张表里只有内联 `<style>` 可读)。改用 CDP + md5 双证。 - `Z3` 的过滤条件写成 `p.name && p.value && !p.parsedOk === false` —— `parsedOk` 是 `undefined`,`!undefined === false` 恒为 `false`, 于是**一条属性都留不下**,判据恒红。否定式断言在 `undefined` 上是坑。 ### 已上线 ``` https://yangyq.net/theme-update/update.json {"version":"3.2.60", "download_url":".../kratos_yang-3.2.60.zip", "details_url":".../readme.html", "md5":"6b6c5ff1bdb9be2373801a59d71fdec7"} ``` - zip 与本地字节一致:`6b6c5ff1bdb9be2373801a59d71fdec7`(4824374 字节) - 重复打包 md5 相同(zip 内时间戳固定 1980-01-01) - readme 已并入 3.2.60 节,历史 50 段完整保留(`new.endswith(old)` 为真) - transient 已清,后台「更新」页可立刻看到 3.2.60 ⚠️ **服务器主题目录仍是 3.2.59**(红线:只发 zip,不解包覆盖)。 需要你在后台「外观 → 主题」点一次升级,升级后我再补一条确认。
Author
Owner

用户已验收通过,关单

线上已确认生效(探测到 kratos.min.css?ver=3.2.64、site.css?ver=3.2.64)。

本单修的是「正文图片左缩进导致右侧溢出正文块」——根因是 text-indent 可继承,
只清叶子 img 无效,外层包裹盒(inline-block)也要一起清(pitfalls #464)。

3.2.60 修复、3.2.61 补充 h2/h3 层级,用户已在上线后逐项验收通过。按用户要求关闭。

## 用户已验收通过,关单 线上已确认生效(探测到 `kratos.min.css?ver=3.2.64`、`site.css?ver=3.2.64`)。 本单修的是「正文图片左缩进导致右侧溢出正文块」——根因是 `text-indent` 可继承, 只清叶子 `img` 无效,外层包裹盒(`inline-block`)也要一起清(pitfalls #464)。 3.2.60 修复、3.2.61 补充 h2/h3 层级,用户已在上线后逐项验收通过。按用户要求关闭。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/wordpress-kratos-yang#28