如何在 10 分钟内把任意 React 项目改造成新粗野主义
想给你那个乏味的 React 应用来一次大胆的改头换面?学习如何用 Neobrutalism 在短短 10 分钟内,把任意 React 项目变成一套惊艳的新粗野主义设计。分步教程,附前后对比示例。
Dov Azencot
@DovAzencot说实话吧:你的 React 应用多半和外面其他所有 React 应用长得一样。干净?当然。专业?绝对。让人记住?差得远。
但如果我告诉你,只要 10 分钟,你就能把那个平平无奇的项目变成一个让个性喷薄而出的东西呢?变成一个让人惊呼「哇,那是啥」的东西。
这就是新粗野主义的力量——一种大胆、毫不掩饰、让人无法忽视的设计风格。而有了 Neobrutalism,改造你的 React 项目简单到离谱。
端起你的咖啡(能量饮料也行,不评判),我们来把那个平淡无奇的应用变得有点辣味。
What the Heck is Neobrutalism Anyway?
在动手之前,我们先统一一下认识。新粗野主义是一场设计运动,它从 1950 年代那种生猛、大量使用混凝土的粗野主义建筑里汲取灵感,再赋予它一种现代、数字化的转译。
想想这些:
- 一切元素上的粗黑边框
- 硬朗的阴影(跟那种柔软的模糊毫无瓜葛)
- 黑、白、霓虹黄这类高对比配色
- 零圆角(锐利、有棱角,就是它)
- 打破网格的非对称布局
它是反完美主义的。它是叛逆的。它相当于穿着皮夹克去参加董事会。而且它管用。
Why Neobrutalism?
你当然可以从零打造新粗野主义组件,但既然有 Neobrutalism,何必重复造轮子?它是一个专为新粗野主义打造的 React UI 组件库,具备:
- 带着那股标志性粗野美学的现成组件
- 通过 CLI 轻松安装
- 用 Tailwind CSS 完全可定制
- 兼容 Next.js、Vite、Remix——基本上任意 React 配置都行
而且,它免费又开源。我们这就开始。
Step 1: Set Up Your Project (2 minutes)
先说要紧的。如果你手上已经有一个现成的 React 项目,那你已经领先一步了。如果没有,我们就快速起一个 Next.js 应用(不过这套流程适用于任意 React 框架)。
出现提示时,对 TypeScript 和 Tailwind CSS 都选「yes」。两者都会用到。
如果你用的是 Vite 或 Create React App,也没问题——配置几乎一模一样。
Step 2: Install Neobrutalism (1 minute)
现在,魔法开始了。我们需要初始化 shadcn(Neobrutalism 在底层用的就是它),并安装 Neobrutalism 的工具函数。
运行这条命令:
会出现一些提示。下面是建议的选择:
- Style: Default
- Base color: Slate(稍后会覆盖它,所以关系不大)
- CSS variables: Yes
接着,安装 Neobrutalism 的 utils:
搞定。就这样。现在你已经有了构建粗野界面的地基。
Step 3: Add the Neobrutalist Theme (2 minutes)
变身从这里真正开始。打开你的 global.css 文件(通常在 app/globals.css 或 src/index.css),把主题变量替换成 Neobrutalism 那套标志性的粗野主题。
把这段 CSS 粘贴进去:
@theme {
--font-head: var(--font-head);
--font-sans: var(--font-sans);
--radius: 0;
--shadow-xs: 1px 1px 0 0 var(--border);
--shadow-sm: 2px 2px 0 0 var(--border);
--shadow: 3px 3px 0 0 var(--border);
--shadow-md: 4px 4px 0 0 var(--border);
--shadow-lg: 6px 6px 0 0 var(--border);
--shadow-xl: 10px 10px 0 1px var(--border);
--shadow-2xl: 16px 16px 0 1px var(--border);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-border: var(--border);
}
:root {
--radius: 0;
--background: #fff;
--foreground: #000;
--primary: #ffdb33;
--primary-foreground: #000;
--secondary: #000;
--secondary-foreground: #fff;
--border: #000;
}
.dark {
--background: #1a1a1a;
--foreground: #f5f5f5;
--primary: #ffdb33;
--primary-foreground: #000;
--secondary: #3a3a3a;
--secondary-foreground: #f5f5f5;
--border: #3a3a3a;
}刚刚发生了什么?
- 我们清掉了所有 border-radius(再没有圆角了)
- 我们把柔软的阴影换成了硬朗、带偏移的阴影
- 我们设定了一套大胆的黑/白/黄配色
- 我们加上了暗色模式支持(因为我们又不是野蛮人)
你的应用已经开始变样了。但我们还没完。
Step 4: Install Your First Components (2 minutes)
我们来拿几个实际的组件。先从基础的开始:Button、Card 和 Input。
一条条运行这些命令:
每个组件都会被加到你的 components/neobrutalism/ 文件夹里,即取即用。一行 CSS 都不用写。
Step 5: Swap Out Your Components (2 minutes)
好玩的部分来了——把你那些乏味的老组件换成新的粗野组件。
Before:
// Your old, generic button
<button className="bg-blue-500 text-white px-4 py-2 rounded">
Click Me
</button>After:
import { Button } from "@/components/neobrutalism/Button";
<Button>Click Me</Button>就这么简单,你就有了一个带粗黑边框、硬阴影,以及那股标志性新粗野主义气质的按钮。
我们对卡片也来一遍:
Before:
<div className="bg-white shadow-lg rounded-lg p-6">
<h2 className="text-2xl font-bold">My Card</h2>
<p className="text-gray-600">Some generic content here.</p>
</div>After:
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/neobrutalism/Card";
<Card>
<CardHeader>
<CardTitle>My Card</CardTitle>
<CardDescription>Now with 100% more attitude.</CardDescription>
</CardHeader>
<CardContent>
Some bold content here.
</CardContent>
</Card>结构相同,但气质截然不同。卡片现在有了锐利的棱角、大胆的边框,以及一道让它从页面上浮起来的硬阴影。
Step 6: Add Neobrutalist Fonts (1 minute)
在新粗野主义里,排版极其重要。默认的系统字体撑不起来。Neobrutalism 推荐标题用 Archivo Black,正文用 Space Grotesk。
如果你用的是 Next.js,把这段加到你的 app/layout.tsx:
import { Archivo_Black, Space_Grotesk } from "next/font/google";
const archivoBlack = Archivo_Black({
subsets: ["latin"],
weight: "400",
variable: "--font-head",
display: "swap",
});
const spaceGrotesk = Space_Grotesk({
subsets: ["latin"],
weight: "400",
variable: "--font-sans",
display: "swap",
});
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={`${archivoBlack.variable} ${spaceGrotesk.variable}`}>
{children}
</body>
</html>
);
}现在你的标题厚重而大胆,正文则保持干净易读。
Step 7: Fine-Tune and Customize (Optional)
到这一步基本就完成了,但如果你想进一步定制,Neobrutalism 也让这件事很简单。
想换个点缀色? 改一下 CSS 里的 --primary 变量。
:root {
--primary: #ff006e; /* Hot pink instead of yellow */
}想要更柔和的阴影? 调一下阴影的变量。
--shadow: 2px 2px 0 0 var(--border); /* Smaller offset */想加更多组件? 到 neobrutalism.com/docs/components 看看整个组件库。这里有输入框、徽章、对话框、表格等等——全都带着那股粗野美学。
Before and After: The Transformation
好,我们来看看差别。下面是一个简单落地页在新粗野主义改造前后的样子。
Before: Generic React App
export default function GenericLanding() {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="max-w-md bg-white shadow-lg rounded-lg p-8">
<h1 className="text-3xl font-bold text-gray-900 mb-4">
Welcome to My App
</h1>
<p className="text-gray-600 mb-6">
This is a clean, minimal design that looks like every other React app.
</p>
<input
type="email"
placeholder="Enter your email"
className="w-full px-4 py-2 border border-gray-300 rounded mb-4"
/>
<button className="w-full bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
Get Started
</button>
</div>
</div>
);
}这有什么问题?
从技术上讲,没有任何问题。它能用。它干净。但它同样毫无记忆点。要是你把它给 100 个人看,他们会把它和这周见过的十几个别的网站搞混。
After: Neobrutalist Makeover
import { Button } from "@/components/neobrutalism/Button";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/neobrutalism/Card";
import { Input } from "@/components/neobrutalism/Input";
export default function BrutalLanding() {
return (
<div className="min-h-screen bg-[#ffdb33] flex items-center justify-center p-4">
<Card className="max-w-md w-full">
<CardHeader>
<CardTitle className="text-4xl font-head uppercase">
Welcome to My App
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<p className="text-lg font-sans">
This is a bold, memorable design that actually stands out.
</p>
<Input type="email" placeholder="Enter your email" />
<Button className="w-full">Get Started</Button>
</CardContent>
</Card>
</div>
);
}有什么变化?
- 背景: 从乏味的灰变成了电光黄
- 排版: 用 Archivo Black 做的大胆全大写标题
- 边框: 一切元素都有粗黑边框
- 阴影: 用硬朗、带偏移的阴影取代柔软的模糊
- 圆角: 零 border-radius——锐利而有棱角
- 气质: 从「企业宣传册」变成了「有脾气的独立创业公司」
组件结构相同,布局相同,但感觉完全不一样了。人们会记住这个。
Another Example: Dashboard Widget
我们来看一个更复杂的例子——一张仪表盘的统计卡片。
Before: Bland Dashboard
export default function GenericStats() {
return (
<div className="grid grid-cols-3 gap-4">
<div className="bg-white rounded-lg shadow p-6">
<p className="text-gray-500 text-sm">Total Users</p>
<p className="text-3xl font-bold text-gray-900">1,284</p>
<p className="text-green-500 text-sm">+12% from last month</p>
</div>
<div className="bg-white rounded-lg shadow p-6">
<p className="text-gray-500 text-sm">Revenue</p>
<p className="text-3xl font-bold text-gray-900">$52,340</p>
<p className="text-green-500 text-sm">+8% from last month</p>
</div>
<div className="bg-white rounded-lg shadow p-6">
<p className="text-gray-500 text-sm">Active Now</p>
<p className="text-3xl font-bold text-gray-900">127</p>
<p className="text-red-500 text-sm">-3% from last hour</p>
</div>
</div>
);
}After: Brutal Dashboard
import { Card, CardContent } from "@/components/neobrutalism/Card";
export default function BrutalStats() {
return (
<div className="grid grid-cols-3 gap-6">
<Card className="bg-[#ffdb33]">
<CardContent className="pt-6">
<p className="text-sm font-bold uppercase mb-2">Total Users</p>
<p className="text-5xl font-head mb-2">1,284</p>
<p className="text-sm font-bold">▲ 12% from last month</p>
</CardContent>
</Card>
<Card className="bg-white">
<CardContent className="pt-6">
<p className="text-sm font-bold uppercase mb-2">Revenue</p>
<p className="text-5xl font-head mb-2">$52,340</p>
<p className="text-sm font-bold">▲ 8% from last month</p>
</CardContent>
</Card>
<Card className="bg-black text-white">
<CardContent className="pt-6">
<p className="text-sm font-bold uppercase mb-2">Active Now</p>
<p className="text-5xl font-head mb-2">127</p>
<p className="text-sm font-bold">▼ 3% from last hour</p>
</CardContent>
</Card>
</div>
);
}有什么不同?
- 色块划分: 每张卡片都有鲜明不同的背景色(黄、白、黑)
- 大胆的排版: 数字特别大,用了展示字体
- 高对比: 黑底白字瞬间制造出视觉层级
- 大写标签: 让一切都显得更刻意、更大胆
- 用箭头而非颜色: 用 ▲ 和 ▼ 符号来保证清晰
同样的数据,呈现方式天差地别。粗野的那版让人觉得是自信设计出来的,而不是随手拼凑的。
Pro Tips for Neobrutalist Design
基础都掌握了,下面是几条真正抓住这套美学的窍门:
1. Embrace Asymmetry
别怕打破网格。把元素错位、让边框重叠、让留白参差不齐。完美很无聊。
2. Use Color Intentionally
新粗野主义偏爱高对比的配色。以黑白为底,再加一两种点缀色(黄、粉、青)。别搞成彩虹——定下一种气质,然后坚持到底。
3. Go Big on Typography
标题要大得夸张。正文可以正常,但你的 H1 应当抓人眼球。想要有力表达时,用粗体、大写的字。
4. Add Micro-Interactions
粗野不代表静止。加上一些悬停效果,让按钮轻微移位或阴影变大。保持含蓄,但要让人察觉得到。
<Button className="hover:translate-x-1 hover:translate-y-1 transition-transform">
Click Me
</Button>5. Don't Overdo It
不是每个元素都需要粗边框。不是每个区块都需要亮色背景。平衡依然重要——只是把天平往大胆那头稍微倾一点。
What to Do Next
恭喜!你刚刚在大约 10 分钟里给你的 React 项目做了一次彻底的视觉翻新。接下来你可以这么做:
Explore More Components
Neobrutalism 有一整套组件库——徽章、对话框、表格、标签页等等。到组件文档看看,还能加些什么。
Customize Your Theme
摆弄一下 CSS 变量,让它贴合你的品牌。换点缀色、调阴影强度、微调间距,让它成为你的。
Build Something Cool
既然你的应用不再千篇一律,那就秀出来。发到 Twitter,贴到 Reddit,放进你的作品集。新粗野主义会被人注意到。
Join the Community
Neobrutalism 有一个活跃的 Discord,设计师和开发者在那里分享项目、互相答疑、为粗野设计而热血。进去打个招呼吧。
Final Thoughts
大多数 React 应用长得一样,是因为大多数开发者都伸手去拿同样的工具——Material UI、Bootstrap、默认设置的 shadcn。这些没什么不好(它们都很棒),但它们帮不了你脱颖而出。
新粗野主义是通往个性的捷径。它大胆、令人难忘,而且只要工具得当,实现起来出乎意料地简单。Neobrutalism 把你切换过去所需的一切都备齐了,无需从零重建。
短短 10 分钟,你就从「又一个 React 应用」跃升到了「等等,那是啥」。老实说?这挺有威力的。
所以,动手吧——让你的应用变得无法被忽视。
现在,出去做点粗野的东西吧。🚀