You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中基于dark类高效切换Prism代码高亮样式的方法

Next.js中结合TailwindCSS与Prism实现高效暗色模式代码样式切换

现状说明

我正在用TailwindCSS和Prism为Next.js应用的MDX文件设置代码样式,已实现暗色模式切换功能——开启时会给<html>标签添加dark类:

亮模式下的HTML标签:

<html class="h-full antialiased"><!-- rest of the html document --></html>

暗模式下的HTML标签:

<html class="h-full antialiased dark"><!-- rest of the html document --></html>

需要为Prism代码块设置分模式的样式:

亮模式(无dark类)样式

pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
  text-shadow: none;
  background: rgba(224, 224, 224, 0.99);
}

.token.comment,
.token.prolog,
.token.cdata {
  color: rgb(152, 159, 177);
}

.token.punctuation {
  color: rgb(153, 76, 195);
}

暗模式(有dark类)样式

pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
  text-shadow: none;
  background: rgba(29, 59, 83, 0.99);
}

.token.comment,
.token.prolog,
.token.cdata {
  color: rgb(99, 119, 119);
}

.token.punctuation {
  color: rgb(199, 146, 234);
}

注:实际样式表包含更多类

问题与尝试过的方法

我想找更高效的实现方式,目前试过两种方案:

  • 给每个样式类手动添加.dark前缀:有效但操作繁琐,示例:
.dark .token.punctuation {
  color: rgb(199, 146, 234);
}
  • 使用嵌套写法:完全无效,示例:
.dark {
  pre[class*="language-"]::selection,
  pre[class*="language-"] ::selection,
  code[class*="language-"]::selection,
  code[class*="language-"] ::selection {
    text-shadow: none;
    background: rgba(29, 59, 83, 0.99);
  }

  .token.comment,
  .token.prolog,
  .token.cdata {
    color: rgb(99, 119, 119);
  }

  .token.punctuation {
    color: rgb(199, 146, 234);
  }
}

当前实现细节

  1. 通过_document.tsx中的脚本切换暗色模式:
import { Head, Html, Main, NextScript } from 'next/document';

const modeScript = `
  const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

  updateMode();
  darkModeMediaQuery.addEventListener('change', updateModeWithoutTransitions);
  window.addEventListener('storage', updateModeWithoutTransitions);

  function updateMode() {
    const isSystemDarkMode = darkModeMediaQuery.matches;
    const isDarkMode =
      window.localStorage.isDarkMode === 'true' ||
      (!('isDarkMode' in window.localStorage) && isSystemDarkMode);

    if (isDarkMode) {
      document.documentElement.classList.add('dark');
    } else {
      document.documentElement.classList.remove('dark');
    }

    if (isDarkMode === isSystemDarkMode) {
      delete window.localStorage.isDarkMode;
    }
  }

  function disableTransitionsTemporarily() {
    document.documentElement.classList.add('[&_*]:!transition-none');
    window.setTimeout(() => {
      document.documentElement.classList.remove('[&_*]:!transition-none');
    }, 0);
  }

  function updateModeWithoutTransitions() {
    disableTransitionsTemporarily();
    updateMode();
  }
`;

export default function Document() {
  return (
    <Html className="h-full antialiased" lang="en">
      <Head>
        <script dangerouslySetInnerHTML={{ __html: modeScript }} />
// ...
    </Html>
  );
}
  1. 在pages/_app.tsx中导入样式:
    globals.css内容:
@tailwind base;
@tailwind components;
@tailwind utilities;
@import './prism.css';

_app.tsx中的导入:

// in _app.tsx
import '~/styles/globals.css';

我还考虑过通过TypeScript导入对应CSS文件,但也未能实现。


内容的提问来源于stack exchange,提问作者J. Hesters

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:40:33