Answer: How to move classic theme CSS into theme.json
Follow these steps to translate your existing CSS into the Global Styles JSON (theme.json) of a block theme, keeping the visual output identical without adding extra stylesheets.
1. Extract and categorize the CSS
- Identify rules that set site‑wide values: colors, font families, font sizes, line heights, spacing (margin/padding) that apply globally or to common HTML elements (
body, h1‑h6, p, a, etc.).
- Separate rules that target specific blocks or block‑inner elements (e.g.,
.wp-block-button, .wp-block-group__inner-container). These will go into the styles section.
- Note any rules that rely on complex selectors, pseudo‑classes, or pseudo‑elements (e.g.,
a:hover, .entry-content > * + *). These may need to stay as additional CSS or be handled via block style variations.
2. Map site‑wide values to settings
Add the extracted global values under the appropriate keys in theme.json. Example:
{
"version": 2,
"settings": {
"color": {
"palette": [
{ "slug": "primary", "color": "#0066cc", "name": "Primary" },
{ "slug": "background", "color": "#ffffff", "name": "Background" }
]
},
"typography": {
"fontFamilies": [
{ "fontFamily": "\"Helvetica Neue\", Arial, sans-serif", "name": "Helvetica", "slug": "helvetica" }
],
"fontSizes": [
{ "slug": "small", "size": "14px", "name": "Small" },
{ "slug": "large", "size": "20px", "name": "Large" }
]
},
"spacing": {
"units": ["px", "em", "rem"],
"spacingScale": [
{ "slug": "10", "size": "10px" },
{ "slug": "20", "size": "20px" }
]
}
}
}
3. Map block‑specific rules to styles
Place each block’s CSS under styles.blockName. Use the block’s CSS class name (without the wp-block- prefix) as the key. Example for buttons:
{
"styles": {
"button": {
"color": {
"background": "var(--wp--preset--color--primary)",
"text": "var(--wp--preset--color--background)"
},
"typography": {
"fontSize": "16px"
},
"spacing": {
"padding": {
"top": "12px",
"right": "24px",
"bottom": "12px",
"left": "24px"
}
},
"border": {
"radius": "4px"
}
}
}
}
4. Handle selectors that cannot be mapped
If you encounter rules that rely on:
- Pseudo‑classes/elements (
:hover, ::before)
- Adjacent or sibling combinators (
+, ~)
- Attribute selectors not exposed by blocks
Keep those rules in a separate stylesheet (e.g., style.css) or create a block style variation that adds a class to the block and scope the CSS there. This preserves the original appearance while keeping the bulk of the design in theme.json.
5. Verify the migration
- Activate the block theme.
- Clear any caching plugins or server caches.
- Open the front‑end in browser dev tools and compare computed values for colors, font sizes, and spacing against the original classic theme.
- Run a diff between the original CSS file and the computed styles (you can copy the computed styles from the
Styles pane).
- Optionally, run the
Theme Check plugin to ensure theme.json is valid.
Missing diagnostic detail
If any of your CSS rules still produce visual differences after the above steps, please share the specific selector or rule (including pseudo‑classes/combinators) that fails to match. That detail will determine whether a block style variation or an additional stylesheet is required.