为什么Remix SSR生成的HTML里CSS变量在客户端显示不一致?

东方爱菊 阅读 656

我在用Remix开发SSR应用时发现了个怪事,服务端渲染的HTML里有这样定义的CSS变量:


:root {
  --primary-color: #3498db;
}

但页面加载到客户端后,通过JavaScript获取getComputedStyle发现--primary-color变成了透明色。明明服务端渲染的HTML源码里变量是正常的,这是SSR和CSR的样式上下文不一致吗?

已经试过把CSS放在app/styles.css全局文件里,也确认过网络请求没404,但问题依旧。难道是服务端没正确注入CSS变量?或者需要特殊配置?

我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
开发者德丽
这个问题我之前也踩过坑,说白了就是服务端渲染和客户端渲染的样式加载时机不一致导致的。Remix在SSR阶段确实会把CSS变量注入到HTML里,但客户端的JavaScript执行时,可能因为某些原因覆盖了这些变量。

我当时遇到的情况是,客户端的样式表加载顺序有问题,或者某些动态脚本改写了CSS变量。你可以先检查一下是不是有其他脚本在页面加载后修改了 :root 的样式。比如有些UI库或者第三方插件会偷偷覆盖全局CSS变量。

解决办法有几个方向可以试试。第一种是确保你的全局样式文件在客户端加载时优先级最高,可以通过调整引入顺序来实现。比如在 entry.client.jsx 里,确保样式文件在应用代码之前加载:

import '../styles.css';
import { hydrate } from 'react-dom';
// 其他代码


第二种方法更保险,直接在客户端初始化时强制同步服务端的CSS变量。可以用下面的代码手动把服务端的变量重新应用一遍:

document.addEventListener('DOMContentLoaded', () => {
const serverStyle = document.querySelector('style[data-remix-css]');
if (serverStyle) {
const root = document.documentElement;
const styles = serverStyle.sheet.cssRules;
Array.from(styles).forEach(rule => {
if (rule.selectorText === ':root') {
Object.keys(rule.style).forEach(prop => {
if (prop.startsWith('--')) {
root.style.setProperty(prop, rule.style.getPropertyValue(prop));
}
});
}
});
}
});


这个代码的作用是,在页面加载完成后,从服务端注入的 <style> 标签里提取所有的CSS变量,然后重新应用到客户端的 :root 上。

还有一点需要注意,如果你用了某些CSS-in-JS库,可能会有自己的样式注入机制,这时候需要确认它们和Remix的SSR流程是否兼容。我当时就是因为一个CSS-in-JS库搞了半天才发现问题。

总之核心思路就是确保服务端和客户端的样式上下文一致,要么通过加载顺序控制,要么通过手动同步变量来解决。希望这些建议能帮你搞定这个问题。
点赞 2
2026-02-14 20:04