DedeCMS文章页图片去重响应式方案47步:5维度+8类避坑实战

织梦 DedeCMS 编辑器上传图片自动塞 width 与 height 属性导致移动端撑破屏幕的根因,给出修改 arc.archives.class.php 的三行 preg_replace 安全版本(用字符类避免正则贪婪问题)、DOMDocument 替代方案性能与正确性对比、配套响应式 CSS 兜底、老文章静态页批量更新与 CDN 缓存清理三步走。

张文保 更新 25 分钟阅读 1,507 阅读
本文目录
  1. 为什么织梦会自动加 width 和 height
  2. FCKEditor 的历史背景
  3. 移动优先时代的冲突点
  4. 处理原则
  5. 修改 arc.archives.class.php 的核心代码
  6. 定位修改点
  7. 三行 preg_replace 完整版
  8. 正则贪婪匹配的坑
  9. 修改后必须重新生成静态页
  10. 用 DOMDocument 替代正则:更稳健但更慢
  11. DOMDocument 改写方案
  12. DOMDocument 的优劣
  13. 适用场景
  14. CSS 兜底:响应式样式必不可少
  15. 主题 CSS 加响应式规则
  16. 关键属性解释
  17. aspect-ratio 进阶用法
  18. 新文章正常但老文章还是变形怎么办
  19. 原因:静态页已生成
  20. 三种修复方法
  21. 三种方法的组合
  22. 现代化升级:从去 width/height 到完整 srcset
  23. 响应式图片的现代写法
  24. WebP / AVIF 格式
  25. 织梦集成现代图片管线的难点
  26. 常见问题解答
  27. 去掉 width 和 height 属性后会不会让 CLS 变差
  28. 原版只删 style 不删 width/height 属性的代码到底能不能用
  29. 改完代码生成静态页后部分图片连图都没有了
  30. 能不能完全交给前端 JS 去掉 width/height 不动 PHP
  31. 修改 include 目录下的核心文件升级会被覆盖怎么办
  32. 动态页面(不生成静态)需要这样改吗
  33. 编辑器里能不能直接禁止上传时加宽高
  34. SEO 角度图片必须有 alt 属性吗
  35. PHP 7.4 升级到 PHP 8 后 stripImgSize 还能用吗
  36. 总结:从去宽高到现代图片管线的演进路径
  37. 改完后的验收清单

织梦 DedeCMS 后台编辑器(FCK / CKEditor 简化版)在用户上传图片时会自动给 <img> 标签塞进 width 与 height 两个 HTML 属性,外加一段 style="width:xxx;height:xxx" 的内联样式。这套设计在 2008 年的 PC-only 时代是合理的——固定尺寸能让浏览器渲染时预留空间避免布局抖动。但在 2024 年的移动优先环境里,这种写法直接和响应式 CSS 冲突:HTML 的 width 属性优先级比 CSS 的 max-width 高,导致图片硬撑出屏幕外形成横向滚动条。本文按"原因 → 改源码 → CSS 兜底 → 历史文章修复 → 现代 srcset 升级 → 性能与 CLS 平衡"六个层面把这个问题完整解决,并补上 DOMDocument 替代正则、CDN 缓存清理、PHP 7-8 兼容、备份恢复等运维细节。

为什么织梦会自动加 width 和 height

FCKEditor 的历史背景

织梦 DedeCMS 5.6 / 5.7 时代默认使用 FCKEditor(后改名 CKEditor)作为富文本编辑器。FCKEditor 在 2007 年左右设计,那时候网页布局还是固定像素栅格、Flash 是主流交互方式、移动端 Web 几乎不存在。编辑器在插入图片时会读本地文件的真实像素尺寸,把它写入 widthheight 两个 HTML 属性,再加一段 style 内联样式——这是当时的"良好实践",能让浏览器预先知道图片占多少空间提前计算布局。

移动优先时代的冲突点

问题在 2014 年 Google 推 mobile-first indexing 后开始严重:

  • 响应式被破坏:现代主题用 max-width: 100%; height: auto 让图片自适应,但 HTML 的 width 属性优先级比 CSS 高,固定 800px 的图片会撑破 375px 的手机屏幕。
  • 横向滚动条出现:图片溢出导致整个文章页可以左右滚动,用户体验崩塌。
  • CLS 指标错位:HTML 固定尺寸 + CSS 等比缩放冲突时,浏览器对最终高度的计算可能滞后,触发 Layout Shift。
  • 编辑器误差被放大:很多客户上传的是设计师切好的高清大图,宽度动辄 1920px,硬塞到手机屏上必然炸。

处理原则

正确思路:HTML 上不留固定尺寸,让 CSS 完全控制布局。这要做两件事:

  1. 在 PHP 层面把现有内容里的 width / height 属性和 style 内联样式去掉。
  2. 在 CSS 层面给图片加响应式样式作为兜底。

修改 arc.archives.class.php 的核心代码

定位修改点

打开 /include/arc.archives.class.php(DedeCMS 5.7 路径),用编辑器的全文搜索找到这段代码:

// 设置全局环境变量
$this->Fields['typename'] = $this->TypeLink->TypeInfos['typename'];
@SetSysEnv($this->Fields['typeid'], $this->Fields['typename'], $this->Fields['id'], $this->Fields['title'], 'archives');

这两行通常出现在 GetArcParAddTable 方法里,作用是把当前文章的元数据写入全局环境。我们要在它后面紧接着插入正文 HTML 改造代码,让所有调用此类的位置都自动应用改造。

三行 preg_replace 完整版

// 去掉正文里 img 标签的 width / height 属性和 style 宽度
$this->Fields['body'] = preg_replace('/style="width\s*:\s*[^"]*"/i', '', $this->Fields['body']);
$this->Fields['body'] = preg_replace('/(<img[^>]*?)\s+width=(["\']?)[0-9]+\2/i', '$1', $this->Fields['body']);
$this->Fields['body'] = preg_replace('/(<img[^>]*?)\s+height=(["\']?)[0-9]+\2/i', '$1', $this->Fields['body']);

三行各自的作用:

  1. 第一行:去掉 style="width:600px" 这种内联样式(精确匹配,不依赖回溯避免贪婪问题)。
  2. 第二行:去掉 <img ... width="600"> 这种 HTML 属性。
  3. 第三行:去掉 <img ... height="400"> 这种 HTML 属性。

正则贪婪匹配的坑

网上很多老教程给的版本第一行写的是 preg_replace('/style="width:(.*)"/', ...)——用了贪婪 (.*)。这个写法在下面这种正文里会出问题:

<p style="width:100%">这是一段话</p>
<img style="width:600px" src="a.jpg"/>
<p>另一段</p>

贪婪正则会从第一个 style="width: 一路吃到最后一个 ",把中间所有 HTML 全删掉。整篇文章被吞。修复方案有两个:

  • (.*) 改成 (.*?) 加问号变成非贪婪。
  • 更稳妥的写法是用字符类 [^"]* 明确"不包含双引号的任意字符"——这样根本不需要回溯,性能也更好。

我现在线上用的是字符类版本,零回溯零踩坑。

修改后必须重新生成静态页

这是新手最容易忽略的一步。织梦默认把每篇文章生成静态 HTML 文件存在 /a/ 目录下,老文章的静态页是在你修改代码之前生成的,里面已经写死了 width/height 属性,新代码不会主动重生成它们。修完代码必须:

  1. 登录后台 → 生成 → 更新文档 HTML → 选择全部栏目 → 开始更新。
  2. 文章数量大(比如几千篇)时这一步会跑很久,建议在低流量时段执行。
  3. 大批量更新可能触发 PHP 脚本超时,调高 max_execution_time 或者分栏目分批跑。

用 DOMDocument 替代正则:更稳健但更慢

DOMDocument 改写方案

如果服务器是 PHP 7.0 以上且你对正则不放心,可以用 DOMDocument 解析正文:

function stripImgSize($html) {
    if (empty($html)) return $html;
    $dom = new DOMDocument();
    @$dom->loadHTML('<?xml encoding="utf-8" ?>' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    foreach ($dom->getElementsByTagName('img') as $img) {
        $img->removeAttribute('width');
        $img->removeAttribute('height');
        $style = $img->getAttribute('style');
        if ($style) {
            $style = preg_replace('/(width|height)\s*:\s*[^;]+;?/i', '', $style);
            if (trim($style) === '') {
                $img->removeAttribute('style');
            } else {
                $img->setAttribute('style', trim($style));
            }
        }
    }
    return $dom->saveHTML();
}

$this->Fields['body'] = stripImgSize($this->Fields['body']);

DOMDocument 的优劣

对比项正则版本DOMDocument 版本
性能快(线性扫描)慢 2-3 倍(建树)
正确性边界条件多解析器级别可靠
HTML5 支持libxml2 支持但不完整
嵌套属性容易出错正确处理
HTML 实体不解码自动解码
自闭合标签需要小心正确识别
编码问题需手动处理需要 xml encoding 声明

适用场景

  • 启用了静态页缓存的站点:DOMDocument 多 200ms 也无所谓,命中缓存后 0ms,选稳定性。
  • 裸跑没静态化的高流量站点:建议正则版本,性能优先。
  • 正文里经常出现奇怪的 HTML(嵌套属性、未闭合标签):DOMDocument 健壮性更高。
  • 开发者团队对正则不熟悉:DOMDocument 维护起来心智负担小。

CSS 兜底:响应式样式必不可少

主题 CSS 加响应式规则

光去掉 HTML 属性还不够,CSS 必须配合:

.article-content img,
.entry-content img,
.post-content img {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 1em auto;
    border-radius: 4px;
}

@media (max-width: 768px) {
    .article-content img {
        margin: 0.6em auto;
    }
}

关键属性解释

  • max-width: 100%:图片不超过容器宽度。
  • height: auto:宽度变化时自动等比缩放高度,避免变形。
  • display: block:图片单独成块,配合 margin auto 居中。
  • margin: auto:水平居中。比 text-align: center 在父元素上更可靠(text-align 只对 inline 元素生效,display block 后失效)。
  • border-radius: 4px:轻微圆角,视觉上更温和。

aspect-ratio 进阶用法

2021 年 CSS 新增 aspect-ratio 属性,可以让浏览器在图片加载前就预留正确高度,消除 CLS:

.article-content img {
    aspect-ratio: attr(width) / attr(height);
    max-width: 100%;
    height: auto;
}

但 attr() 在 aspect-ratio 上的支持还不普及,更稳妥的写法是 PHP 渲染时根据图片真实尺寸生成内联 CSS 变量:

<img src="a.jpg" style="aspect-ratio: 16/9;" alt="...">

这样既能保持响应式,又能预留布局空间——既不固定像素也不丢失尺寸信息。

新文章正常但老文章还是变形怎么办

原因:静态页已生成

这是改完代码后最常见的问题。织梦默认把动态文章生成静态 HTML 文件存在 /a/<栏目>/<ID>.html,老文章的静态页在修改代码之前就已经生成了,里面写死了 width/height 属性。代码改完后不主动重生成,老页面不会自动应用新逻辑。

三种修复方法

方法 1:后台手动批量更新

登录后台 → 生成 → 更新文档 HTML → 选择全部栏目 → 开始更新。

文章多的话会跑很久(几千篇大概 30-60 分钟)。建议设置 PHP max_execution_time = 0(仅命令行有效)或者分栏目跑。

方法 2:直接在数据库跑 SQL 替换

MySQL 8 以上支持 REGEXP_REPLACE

UPDATE dede_addonarticle
SET body = REGEXP_REPLACE(body, ' width=("[0-9]+"|[0-9]+)', '')
WHERE body REGEXP ' width=';

UPDATE dede_addonarticle
SET body = REGEXP_REPLACE(body, ' height=("[0-9]+"|[0-9]+)', '')
WHERE body REGEXP ' height=';

UPDATE dede_addonarticle
SET body = REGEXP_REPLACE(body, 'style="width\\s*:\\s*[^"]*"', '')
WHERE body LIKE '%style="width%';

MySQL 5.7 没有 REGEXP_REPLACE,要写 PHP 脚本读出来 preg_replace 再写回去。务必先 mysqldump 备份。

方法 3:CDN 缓存清理

如果用了 CDN(Cloudflare、阿里云 CDN、腾讯云 CDN 等),改完源站要清 CDN 缓存:

  • Cloudflare:Caching → Purge Everything 或 Custom Purge 指定路径。
  • 阿里云 CDN:刷新缓存 → URL 刷新 / 目录刷新。
  • 腾讯云 CDN:缓存配置 → 缓存刷新。

三种方法的组合

实操时通常三种结合用:先 SQL 把数据库里的属性清掉,再后台批量更新静态页,最后清 CDN 缓存。三步走完才算彻底搞定,否则总有一层缓存还在持有旧版本。

现代化升级:从去 width/height 到完整 srcset

响应式图片的现代写法

2024 年的最佳实践不只是去掉固定尺寸,而是用 srcset + sizes 给浏览器多个分辨率选择:

<img
  src="image-800.jpg"
  srcset="image-400.jpg 400w, image-800.jpg 800w, image-1600.jpg 1600w"
  sizes="(max-width: 768px) 100vw, 800px"
  loading="lazy"
  alt="...">

这样浏览器会根据视口宽度和 DPR 自动选最合适的图片,节省流量、保持清晰。

WebP / AVIF 格式

<picture> 给现代浏览器优先 WebP,老浏览器回退 JPEG:

<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="..." loading="lazy">
</picture>

WebP 比 JPEG 平均小 25-30%,AVIF 比 JPEG 小 50%。同样视觉质量下大幅减少加载时间。

织梦集成现代图片管线的难点

织梦原生不支持 srcset 和 picture。要集成现代化方案:

  • 修改后台上传脚本,生成多种分辨率的副本。
  • 修改 arc.archives.class.php,在输出正文时把 <img src="..."> 重写为 <picture>...</picture>
  • 或者用 CDN 的图片处理服务(Cloudflare Image Resizing、阿里云 OSS 图片处理等)做边缘转换,源站只存一张原图。

常见问题解答

去掉 width 和 height 属性后会不会让 CLS 变差

会有一定影响但实测下来不严重。CLS 主要看图片加载完成前后的布局变化。max-width: 100%height: auto,再加服务端给图片包一层 aspect-ratio 容器或用 loading="lazy",可以把视觉跳动控制在可接受范围。如果对 Core Web Vitals 极度敏感,可以让 PHP 渲染时根据真实图片尺寸生成 aspect-ratio CSS 变量,这样既能保持响应式又能预留布局空间。

原版只删 style 不删 width/height 属性的代码到底能不能用

能用但只解决了一半问题。织梦不同版本的 FCK/CKEditor 在插入图片时不一定都加 style 内联样式,有些版本只加 HTML 属性。所以单行替换在部分站点上看似没效果。完整三行版本才能覆盖所有情况不会漏。建议直接用三行版本一劳永逸。

改完代码生成静态页后部分图片连图都没有了

大概率是正则贪婪匹配吃掉了图片的 src。检查代码是不是用了 (.*) 而不是 (.*?),或者按上文给的精确字符类版本重写。务必在测试站验证完再推到生产。如果已经在生产炸了,从备份恢复 dede_addonarticle 表即可。

能不能完全交给前端 JS 去掉 width/height 不动 PHP

技术上可以,写一段 jQuery:document ready 后 $('.article-content img').removeAttr('width').removeAttr('height')。但不推荐,原因有两个:第一 JS 执行前那一瞬间用户已经看到了变形的图片体验不好;第二搜索引擎抓取的是原始 HTML 里面还是带固定尺寸,对移动友好度评分有影响。从根上在 PHP 输出阶段处理才是正解。

修改 include 目录下的核心文件升级会被覆盖怎么办

织梦官方很久没主版本更新,升级风险其实不大。但如果要做安全补丁升级,建议把 stripImgSize 这种自定义函数封装到一个独立文件里(如 /include/custom_helpers.inc.php),在 arc.archives.class.php 里 require_once 这个文件然后调用函数。这样下次升级 arc.archives.class.php 时只要重新加一行 require 和一行调用即可,不会丢失改动。

动态页面(不生成静态)需要这样改吗

需要而且更直接。动态页面每次访问都跑 arc.archives.class.phpGetArc,所以改完源码立刻全站生效不需要批量更新。性能开销在每次请求多 0.5-2ms(取决于正文长度)。如果用静态页缓存或反向代理缓存,开销可以忽略。

编辑器里能不能直接禁止上传时加宽高

可以但需要改编辑器配置。织梦 5.7 的 FCKEditor 在 /include/FCKeditor/fckeditor.js/include/ckeditor/config.js 里有 image plugin 配置,找到生成 img 标签的代码删除 width / height 属性赋值即可。但这会让"对话框里的尺寸预览"功能失效——用户看不到图片有多大。权衡是否值得,看用户群体技术水平。

SEO 角度图片必须有 alt 属性吗

必须有且必须填实质内容。alt 属性是搜索引擎理解图片内容的唯一文本信号,缺失或填空字符串会失去图片搜索的所有流量入口。FCK 编辑器默认有 alt 输入框但默认不填。建议改造编辑器或写后端 hook 强制 alt 不能为空(实在不知道写什么用文章标题兜底)。

PHP 7.4 升级到 PHP 8 后 stripImgSize 还能用吗

能用但要注意两点:(1) PHP 8 把 libxml_disable_entity_loader 标记为 deprecated 但 DOMDocument 默认安全;(2) preg_replace 的回调写法 preg_replace_callback 在 PHP 8 行为不变。本文给的所有正则代码在 PHP 5.4 到 PHP 8.3 上都验证过可用。如果你站点要升 PHP 版本,先用 PHPUnit 写几条针对性的测试覆盖各种 img 标签变体,升级后跑一遍即可。

总结:从去宽高到现代图片管线的演进路径

"织梦 DedeCMS 去掉 img 宽高"这个看起来一行 preg_replace 的小事,背后是 16 年间 Web 图片处理的演进史:

  1. 2008 PC-only 时代:固定宽高是 best practice。
  2. 2014 移动优先:固定宽高变成 anti-pattern,需要响应式 CSS 兜底。
  3. 2018 Core Web Vitals:完全去掉宽高又会让 CLS 变差,需要 aspect-ratio。
  4. 2020 srcset 普及:单图变多图,浏览器自动选择最佳分辨率。
  5. 2024 AVIF/WebP:格式升级,文件减半视觉无损。

如果你只是接手一个老织梦站做应急修复,本文方案 A(三行 preg_replace + CSS max-width 100%)足够用。如果是要长期维护甚至做 SEO 优化,建议直接做到第 4-5 步——这才是 2024 年企业站该有的样子。

改完后的验收清单

把这 8 项过一遍才算彻底搞定:

  1. 桌面端测试:随机抽 5 篇文章在 Chrome、Edge、Firefox 上看一遍,图片不变形、不溢出。
  2. 移动端测试:用 iPhone Safari、Android Chrome、微信内置浏览器各看 3 篇,没有横向滚动条。
  3. F12 检查 HTML:在文章页 F12 → Elements 面板,搜索 <img,确认没有任何 img 标签带 width 或 height 属性,没有 style 内联宽度。
  4. F12 检查 CSS:选中任一图片,看 Computed 面板里 max-width 是 100% 不是 none。
  5. 响应式测试:DevTools 切换到 iPhone 12 Pro 模拟器(390×844),图片应该等比缩放。
  6. CLS 验证:跑 Lighthouse 看 Cumulative Layout Shift 分数应小于 0.1。
  7. Search Console 移动友好度:等 7-14 天看 Search Console → 体验 → 移动设备易用性,"内容比屏幕宽"错误应清零。
  8. SEO 抽检:用 Screaming Frog 抓 100 篇文章,导出 image 报告,确认所有 img 都有 alt 属性都没有 width/height。

这 8 项跑完图片改造才算闭环。最常见的疏漏是第 7 项——很多站长改完 1 天就来看 Search Console 没动静以为没生效,实际上 Google 重新抓取并更新指标至少要 7 天。耐心点,给 2 周观察期再做下一轮调整。

FAQPage + Article AI 引用友好版

TL;DR · 60–80 字摘要 · 适用 ChatGPT / Perplexity / Gemini / 文心 引用

织梦 DedeCMS 编辑器上传图片自动塞 width 与 height 属性导致移动端撑破屏幕的根因,给出修改 arc.archives.class.php 的三行 preg_replace 安全版本(用字符类避免正则贪婪问题)、DOMDocument 替代方案性能与正确性对比、配套响应式 CSS 兜底、老文章静态页批量更新与 CDN 缓存清理三步走。

关键实体 · Key Entities

  • DedeCMS手机站
  • DedeCMS批量处理
  • 织梦图片
  • 技术SEO
  • DedeCMS
  • 网页编辑器
  • 织梦CMS教程

引用元数据 · Citation Metadata

title:       DedeCMS文章页图片去重响应式方案47步:5维度+8类避坑实战
author:      张文保 (Paul Zhang) — PatPat SEO 经理
url:         https://zhangwenbao.com/dedecms-removes-height-width.html
published:   2021-02-10
modified:    2026-05-16
source-type: First-hand expert commentary
language:    zh-CN
license:     CC BY-NC-SA 4.0 (要求保留原文链接与作者归属)
分享到
标签
版权声明

本文标题:《DedeCMS文章页图片去重响应式方案47步:5维度+8类避坑实战》

本文链接:https://zhangwenbao.com/dedecms-removes-height-width.html

版权声明:本文原创,转载请注明出处和链接。许可协议: CC BY-NC-SA 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交