theme.json là file JSON nằm ở root block theme WordPress 6+ — declare design system gồm color, typography, spacing, layout, default cho từng block. Bài này phân tích schema version 2 2026, tách rõ settings vs styles, cơ chế cascade per block, và 5 pattern theme.json phổ biến cho shop WordPress VN.
Vì sao theme.json thay được cả functions.php + style.css
Trước WordPress 5.8, design system theme nằm rải rác ba chỗ — functions.php khai báo color palette qua add_theme_support, style.css chứa CSS variable, block CSS riêng cho mỗi block custom. Quản lý hệ thống ba file song song dễ lệch token và khó audit khi project chạy dài.
theme.json gom toàn bộ design system về một file declarative duy nhất. WordPress core đọc file này, sinh ra CSS variable cho mọi token, áp default cho mọi block, đồng thời expose UI picker cho Site Editor để client không code vẫn đổi được màu.
3 lợi ích thực tế khi chuyển sang theme.json
- Single source of truth: design system gom 1 file — đổi màu primary 1 dòng JSON, mọi block kế thừa thay vì sửa 3-4 file rời rạc.
- UI Site Editor tự sinh: color palette + font size + spacing scale lên dropdown picker — client tự đổi không cần dev, giảm ticket “đổi màu cho anh”.
- CSS variable global: WordPress generate biến
--wp--preset--color--primarydùng được trong block custom, style.css, plugin — đồng bộ token cross-context.
Khi nào KHÔNG nên đầu tư theme.json đầy đủ
theme.json mạnh nhất với block theme dùng Site Editor — site classic theme đầu tư đầy đủ theme.json lại lãng phí. Có ba bối cảnh nên giữ approach cũ thay vì migrate toàn diện.
- Theme classic legacy nhiều năm: đã đầu tư PHP template phức tạp, migrate theme.json đòi rewrite kiến trúc — chỉ nên dùng hybrid mode với 10-15 token cơ bản.
- Landing 1-2 trang ngân sách dưới 5 triệu: setup theme.json đầy đủ tốn 4-6 giờ, không bù lại được giá trị khi site đơn giản và ít người chỉnh sửa.
- Site không cho client tự sửa: nếu design lock cứng và chỉ dev sửa CSS qua code, theme.json mất ưu điểm UI picker và chỉ còn vai trò register CSS variable.
Bước 1 — Hiểu schema version 2 và 7 top-level key
theme.json schema version 2 là phiên bản ổn định 2026, dùng cho WordPress 6.0 trở lên. Mỗi file bắt đầu bằng dòng tham chiếu schema URL để IDE auto-complete và validate cú pháp khi gõ.
Skeleton chuẩn 7 top-level key
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 2,
"settings": { /* design tokens cho phép */ },
"styles": { /* apply token cho element */ },
"customTemplates": [ /* template tuỳ chỉnh */ ],
"templateParts": [ /* parts header/footer */ ],
"patterns": [ /* slug pattern từ directory */ ]
}
Vai trò 7 key — đọc theo nghiệp vụ
Mỗi top-level key đảm nhiệm một vai trò riêng biệt — nhầm settings với styles là lỗi phổ biến nhất khi mới làm quen. Hai key đầu là backbone, năm key sau optional theo nhu cầu site.
- $schema + version: 2 dòng metadata bắt buộc — IDE đọc $schema để gợi ý key hợp lệ, WordPress đọc version để parse đúng phiên bản.
- settings: declare token nào có sẵn — palette màu, font family, spacing scale — chưa apply, chỉ liệt kê option.
- styles: apply token đã declare vào element cụ thể — body, heading, button — đây là phần “thực sự render”.
- customTemplates: đăng ký template tuỳ chỉnh xuất hiện trong Site Editor — vd page-landing.html cho landing page sale.
- templateParts: đăng ký các part header/footer/sidebar dùng chung — Site Editor cho user chọn part.
- patterns: liệt kê slug pattern từ Pattern Directory để pre-load vào theme, không cần user search.
Bước 2 — Settings: declare 5 nhóm token
Section settings là nơi liệt kê mọi token thiết kế cho phép. WordPress đọc settings để sinh CSS variable và bơm option vào UI Site Editor — chưa thực sự apply style lên element nào.
Settings color — palette + gradient + duotone
"settings": {
"color": {
"palette": [
{ "slug": "primary", "color": "#0066cc", "name": "Primary" },
{ "slug": "secondary", "color": "#ffaa00", "name": "Secondary" },
{ "slug": "text", "color": "#1a1a1a", "name": "Text" },
{ "slug": "muted", "color": "#666666", "name": "Muted" }
],
"gradients": [
{ "slug": "hero", "gradient": "linear-gradient(135deg, #0066cc 0%, #00aaff 100%)", "name": "Hero" }
],
"duotone": [
{ "slug": "primary-bw", "colors": ["#000000", "#0066cc"], "name": "Primary BW" }
]
}
}
Settings typography — font family + fluid size
"settings": {
"typography": {
"fontFamilies": [
{
"slug": "inter",
"fontFamily": "Inter, sans-serif",
"name": "Inter",
"fontFace": [
{ "fontWeight": "400", "src": ["file:./assets/fonts/inter-400.woff2"] },
{ "fontWeight": "700", "src": ["file:./assets/fonts/inter-700.woff2"] }
]
}
],
"fontSizes": [
{ "slug": "small", "size": "14px", "name": "Small" },
{ "slug": "medium", "size": "16px", "name": "Medium" },
{ "slug": "large", "size": "24px", "name": "Large" },
{ "slug": "x-large","size": "40px", "name": "Extra Large",
"fluid": { "min": "32px", "max": "56px" } }
]
}
}
Settings spacing — 8pt scale chuẩn shop
Spacing scale 8pt là chuẩn thiết kế hiện đại — mọi margin/padding/gap đều bội số 8. Khai báo scale trong theme.json giúp Site Editor cho user chọn dropdown thay vì gõ tay pixel, đồng bộ rhythm dọc của trang.
"settings": {
"spacing": {
"spacingScale": { "steps": 0 },
"spacingSizes": [
{ "slug": "10", "size": "4px", "name": "XXS" },
{ "slug": "20", "size": "8px", "name": "XS" },
{ "slug": "30", "size": "16px", "name": "S" },
{ "slug": "40", "size": "24px", "name": "M" },
{ "slug": "50", "size": "32px", "name": "L" },
{ "slug": "60", "size": "48px", "name": "XL" },
{ "slug": "70", "size": "96px", "name": "XXL" }
]
}
}
Settings layout — content + wide width
"settings": {
"layout": {
"contentSize": "720px",
"wideSize": "1200px"
}
}
contentSize quy định width tối đa khi paragraph render — đảm bảo dòng chữ không vượt 80-90 ký tự gây khó đọc. wideSize dùng cho block có thuộc tính alignWide như image hero hoặc gallery full-bleed.
Settings cho phép user override không
Một số settings có flag boolean cho phép user mở custom value bên cạnh preset — vd cho phép user nhập màu hex tự do thay vì chỉ chọn từ palette. Cẩn trọng khi mở, vì user có thể phá design system nếu thiếu hướng dẫn.
- color.custom: true: mở color picker tự do cho user nhập hex — phù hợp khi client cần linh hoạt branding theo campaign.
- typography.customFontSize: false: khoá user khỏi nhập font size lung tung, ép chọn từ fontSizes preset — giữ rhythm typography đồng nhất.
- spacing.customSpacingSize: false: ép user chỉ chọn từ spacingSizes — tránh tình trạng margin lẫn 13px, 17px, 23px phá rhythm 8pt.
Bước 3 — Styles: apply token vào body và block
Section styles là nơi token được apply thực sự vào element. Khác với settings chỉ liệt kê, styles trỏ token cụ thể tới body hoặc từng block — cascade từ global xuống chi tiết.
Styles top-level cho body
"styles": {
"color": {
"background": "var(--wp--preset--color--background)",
"text": "var(--wp--preset--color--text)"
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--inter)",
"fontSize": "var(--wp--preset--font-size--medium)",
"lineHeight": "1.6"
},
"spacing": {
"blockGap": "var(--wp--preset--spacing--40)"
}
}
Styles per-block override
"styles": {
"blocks": {
"core/heading": {
"typography": {
"fontFamily": "var(--wp--preset--font-family--inter)",
"fontWeight": "700"
}
},
"core/button": {
"color": {
"background": "var(--wp--preset--color--primary)",
"text": "#ffffff"
},
"border": { "radius": "6px" },
"spacing": {
"padding": { "top": "12px", "bottom": "12px", "left": "24px", "right": "24px" }
}
},
"core/post-title": {
"typography": { "fontSize": "var(--wp--preset--font-size--x-large)" }
}
}
}
Styles element pseudo-class
theme.json version 2 hỗ trợ style element link, heading, caption với pseudo-class hover, focus, active. Khả năng này thay được nhiều dòng CSS thừa khi muốn đổi màu link hover hoặc focus state cho keyboard navigation.
- elements.link: style mọi link trong content — color, text-decoration, font-weight chung cho toàn site.
- elements.link.:hover: đổi màu link khi hover — không cần CSS riêng cho :hover trong style.css.
- elements.heading: style chung cho H1-H6 — vd font-family Inter bold, line-height 1.3 áp cho mọi heading.
Bước 4 — Cascade: theme.json vs block.json vs CSS
Hiểu thứ tự ưu tiên giữa các nguồn style là điều kiện để debug khi style hiển thị không đúng kỳ vọng. WordPress cascade 4 tầng từ default tới user override, độc lập với style.css custom theme.
Bảng ưu tiên 5 nguồn style
| Source | Priority | Use case |
|---|---|---|
| theme.json settings | 1 (thấp nhất) | Declare token có sẵn, chưa apply |
| theme.json styles | 2 | Apply default global + per block |
| block.json custom block | 3 | Default cho block tự code |
| User override Site Editor | 4 (cao nhất) | Per-instance customization |
| style.css theme | Độc lập | CSS không thay được qua UI picker |
Khi style.css nên thắng theme.json
style.css chạy ngoài cascade theme.json — specificity CSS thuần quyết định thắng thua. Dùng style.css cho chi tiết design không expose cho user, vd hover effect phức tạp hoặc animation transform.
- Animation + transition: theme.json chưa hỗ trợ keyframes hoặc transition phức tạp — viết trong style.css với class custom.
- Responsive breakpoint custom: theme.json fluid typography đủ 90% case, nhưng media query custom (vd tablet ngang vs dọc) phải viết tay.
- Style component đặc thù: mega menu, mobile drawer, sticky header — code component riêng vì theme.json không cover được state-based UI.
Bước 5 — 4 pattern theme.json phổ biến cho shop VN
Theme cho shop WordPress VN có vài pattern theme.json đã được kiểm nghiệm qua nhiều dự án. Áp dụng pattern có sẵn nhanh hơn dựng từ skeleton trắng.
Pattern 1 — Shop tối giản trẻ trung
- Color: 2 màu chính (primary đậm + accent vàng/cam), background trắng, text gần đen.
- Typography: 1 font sans-serif (Inter/Be Vietnam Pro), 4 size step từ 14px tới 40px fluid.
- Spacing: scale 8pt 7 step, blockGap 24px cho rhythm thoáng.
- Button radius: 6px cho cảm giác hiện đại, không quá tròn không quá vuông.
Pattern 2 — Shop cao cấp luxury
- Color: palette đơn sắc (đen/trắng/vàng đồng), gradient hero subtle, duotone cho ảnh sản phẩm.
- Typography: 2 font (serif heading + sans body), font weight 300-700 phân tầng rõ.
- Spacing: blockGap 48px tạo whitespace nhiều, cảm giác cao cấp.
- Button radius: 0 (vuông) hoặc 9999px (pill) — chọn dứt khoát, tránh nửa vời.
Pattern 3 — Shop nhiều SKU performance-first
Shop bán hàng trăm SKU cần tối ưu LCP và CLS dưới ngưỡng Core Web Vitals. Pattern theme.json cho shop này tập trung giảm payload font và đơn giản hoá block style.
- fontFamilies giới hạn 1 font duy nhất: giảm 100-200KB payload font WOFF2 — LCP cải thiện rõ trên mobile 3G.
- fluid typography: dùng fluid min/max cho 2-3 font size lớn — không cần media query riêng.
- spacing đơn giản 5 step: giảm CSS variable dư thừa, file CSS generate gọn hơn 20-30%.
Pattern 4 — Shop B2B nhiều form + table
- core/table styling: override border color + cell padding + zebra stripe trong styles.blocks.
- core/button variation: 2-3 variant (primary/secondary/ghost) đăng ký qua block style filter.
- Form field token: spacing 12px padding + border radius 4px cho input — đồng bộ với plugin form như Gravity Forms.
Câu hỏi thường gặp
Theme classic có dùng được theme.json không?
Có, từ WordPress 5.8 trở lên. Theme classic kết hợp theme.json gọi là hybrid theme — dùng PHP template như cũ nhưng design system khai báo qua theme.json để hưởng CSS variable global.
Hybrid theme bị giới hạn — không dùng được customTemplates và templateParts (chỉ block theme mới có Site Editor). Phạm vi áp dụng dừng ở settings color, typography, spacing và styles cơ bản cho body.
theme.json conflict với plugin custom CSS — xử lý thế nào?
Plugin CSS thường viết bằng class selector có specificity cao hơn CSS variable do theme.json sinh ra. Trong phần lớn trường hợp, plugin CSS sẽ thắng và override style mặc định của theme.
Cách xử lý là viết CSS override trong style.css của theme với specificity cao hơn, enqueue style.css với priority lớn hơn plugin để chèn sau. Tránh dùng !important vì sẽ phá luôn user override từ Site Editor.
theme.json có size limit không?
Không có hard limit từ WordPress core. Trong thực tế file 50-200KB là phổ biến cho theme phức tạp có 5-10 block custom và 20-30 token design.
WordPress cache parsed result của theme.json nên size không impact runtime nhiều. File quá lớn trên 500KB có thể làm chậm load Site Editor — khi đó nên tách style per-block sang block.json riêng từng folder.
Update theme.json có cần restart server không?
Không cần. Edit file xong reload trang admin Site Editor là apply ngay — WordPress đọc lại file mỗi lần render editor view.
Trên production có cache plugin như WP Rocket hoặc Cache Enabler, phải clear cache plugin và hard reload browser (Ctrl+F5) để bypass cache cũ. Không cần restart PHP-FPM hay nginx vì theme.json không phải file PHP biên dịch.
theme.json đầy đủ cho shop nhỏ tốn bao nhiêu thời gian?
Dev WordPress 2-3 năm kinh nghiệm setup theme.json đầy đủ cho shop nhỏ trong 4-8 giờ. Phạm vi gồm palette 6-8 màu, 1-2 font family, spacing 7 step, styles cho 10-15 block phổ biến.
Shop phức tạp với 5-10 block custom và 3-4 pattern hero cần thêm 8-12 giờ để tinh chỉnh styles per-block và test cross-browser. Cộng test responsive 3 breakpoint, tổng thời gian setup design system production rơi vào 20-30 giờ.
Tài nguyên và bước tiếp theo
theme.json là nền của block theme — sau khi nắm schema và cascade, mở rộng sang template hierarchy và custom block để hoàn thiện workflow dev. Các bài liên quan trong cụm WordPress Development:
- Block theme vs Classic theme — so sánh 8 khía cạnh — quyết định paradigm trước khi đầu tư theme.json.
- Template hierarchy WordPress — 6 context và pattern override — kết hợp với customTemplates trong theme.json.
- Custom block FSE — 5 bước build block React — block.json kế thừa token từ theme.json.
- Thiết kế block pattern — 5 bước cho shop — pattern dùng lại token theme.json đồng bộ.
- Dịch vụ thiết kế website WordPress chuyên nghiệp — tham khảo gói thi công theme custom trọn gói.
Cần đội Web22 dev theme/plugin WordPress custom theo nhu cầu shop của bạn? Dịch vụ dev theme/plugin WordPress custom tại Web22 — báo giá rõ ràng theo phạm vi, không phát sinh sau khi ký hợp đồng.


