Remix CSS模块 #
一、CSS模块概述 #
CSS Modules 提供了作用域隔离的CSS,避免样式冲突。Remix 原生支持 CSS Modules。
二、基本用法 #
2.1 创建CSS模块 #
创建 app/components/Button.module.css:
css
.button {
padding: 0.5rem 1rem;
border-radius: 0.25rem;
font-weight: 500;
}
.primary {
background-color: #3b82f6;
color: white;
}
.secondary {
background-color: #6b7280;
color: white;
}
.disabled {
opacity: 0.5;
cursor: not-allowed;
}
2.2 使用CSS模块 #
tsx
import styles from "./Button.module.css";
interface ButtonProps {
variant?: "primary" | "secondary";
disabled?: boolean;
children: React.ReactNode;
}
export function Button({
variant = "primary",
disabled,
children
}: ButtonProps) {
return (
<button
className={`${styles.button} ${styles[variant]} ${disabled ? styles.disabled : ""}`}
disabled={disabled}
>
{children}
</button>
);
}
2.3 使用links函数加载样式 #
tsx
import type { LinksFunction } from "@remix-run/node";
import styles from "./Button.module.css?url";
export const links: LinksFunction = () => [
{ rel: "stylesheet", href: styles },
];
export function Button() {
return <button className="button">点击</button>;
}
三、类名组合 #
3.1 使用clsx #
安装 clsx:
bash
npm install clsx
使用示例:
tsx
import clsx from "clsx";
import styles from "./Button.module.css";
export function Button({ variant, size, disabled, children }) {
return (
<button
className={clsx(
styles.button,
styles[variant],
styles[size],
disabled && styles.disabled
)}
>
{children}
</button>
);
}
3.2 组合多个模块 #
tsx
import clsx from "clsx";
import buttonStyles from "./Button.module.css";
import textStyles from "./Text.module.css";
export function Button({ children }) {
return (
<button className={clsx(buttonStyles.button, textStyles.bold)}>
{children}
</button>
);
}
四、CSS变量 #
4.1 定义变量 #
css
/* app/styles/variables.css */
:root {
--color-primary: #3b82f6;
--color-secondary: #6b7280;
--color-danger: #ef4444;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
--radius: 0.25rem;
}
4.2 使用变量 #
css
/* Button.module.css */
.button {
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius);
background-color: var(--color-primary);
color: white;
}
.danger {
background-color: var(--color-danger);
}
4.3 加载全局样式 #
tsx
import type { LinksFunction } from "@remix-run/node";
import variables from "~/styles/variables.css?url";
export const links: LinksFunction = () => [
{ rel: "stylesheet", href: variables },
];
五、组件样式组织 #
5.1 目录结构 #
text
app/
├── components/
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.module.css
│ │ └── index.ts
│ └── Card/
│ ├── Card.tsx
│ └── Card.module.css
└── styles/
├── variables.css
└── global.css
5.2 组件示例 #
tsx
import clsx from "clsx";
import type { LinksFunction } from "@remix-run/node";
import styles from "./Card.module.css?url";
export const links: LinksFunction = () => [
{ rel: "stylesheet", href: styles },
];
interface CardProps {
title: string;
variant?: "default" | "highlighted";
children: React.ReactNode;
}
export function Card({ title, variant = "default", children }: CardProps) {
return (
<div className={clsx(styles.card, styles[variant])}>
<h3 className={styles.title}>{title}</h3>
<div className={styles.content}>{children}</div>
</div>
);
}
六、响应式样式 #
6.1 媒体查询 #
css
/* Card.module.css */
.card {
padding: 1rem;
}
@media (min-width: 768px) {
.card {
padding: 1.5rem;
}
}
@media (min-width: 1024px) {
.card {
padding: 2rem;
}
}
6.2 CSS Grid响应式 #
css
.grid {
display: grid;
gap: 1rem;
grid-template-columns: 1fr;
}
@media (min-width: 640px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
七、动画和过渡 #
7.1 过渡效果 #
css
.button {
transition: all 0.2s ease-in-out;
}
.button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
7.2 动画 #
css
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.card {
animation: fadeIn 0.3s ease-out;
}
八、最佳实践 #
8.1 命名规范 #
css
/* 推荐:语义化命名 */
.container { }
.header { }
.content { }
.footer { }
.title { }
.description { }
/* 不推荐:外观命名 */
.blueBox { }
.bigText { }
.leftColumn { }
8.2 组合而非继承 #
css
/* 基础样式 */
.button {
padding: 0.5rem 1rem;
border-radius: 0.25rem;
}
/* 变体样式 */
.primary {
background-color: #3b82f6;
color: white;
}
.large {
padding: 1rem 2rem;
font-size: 1.125rem;
}
8.3 避免深层嵌套 #
css
/* 不推荐 */
.card .header .title .icon { }
/* 推荐 */
.card { }
.cardHeader { }
.cardTitle { }
.cardIcon { }
九、总结 #
本章我们学习了:
- 基本用法:创建和使用CSS模块
- 类名组合:使用clsx组合类名
- CSS变量:定义和使用全局变量
- 响应式:媒体查询和响应式布局
- 最佳实践:命名规范和代码组织
核心要点:
- CSS模块提供作用域隔离
- 使用clsx组合类名
- 使用CSS变量管理主题
- 保持样式简洁和语义化
最后更新:2026-03-28