正在加载文档...
文档内容较大,正在处理中,请稍候
正在加载文档...
文档内容较大,正在处理中,请稍候
项目已配置 Tailwind CSS,依赖已包含在 package.json 中:
{
"dependencies": {
"tailwindcss": "^3.4.19"
},
"devDependencies": {
"postcss": "^8.5.6",
"autoprefixer": "^10.4.20"
}
}如果需要在其他项目中安装,执行:
cd apps/doc-next-ts
pnpm add -D tailwindcss postcss autoprefixer项目配置文件位置:apps/doc-next-ts/tailwind.config.ts
/** @type {import('tailwindcss').Config} */
const config = {
darkMode: "class", // 使用 class 策略控制暗色模式
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: {
background: "var(--background)",
foreground: "var(--foreground)",
},
fontFamily: {
sans: ["var(--font-geist-sans)", "Arial", "Helvetica", "sans-serif"],
mono: ["var(--font-geist-mono)", "monospace"],
},
},
},
plugins: [],
};
export default config;配置说明:
dark class 来控制暗色模式PostCSS 配置文件:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};全局样式文件:src/styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
/* CSS 变量定义 */
:root {
--background: #ffffff;
--foreground: #171717;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
/* 使用 @layer base 定义基础样式 */
@layer base {
* {
@apply box-border p-0 m-0;
}
html,
body {
@apply max-w-full overflow-x-hidden;
}
body {
@apply bg-background text-foreground;
font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif;
}
a {
@apply text-inherit no-underline;
}
}
/* 使用 @layer utilities 定义自定义工具类 */
@layer utilities {
@keyframes progress {
0% {
width: 0%;
transform: translateX(0);
}
50% {
width: 70%;
transform: translateX(0);
}
100% {
width: 100%;
transform: translateX(100%);
}
}
.animate-progress {
animation: progress 1.5s ease-in-out infinite;
}
}项目使用 zinc 和 emerald 作为主要配色:
用于文本、背景、边框等基础元素:
// 文本颜色
className = "text-zinc-900 dark:text-white"; // 主文本
className = "text-zinc-600 dark:text-zinc-400"; // 次要文本
className = "text-zinc-500 dark:text-zinc-500"; // 辅助文本
// 背景颜色
className = "bg-white dark:bg-zinc-900"; // 主背景
className = "bg-zinc-100 dark:bg-zinc-800"; // 次要背景
className = "bg-zinc-50 dark:bg-zinc-900/20"; // 浅色背景
// 边框颜色
className = "border-zinc-200 dark:border-zinc-700";
className = "border-zinc-900/10 dark:border-white/10";用于链接、按钮、激活状态等强调元素:
// 链接颜色
className = "text-emerald-600 hover:text-emerald-500 dark:text-emerald-400";
// 按钮颜色
className = "bg-emerald-600 hover:bg-emerald-700 dark:bg-emerald-500";
// 激活状态
className = "bg-emerald-50 text-emerald-600 dark:bg-emerald-900/20 dark:text-emerald-400";项目使用 class 策略,通过添加 dark class 到 <html> 或 <body> 元素来启用:
// 在 layout.tsx 中
<html lang="en" className="h-full">
<body className="dark:bg-zinc-900">{/* ... */}</body>
</html>// 基础用法
<div className="bg-white dark:bg-zinc-900">
<p className="text-zinc-900 dark:text-white">文本内容</p>
</div>
// 透明度
<div className="bg-white/90 dark:bg-zinc-900/90">
<div className="bg-black/20 dark:bg-white/20">
// 边框
<div className="border-zinc-200 dark:border-zinc-700">项目使用 ThemeContext 管理主题:
import { useTheme } from "@/hooks/useTheme";
function Component() {
const { theme, toggleTheme } = useTheme();
return <button onClick={toggleTheme}>{theme === "light" ? "切换到暗色" : "切换到亮色"}</button>;
}// 固定宽度
className = "w-4"; // 1rem (16px)
className = "w-8"; // 2rem (32px)
className = "w-12"; // 3rem (48px)
className = "w-16"; // 4rem (64px)
className = "w-24"; // 6rem (96px)
className = "w-32"; // 8rem (128px)
className = "w-48"; // 12rem (192px)
className = "w-64"; // 16rem (256px)
className = "w-72"; // 18rem (288px) - Sidebar 宽度
className = "w-80"; // 20rem (320px) - Sidebar 宽度(xl)
// 百分比宽度
className = "w-full"; // 100%
className = "w-1/2"; // 50%
className = "w-1/3"; // 33.333%
className = "w-2/3"; // 66.666%
className = "w-1/4"; // 25%
className = "w-3/4"; // 75%
// 自动宽度
className = "w-auto"; // auto
className = "w-fit"; // fit-content
className = "w-max"; // max-content
className = "w-min"; // min-content
// 响应式宽度
className = "w-full md:w-1/2 lg:w-1/3";// 固定高度
className = "h-4"; // 1rem (16px)
className = "h-8"; // 2rem (32px)
className = "h-12"; // 3rem (48px)
className = "h-14"; // 3.5rem (56px) - Header 高度
className = "h-16"; // 4rem (64px)
className = "h-24"; // 6rem (96px)
className = "h-32"; // 8rem (128px)
className = "h-48"; // 12rem (192px)
className = "h-64"; // 16rem (256px)
// 百分比高度
className = "h-full"; // 100%
className = "h-screen"; // 100vh
className = "h-auto"; // auto
className = "h-fit"; // fit-content
// 最小/最大高度
className = "min-h-screen"; // min-height: 100vh
className = "min-h-full"; // min-height: 100%
className = "max-h-screen"; // max-height: 100vh
className = "max-h-96"; // max-height: 24rem// 统一内边距
className = "p-0"; // 0
className = "p-1"; // 0.25rem (4px)
className = "p-2"; // 0.5rem (8px)
className = "p-3"; // 0.75rem (12px)
className = "p-4"; // 1rem (16px)
className = "p-6"; // 1.5rem (24px)
className = "p-8"; // 2rem (32px)
className = "p-10"; // 2.5rem (40px)
className = "p-12"; // 3rem (48px)
// 方向内边距
className = "px-4"; // padding-left & padding-right: 1rem
className = "py-2"; // padding-top & padding-bottom: 0.5rem
className = "pt-4"; // padding-top: 1rem
className = "pr-4"; // padding-right: 1rem
className = "pb-4"; // padding-bottom: 1rem
className = "pl-4"; // padding-left: 1rem
// 响应式内边距
className = "p-4 sm:p-6 lg:p-8";
className = "px-4 sm:px-6 lg:px-8";// 统一外边距
className = "m-0"; // 0
className = "m-1"; // 0.25rem (4px)
className = "m-2"; // 0.5rem (8px)
className = "m-4"; // 1rem (16px)
className = "m-6"; // 1.5rem (24px)
className = "m-8"; // 2rem (32px)
className = "m-auto"; // auto (居中)
// 方向外边距
className = "mx-auto"; // margin-left & margin-right: auto (水平居中)
className = "my-4"; // margin-top & margin-bottom: 1rem
className = "mt-4"; // margin-top: 1rem
className = "mr-4"; // margin-right: 1rem
className = "mb-4"; // margin-bottom: 1rem
className = "ml-4"; // margin-left: 1rem
// 负边距
className = "-m-4"; // -1rem
className = "-mt-4"; // margin-top: -1rem// Flexbox/Grid 间距
className = "gap-0"; // 0
className = "gap-1"; // 0.25rem (4px)
className = "gap-2"; // 0.5rem (8px)
className = "gap-4"; // 1rem (16px)
className = "gap-6"; // 1.5rem (24px)
className = "gap-8"; // 2rem (32px)
// 方向间距
className = "gap-x-4"; // column-gap: 1rem
className = "gap-y-2"; // row-gap: 0.5rem// 字体大小
className = "text-xs"; // 0.75rem (12px)
className = "text-sm"; // 0.875rem (14px)
className = "text-base"; // 1rem (16px)
className = "text-lg"; // 1.125rem (18px)
className = "text-xl"; // 1.25rem (20px)
className = "text-2xl"; // 1.5rem (24px)
className = "text-3xl"; // 1.875rem (30px)
className = "text-4xl"; // 2.25rem (36px)
className = "text-5xl"; // 3rem (48px)
className = "text-6xl"; // 3.75rem (60px)
// 响应式字体大小
className = "text-sm sm:text-base md:text-lg lg:text-xl";className = "font-thin"; // 100
className = "font-extralight"; // 200
className = "font-light"; // 300
className = "font-normal"; // 400
className = "font-medium"; // 500
className = "font-semibold"; // 600
className = "font-bold"; // 700
className = "font-extrabold"; // 800
className = "font-black"; // 900className = "leading-none"; // 1
className = "leading-tight"; // 1.25
className = "leading-snug"; // 1.375
className = "leading-normal"; // 1.5
className = "leading-relaxed"; // 1.625
className = "leading-loose"; // 2
className = "leading-6"; // 1.5rem (24px)
className = "leading-7"; // 1.75rem (28px)
className = "leading-8"; // 2rem (32px)// Zinc 色系(中性色)
className = "text-zinc-50"; // 最浅
className = "text-zinc-100";
className = "text-zinc-200";
className = "text-zinc-300";
className = "text-zinc-400"; // 次要文本
className = "text-zinc-500"; // 辅助文本
className = "text-zinc-600"; // 次要文本
className = "text-zinc-700";
className = "text-zinc-800";
className = "text-zinc-900"; // 主文本
// Emerald 色系(强调色)
className = "text-emerald-50";
className = "text-emerald-100";
className = "text-emerald-200";
className = "text-emerald-300";
className = "text-emerald-400"; // 暗色模式链接
className = "text-emerald-500";
className = "text-emerald-600"; // 亮色模式链接
className = "text-emerald-700";
className = "text-emerald-800";
className = "text-emerald-900";
// 其他常用颜色
className = "text-white";
className = "text-black";
className = "text-transparent";
className = "text-current"; // 继承父元素颜色// Zinc 色系
className = "bg-zinc-50"; // 浅色背景
className = "bg-zinc-100";
className = "bg-zinc-200";
className = "bg-white"; // 主背景
className = "bg-zinc-800"; // 暗色次要背景
className = "bg-zinc-900"; // 暗色主背景
// Emerald 色系
className = "bg-emerald-50"; // 激活状态背景
className = "bg-emerald-100";
className = "bg-emerald-500"; // 暗色模式按钮
className = "bg-emerald-600"; // 亮色模式按钮
className = "bg-emerald-700"; // hover 状态
// 透明度
className = "bg-white/90"; // 90% 不透明度
className = "bg-black/20"; // 20% 不透明度
className = "bg-zinc-900/20"; // 暗色模式浅色背景
className = "bg-emerald-900/20"; // 激活状态(暗色模式)className = "border-zinc-200"; // 亮色模式边框
className = "border-zinc-700"; // 暗色模式边框
className = "border-zinc-900/10"; // 10% 不透明度
className = "border-white/10"; // 暗色模式边框
className = "border-emerald-500"; // 强调边框
className = "border-transparent"; // 透明边框// 边框宽度
className = "border"; // 1px
className = "border-0"; // 0
className = "border-2"; // 2px
className = "border-4"; // 4px
className = "border-8"; // 8px
// 方向边框
className = "border-t"; // border-top: 1px
className = "border-r"; // border-right: 1px
className = "border-b"; // border-bottom: 1px
className = "border-l"; // border-left: 1px
className = "border-l-4"; // border-left: 4px (激活状态)
// 边框圆角
className = "rounded-none"; // 0
className = "rounded-sm"; // 0.125rem (2px)
className = "rounded"; // 0.25rem (4px)
className = "rounded-md"; // 0.375rem (6px)
className = "rounded-lg"; // 0.5rem (8px)
className = "rounded-xl"; // 0.75rem (12px)
className = "rounded-2xl"; // 1rem (16px)
className = "rounded-full"; // 9999px (圆形)
className = "rounded-t-lg"; // 只圆角顶部
className = "rounded-b-lg"; // 只圆角底部className = "shadow-sm"; // 小阴影
className = "shadow"; // 默认阴影
className = "shadow-md"; // 中等阴影
className = "shadow-lg"; // 大阴影
className = "shadow-xl"; // 超大阴影
className = "shadow-2xl"; // 2xl 阴影
className = "shadow-none"; // 无阴影
className = "shadow-inner"; // 内阴影
// hover 阴影
className = "hover:shadow-md";
className = "hover:shadow-lg";// 移动端优先
<div className="text-sm sm:text-base md:text-lg lg:text-xl">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">{/* ... */}</div>
</div><button
className="
bg-emerald-600
hover:bg-emerald-700
focus-visible:outline
focus-visible:outline-2
focus-visible:outline-offset-2
focus-visible:outline-emerald-600
dark:bg-emerald-500
dark:hover:bg-emerald-600
"
>
按钮
</button><div
className="
transition-colors
hover:bg-zinc-100
dark:hover:bg-zinc-800
"
>
内容
</div>// Header 固定定位
<header className="fixed inset-x-0 top-0 z-50">
{/* ... */}
</header>
// Sidebar 固定定位
<aside className="fixed inset-y-0 left-0 z-40">
{/* ... */}
</aside>// 水平居中
<div className="flex items-center justify-center">
// 垂直居中
<div className="flex items-center">
// 两端对齐
<div className="flex items-center justify-between">
// 响应式 Flex
<div className="flex flex-col sm:flex-row">// 响应式网格
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">{/* ... */}</div>用于定义基础样式,重置默认样式:
@layer base {
* {
@apply box-border p-0 m-0;
}
a {
@apply text-inherit no-underline;
}
}用于定义可复用的组件样式:
@layer components {
.btn-primary {
@apply px-6 py-3 bg-emerald-600 text-white rounded-lg
hover:bg-emerald-700 transition-colors;
}
}用于定义自定义工具类:
@layer utilities {
.animate-progress {
animation: progress 1.5s ease-in-out infinite;
}
}使用多行格式提高可读性:
// ✅ 推荐
<button className="
inline-flex
items-center
gap-2
rounded-lg
bg-emerald-600
px-6
py-3
text-sm
font-semibold
text-white
shadow-sm
hover:bg-emerald-700
">
按钮
</button>
// ❌ 不推荐(单行过长)
<button className="inline-flex items-center gap-2 rounded-lg bg-emerald-600 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:bg-emerald-700">使用模板字符串或条件表达式:
// 方式一:模板字符串
className={`block rounded-md px-3 py-2 ${
active
? "bg-emerald-50 text-emerald-600"
: "text-zinc-700 hover:bg-zinc-100"
}`}
// 方式二:使用 clsx 或 classnames(可选)
import clsx from "clsx";
className={clsx(
"block rounded-md px-3 py-2",
active && "bg-emerald-50 text-emerald-600",
!active && "text-zinc-700 hover:bg-zinc-100"
)}项目使用的断点:
sm: 640pxmd: 768pxlg: 1024pxxl: 1280px2xl: 1536px// 移动端隐藏,桌面端显示
<div className="hidden lg:block">
// 桌面端隐藏,移动端显示
<div className="lg:hidden">始终为暗色模式提供对应的样式:
// ✅ 推荐
<div className="bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white">
// ❌ 不推荐(缺少暗色模式样式)
<div className="bg-white text-zinc-900">Next.js 16 默认支持热更新!
--turbopack 标志时,HMR 已自动启用启动开发服务器:
pnpm run dev修改任意组件文件(如 src/app/page.tsx)
保存文件后,浏览器会自动更新,无需刷新
package.json 中配置A: 需要重启开发服务器,Tailwind 配置在启动时加载。
A: 在 tailwind.config.ts 的 theme.extend.colors 中添加:
theme: {
extend: {
colors: {
custom: '#your-color',
},
},
}A: 在 globals.css 中定义变量,然后在配置中引用:
:root {
--custom-color: #your-color;
}colors: {
custom: "var(--custom-color)",
}A: 在 tailwind.config.ts 中使用 corePlugins:
corePlugins: {
preflight: false, // 禁用基础样式重置
}一个个查太费劲了