WordPress作为无头CMS时Next.js单篇博客丢失默认样式问题
核心原因
WordPress作为无头CMS时,REST API返回的内容只是纯HTML结构,不包含WordPress主题自带的样式文件。你看到的WP默认样式(比如段落间距、标题层级、图片排版、列表样式等)都来自WP主题的CSS,这些不会通过API返回,所以直接渲染HTML自然丢失了样式。
具体修复步骤
1. 修正代码中的内容渲染错误
你的代码存在逻辑问题:在map遍历blogData时,渲染内容用了blogData[0]["content"]["rendered"],这会导致所有循环项都渲染第一篇文章的内容。应该改为使用当前遍历项post的内容:
<div className="mt-6" dangerouslySetInnerHTML={{ __html: sanitizeHtml(post.content.rendered), // 将blogData[0]替换为post }} ></div>
2. 引入WordPress基础排版样式
要还原WP的默认内容样式,有两种可行方式:
方式一:提取WP主题的内容样式
打开你的WordPress后台对应主题的style.css文件,提取其中和文章内容相关的样式规则(比如.entry-content下的段落、标题、列表、图片、引用等样式),复制到Next.js项目的全局CSS文件(如globals.css)中。举个WP默认主题的基础内容样式示例:
.entry-content p { margin-bottom: 1.5em; line-height: 1.8; } .entry-content h2 { font-size: 1.8em; margin: 1.5em 0 0.8em; font-weight: 600; } .entry-content ul, .entry-content ol { margin-left: 1.5em; margin-bottom: 1.5em; } .entry-content img { max-width: 100%; height: auto; margin: 1em 0; } .entry-content blockquote { border-left: 4px solid #ccc; padding-left: 1em; margin: 1.5em 0; font-style: italic; }然后给渲染内容的div加上对应的类名:
<div className="mt-6 entry-content" // 添加entry-content类 dangerouslySetInnerHTML={{ __html: sanitizeHtml(post.content.rendered), }} ></div>方式二:引入WP官方内容样式库
在Next.js的布局组件(如layout.tsx)中通过<link>标签引入WordPress官方的内容样式文件:<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@wordpress/style-builds@6.2.0/style.css" />注意:这种方式会引入完整WP样式,可能和项目现有样式冲突,建议按需裁剪。
3. 检查sanitize-html的过滤配置
确认sanitize-html没有过滤WP内容中的类名(比如wp-image-xxx、aligncenter等)。如果你的sanitize配置限制了允许的类名,需要把这些WP相关类加入白名单:
import sanitizeHtml from 'sanitize-html'; export const sanitizeHtml = (html: string) => { return sanitizeHtml(html, { allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img', 'figure', 'figcaption']), allowedAttributes: { ...sanitizeHtml.defaults.allowedAttributes, 'img': ['src', 'alt', 'class', 'width', 'height'], 'div': ['class'], 'p': ['class'] }, allowedClasses: { '*': ['wp-image-*', 'aligncenter', 'alignleft', 'alignright'] } }); };
总结
问题本质是缺少WordPress主题的内容样式,先修正代码中的渲染错误,再通过引入WP基础样式或自定义排版样式还原默认外观,同时确保sanitize-html不过滤必要的类名。
内容的提问来源于stack exchange,提问作者Olaintech

