Bỏ qua đến nội dung

Cách chuyển bất kỳ dự án React nào sang neo-brutalism trong 10 phút

Muốn khoác cho ứng dụng React nhàm chán của bạn một diện mạo táo bạo? Học cách biến bất kỳ dự án React nào thành một thiết kế neo-brutalist đầy ấn tượng chỉ trong 10 phút với Neobrutalism. Bài hướng dẫn từng bước kèm ví dụ trước/sau.

Thành thật mà nói: ứng dụng React của bạn có lẽ trông giống mọi ứng dụng React khác ngoài kia. Sạch sẽ? Chắc chắn rồi. Chuyên nghiệp? Tuyệt đối. Đáng nhớ? Còn xa mới tới.


Nhưng nếu tôi nói rằng chỉ trong 10 phút, bạn có thể biến dự án trông đại trà của mình thành thứ gì đó gào lên cá tính thì sao? Thứ gì đó khiến người ta phải thốt lên: "Ồ, cái này là GÌ vậy?"


Đó chính là sức mạnh của neo-brutalism: một phong cách thiết kế táo bạo, không khoan nhượng và không thể bị bỏ qua. Và với Neobrutalism, việc chuyển đổi dự án React của bạn dễ đến mức nực cười.


Lấy cà phê của bạn ra (hay nước tăng lực cũng được, không phán xét), và cùng biến ứng dụng nhạt nhẽo đó thành thứ gì đó có chút gia vị.


Rốt cuộc thì neo-brutalism là gì?

Trước khi lao vào, hãy thống nhất với nhau đã. Neo-brutalism là một trào lưu thiết kế lấy cảm hứng từ kiến trúc brutalist thô ráp, ngập bê tông của thập niên 1950 và mang lại cho nó một sự lột xác hiện đại, mang chất số.


Hãy hình dung:

  • Đường viền đen dày ở mọi thứ
  • Bóng đổ cứng (không có mấy trò blur mềm nhũn đó)
  • Màu tương phản cao như đen, trắng và vàng neon
  • Không một góc bo tròn nào (mọi thứ đều sắc và góc cạnh)
  • Bố cục bất đối xứng phá vỡ lưới

Đó là chống chủ nghĩa hoàn hảo. Đó là nổi loạn. Đó là phiên bản thiết kế của việc mặc áo khoác da đi họp hội đồng quản trị. Và nó hiệu quả.


Tại sao lại là Neobrutalism?

Bạn có thể tự dựng các thành phần neo-brutalist từ đầu, nhưng tại sao phải phát minh lại bánh xe khi đã có Neobrutalism? Đây là một thư viện UI cho React được xây riêng cho neo-brutalism, với:

  • Các thành phần dựng sẵn mang thẩm mỹ brutal đặc trưng đó
  • Cài đặt dễ dàng qua CLI
  • Tùy biến hoàn toàn với Tailwind CSS
  • Tương thích với Next.js, Vite, Remix; về cơ bản là mọi thiết lập React

Hơn nữa, nó miễn phí và mã nguồn mở. Bắt đầu thôi.



Bước 1: Thiết lập dự án của bạn (2 phút)

Chuyện quan trọng trước đã. Nếu bạn đang làm việc với một dự án React sẵn có, bạn đã đi trước một bước. Nếu chưa, cùng dựng nhanh một ứng dụng Next.js (nhưng cách này hoạt động với bất kỳ framework React nào).


pnpm create next-app@latest my-brutal-app
cd my-brutal-app
npx create-next-app@latest my-brutal-app
cd my-brutal-app
yarn create next-app@latest my-brutal-app
cd my-brutal-app
bunx --bun create-next-app@latest my-brutal-app
cd my-brutal-app

Hãy chọn có với TypeScript và Tailwind CSS khi được hỏi. Chúng ta cần cả hai.


Nếu bạn dùng Vite hoặc Create React App, cũng ổn thôi: cách thiết lập gần như y hệt.



Bước 2: Cài Neobrutalism (1 phút)

Giờ đến phần phép thuật. Chúng ta cần khởi tạo shadcn (Neobrutalism dựa vào nó ở bên dưới) và cài các tiện ích của Neobrutalism.


Chạy lệnh này:

pnpm dlx shadcn@latest init
npx shadcn@latest init
yarn dlx shadcn@latest init
bunx --bun shadcn@latest init

Sẽ có vài câu hỏi hiện ra. Đây là những gì bạn nên chọn:

  • Style: Default
  • Base color: Slate (không quan trọng lắm, đằng nào ta cũng ghi đè)
  • CSS variables: Yes

Tiếp theo, cài các utils của Neobrutalism:

pnpm dlx shadcn@latest add https://neobrutalism.com/r/utils.json
npx shadcn@latest add https://neobrutalism.com/r/utils.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/utils.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/utils.json

Xong. Chỉ vậy thôi. Giờ bạn đã có nền móng để xây các giao diện brutalist.



Bước 3: Thêm theme neo-brutalist (2 phút)

Đây là nơi cuộc lột xác thực sự bắt đầu. Mở tệp global.css của bạn (thường ở app/globals.css hoặc src/index.css) và thay các biến theme bằng theme brutal đặc trưng của Neobrutalism.


Dán cái này vào CSS của bạn:

@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;
}

Chuyện gì vừa xảy ra?

  • Chúng ta đã xóa mọi border-radius (không còn góc bo tròn nữa)
  • Chúng ta đã thay các bóng đổ mềm bằng bóng đổ cứng, có độ lệch
  • Chúng ta đã thiết lập một hệ màu đen/trắng/vàng táo bạo
  • Chúng ta đã thêm hỗ trợ chế độ tối (vì chúng ta không phải người rừng)

Ứng dụng của bạn đã bắt đầu trông khác đi. Nhưng chưa xong đâu.



Bước 4: Cài các thành phần đầu tiên của bạn (2 phút)

Cùng lấy vài thành phần thực thụ. Chúng ta sẽ bắt đầu với những thứ cốt lõi: Button, Card và Input.


Chạy các lệnh này từng cái một:

pnpm dlx shadcn@latest add https://neobrutalism.com/r/button.json
npx shadcn@latest add https://neobrutalism.com/r/card.json
npx shadcn@latest add https://neobrutalism.com/r/input.json
npx shadcn@latest add https://neobrutalism.com/r/button.json
npx shadcn@latest add https://neobrutalism.com/r/card.json
npx shadcn@latest add https://neobrutalism.com/r/input.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/button.json
npx shadcn@latest add https://neobrutalism.com/r/card.json
npx shadcn@latest add https://neobrutalism.com/r/input.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/button.json
npx shadcn@latest add https://neobrutalism.com/r/card.json
npx shadcn@latest add https://neobrutalism.com/r/input.json

Mỗi thành phần được thêm vào thư mục components/neobrutalism/ của bạn, sẵn sàng để dùng. Không cần viết lấy một dòng CSS.



Bước 5: Thay thế các thành phần của bạn (2 phút)

Giờ đến phần thú vị: thay các thành phần cũ nhàm chán của bạn bằng những cái mới, đầy chất brutal.


Trước:

// Your old, generic button
<button className="bg-blue-500 text-white px-4 py-2 rounded">
  Click Me
</button>

Sau:

import { Button } from "@/components/neobrutalism/Button";
 
<Button>Click Me</Button>

Chỉ trong nháy mắt, bạn đã có một nút bấm với đường viền đen dày, một bóng đổ cứng và cái chất neo-brutalist đặc trưng đó.


Cùng làm điều tương tự với một thẻ:


Trước:

<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>

Sau:

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>

Cùng một cấu trúc, một chất hoàn toàn khác. Giờ thẻ có cạnh sắc, đường viền dày và một bóng đổ cứng khiến nó như nhảy ra khỏi trang.



Bước 6: Thêm các phông chữ neo-brutalist (1 phút)

Trong neo-brutalism, typography là thứ CỰC KỲ QUAN TRỌNG. Các phông hệ thống mặc định sẽ không đủ. Neobrutalism khuyên dùng Archivo Black cho tiêu đề và Space Grotesk cho phần chữ nội dung.


Nếu bạn dùng Next.js, hãy thêm cái này vào app/layout.tsx của bạn:

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>
  );
}

Giờ tiêu đề của bạn đồ sộ và đậm, còn phần chữ nội dung vẫn sạch sẽ và dễ đọc.



Bước 7: Tinh chỉnh và tùy biến (tùy chọn)

Đến bước này về cơ bản bạn đã xong, nhưng nếu muốn tùy biến sâu hơn, Neobrutalism khiến việc đó dễ dàng.


Muốn một màu nhấn khác? Đổi biến --primary trong CSS của bạn.

:root {
  --primary: #ff006e; /* Hot pink instead of yellow */
}

Muốn bóng đổ mềm hơn? Điều chỉnh các biến bóng đổ.

--shadow: 2px 2px 0 0 var(--border); /* Smaller offset */

Muốn thêm thành phần? Ghé thư viện đầy đủ tại neobrutalism.com/docs/components. Có input, badge, dialog, table và nhiều nữa, tất cả đều mang thẩm mỹ brutal đó.



Trước và sau: cuộc lột xác

Được rồi, cùng xem sự khác biệt. Đây là hình dáng của một landing page đơn giản trước và sau khi chuyển đổi neo-brutalist.


Trước: Một ứng dụng React đại trà

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>
  );
}

Có gì sai ở đây?

Về mặt kỹ thuật thì không có gì. Nó hoạt động được. Nó sạch sẽ. Nhưng nó cũng hoàn toàn dễ quên. Nếu bạn cho 100 người xem, họ sẽ nhầm nó với cả tá trang khác họ thấy trong tuần này.


Sau: cú lột xác neo-brutalist

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>
  );
}

Điều gì đã thay đổi?

  • Nền: chuyển từ xám nhàm chán sang vàng điện
  • Typography: một tiêu đề đậm, in hoa, với Archivo Black
  • Đường viền: mọi thứ đều có đường viền đen dày
  • Bóng đổ: cứng và có độ lệch, thay cho blur mềm
  • Góc: border-radius bằng 0, sắc và góc cạnh
  • Chất: từ "tờ rơi doanh nghiệp" sang "startup indie có cá tính"

Đây vẫn là cùng cấu trúc thành phần, cùng bố cục, nhưng cảm giác hoàn toàn khác. Người ta sẽ nhớ trang này.



Một ví dụ khác: Widget dashboard

Cùng xem một ví dụ phức tạp hơn: một thẻ thống kê dashboard.


Trước: Một dashboard nhạt nhẽo

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>
  );
}

Sau: Một dashboard brutal

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>
  );
}

Điều gì khác biệt?

  • Color blocking: mỗi thẻ có một nền riêng (vàng, trắng, đen)
  • Typography đậm: các con số khổng lồ và dùng phông display
  • Tương phản cao: chữ trắng trên nền đen tạo phân cấp thị giác tức thì
  • Nhãn in hoa: khiến mọi thứ cảm giác có chủ đích và đậm hơn
  • Mũi tên thay cho màu: dùng các ký hiệu ▲ và ▼ để rõ ràng

Cùng dữ liệu, cách trình bày khác biệt hoàn toàn. Phiên bản brutal cảm giác tự tin và có tính toán, không chỉ là ghép lại.



Mẹo chuyên nghiệp cho thiết kế neo-brutalist

Giờ bạn đã nắm được những điều cơ bản, đây là vài mẹo để thực sự chạm đúng thẩm mỹ:


1. Đón nhận sự bất đối xứng

Đừng ngại phá vỡ lưới. Dịch các phần tử, chồng các đường viền, để mọi thứ thở một cách không đều. Sự hoàn hảo thì nhàm chán.


2. Dùng màu có chủ đích

Neo-brutalism yêu những kết hợp màu tương phản cao. Đen và trắng làm nền, rồi thêm một hoặc hai màu nhấn (vàng, hồng, cyan). Đừng biến thành cầu vồng: chọn một chất và cam kết với nó.


3. Làm lớn với typography

Tiêu đề phải KHỔNG LỒ. Phần chữ nội dung có thể bình thường, nhưng các H1 của bạn phải thu hút sự chú ý. Dùng chữ đậm, in hoa khi bạn muốn tạo một tuyên ngôn.


4. Thêm các vi tương tác

Brutal không có nghĩa là tĩnh. Thêm các hiệu ứng hover nơi nút bấm dịch nhẹ hoặc bóng đổ lớn ra. Giữ nó tinh tế nhưng dễ nhận thấy.

<Button className="hover:translate-x-1 hover:translate-y-1 transition-transform">
  Click Me
</Button>

5. Đừng quá tay

Không phải phần tử nào cũng cần một đường viền dày. Không phải khu vực nào cũng cần một nền chói. Sự cân bằng vẫn quan trọng, chỉ là nghiêng về phía táo bạo.



Làm gì tiếp theo

Chúc mừng. Bạn vừa thực hiện một cuộc đại tu thị giác hoàn chỉnh cho dự án React của mình trong khoảng 10 phút. Đây là những gì bạn có thể làm từ đây:


Khám phá thêm các thành phần

Neobrutalism có một thư viện thành phần đầy đủ: badge, dialog, table, tab và nhiều nữa. Ghé tài liệu thành phần và xem bạn còn có thể thêm gì.


Tùy biến theme của bạn

Nghịch với các biến CSS để khớp với thương hiệu của bạn. Đổi màu nhấn, chỉnh cường độ bóng đổ, hoặc tinh chỉnh khoảng cách để biến nó thành của bạn.


Xây thứ gì đó thật ngầu

Giờ ứng dụng của bạn không còn trông đại trà, hãy khoe nó. Chia sẻ trên Twitter, đăng lên Reddit, thêm vào portfolio của bạn. Neo-brutalism thu hút sự chú ý.


Tham gia cộng đồng

Neobrutalism có một Discord rất sôi nổi nơi các nhà thiết kế và lập trình viên chia sẻ dự án, đặt câu hỏi và say sưa bàn về thiết kế brutal. Ghé qua và chào một tiếng.



Vài suy nghĩ cuối

Phần lớn ứng dụng React trông giống nhau vì phần lớn lập trình viên với tay đến cùng những công cụ: Material UI, Bootstrap, shadcn với cài đặt mặc định. Chẳng có gì sai với chúng (chúng tuyệt vời), nhưng chúng sẽ không giúp bạn nổi bật.


Neo-brutalism là một lối tắt đến cá tính. Nó táo bạo, đáng nhớ và dễ triển khai đến bất ngờ khi có công cụ phù hợp. Neobrutalism mang lại cho bạn mọi thứ cần thiết để chuyển đổi mà không phải xây lại từ đầu.


Chỉ trong 10 phút, bạn đã đi từ "lại thêm một ứng dụng React" đến "khoan đã, cái này là GÌ vậy?". Và thành thật mà nói? Điều đó rất mạnh mẽ.


Vậy nên cứ tiến tới: khiến ứng dụng của bạn không thể bị bỏ qua.


Giờ thì ra ngoài kia và xây một thứ gì đó thật brutal. 🚀


← Quay lại các bài viết