CSS-in-JS viết style bằng JavaScript, gắn thẳng vào component.
import styled from 'styled-components'
const Button = styled.button<{ $variant: 'primary' | 'ghost' }>`
padding: 8px 16px;
border-radius: 8px;
background: ${(p) => (p.$variant === 'primary' ? 'var(--accent-solid)' : 'transparent')};
`Ưu: scope tự động, style đổi theo props/state ngay trong cùng file, xoá component là xoá luôn style của nó (không còn CSS chết).
Nhược: thư viện runtime phải sinh và chèn CSS trong lúc render — tốn thời gian main thread, tăng bundle, và với SSR phải thu thập style rồi chèn vào HTML, cấu hình phức tạp hơn.
Hướng đi hiện tại là zero-runtime: viết cú pháp tương tự nhưng biên dịch ra CSS tĩnh lúc build.
// vanilla-extract: chạy lúc build, ra file .css thật
import { style } from '@vanilla-extract/css'
export const button = style({ padding: '8px 16px', borderRadius: 8 })Nhóm này gồm Vanilla Extract, Panda CSS, Linaria.
Điểm quan trọng với Next.js App Router: thư viện CSS-in-JS chạy runtime không hoạt động trong Server Component vì cần context phía client. Đây là lý do phần lớn dự án Next.js mới chọn CSS Modules, Tailwind hoặc zero-runtime — trả lời được ý này cho thấy có theo dõi hệ sinh thái thật, không chỉ liệt kê ưu nhược.