How to build a block theme with theme.json — typography, color palettes, and spacing scales?

Let’s dive into building a block theme with theme.json, focusing on how to get your typography, color palettes, and spacing scales just right. Think of theme.json as the central control panel for your WordPress site’s look and feel when you’re using block themes. It’s where you define the foundational styles that will cascade across your entire website. This means you can set things up once, and have them applied consistently, making your life way easier.

We’re going to break down how to get your typography, colors, and spacing looking sharp by digging into theme.json. This isn’t about just slapping some CSS onto a page; it’s about leveraging the power of WordPress’s block editor to create a cohesive and customizable experience for yourself and your users. We’ll get practical, showing you what to put where and why.

Before we get too deep into specific styling, it’s crucial to get a handle on what theme.json actually is and why it’s so important for block themes. At its core, theme.json is a configuration file that allows you to define global styles for your WordPress site. This includes things like your site’s color scheme, typography settings, layout options, and much more.

It acts as a single source of truth. Instead of scattering style declarations across multiple CSS files, you centralize them here. This makes your theme more performant, easier to manage, and gives users (or yourself) a consistent way to apply styles across the entire site through the Site Editor.

Structure of theme.json

theme.json is essentially a JSON object. This means it has a very specific structure, with key-value pairs. You’ll see it organized into different sections, each controlling a specific aspect of your theme’s styling. We’ll be focusing on these key sections:

  • settings: This is where you define the available options for users in the Site Editor. Think of this as the “palette” you offer.
  • styles: This is where you apply the actual styles based on the settings you’ve defined. This is the “painting” you create with your palette.

Why Use theme.json?

There are a few solid reasons why theme.json is the way to go for block themes:

  • Consistency: It ensures that your brand’s visual identity is maintained across every part of your website, from headers and footers to individual posts and pages.
  • Performance: By centralizing styles and leveraging WordPress’s built-in systems, theme.json can lead to more efficient CSS output, which is great for site speed.
  • Customization: It empowers users to easily customize their site’s look and feel through the WordPress Site Editor without needing to touch code.
  • Maintainability: Having all your global styles in one place makes updates and modifications much simpler.

For those interested in expanding their knowledge on creating block themes using theme.json, a related article that delves deeper into the intricacies of design elements is available at The Sheryar Blog. This resource provides valuable insights into typography, color palettes, and spacing scales, making it an excellent complement to your understanding of block theme development.

Typography Settings in theme.json

Typography is a huge part of how your content is perceived. Getting it right means ensuring readability and reflecting your brand’s personality. theme.json gives you a lot of power to control typography at a global level.

Defining Font Families

You’ll want to specify the font families that are available to your users. This usually involves listing the primary font for headings and the font for body text.

“`json

{

“settings”: {

“typography”: {

“fontFamilies”: [

{

“fontFamily”: “-apple-system, BlinkMacSystemFont, \”Segoe UI\”, Roboto, Helvetica, Arial, sans-serif, \”Apple Color Emoji\”, \”Segoe UI Emoji\”, \”Segoe UI Symbol\””,

“name”: “System Default”

},

{

“fontFamily”: “\”Inter\”, sans-serif”,

“name”: “Inter”

},

{

“fontFamily”: “\”Playfair Display\”, serif”,

“name”: “Playfair Display”

}

]

}

}

}

“`

Explanation:

  • fontFamilies: This is an array of objects, where each object defines a font family.
  • fontFamily: This is the actual CSS font-family value. It’s good practice to include fallback fonts here (like system defaults) to ensure your text still displays correctly if the primary font fails to load.
  • name: This is a human-readable name that will appear in the Site Editor’s font selection menus.

Practical Tip: To use custom fonts like “Inter” or “Playfair Display,” you’ll need to enqueue them properly in your theme’s functions.php file using wp_enqueue_style. Make sure the font files are accessible either through a CDN or locally within your theme.

Setting Default Font Sizes

Defining default font sizes helps maintain visual hierarchy and readability across your entire site. You can set these for different elements.

“`json

{

“styles”: {

“blocks”: {

“core/post-content”: {

“typography”: {

“fontSize”: “1.125rem”

}

},

“core/post-title”: {

“typography”: {

“fontSize”: “2.5rem”

}

},

“core/heading”: {

“typography”: {

“fontSize”: “2rem”

},

“layout”: {

“padding”: “1rem 0”

}

}

}

}

}

“`

Explanation:

  • styles.blocks: We target specific blocks here. core/post-content applies to the main content area, core/post-title to the post title, and core/heading to any heading block.
  • typography.fontSize: This is where you set the size. rem is generally preferred for scalability and accessibility, as it’s relative to the root font size.

Practical Tip: While you can set absolute pixel values, using rem or em units is more flexible. WordPress also provides predefined size options in the Site Editor based on what you define in settings.typography.fontSizes. It’s good to define a few custom sizes here, but also to allow users to pick from a range.

Enabling Font Size Controls

To give users the ability to adjust font sizes in the Site Editor, you need to define predefined font sizes in the settings section.

“`json

{

“settings”: {

“typography”: {

“fontSizes”: [

{

“size”: “0.875rem”,

“name”: “Small”

},

{

“size”: “1rem”,

“name”: “Base”

},

{

“size”: “1.25rem”,

“name”: “Medium”

},

{

“size”: “1.75rem”,

“name”: “Large”

},

{

“size”: “2.5rem”,

“name”: “Extra Large”

}

]

}

}

}

“`

Explanation:

  • settings.typography.fontSizes: Similar to fontFamilies, this is an array of objects.
  • size: The actual CSS value for the font size.
  • name: The label that appears in the Site Editor’s font size selector.

Practical Tip: Aim for a logical progression of sizes. These presets appear in the “Typography” panel for blocks that support font size adjustments. Users can then choose from these or, if your theme allows, enter a custom value.

Color Palettes in theme.json

Color is a powerful tool for branding and setting the mood of your website. theme.json allows you to define a consistent set of colors that users can apply across their site, ensuring brand adherence.

Defining Global Colors

This is where you specify the core colors for your website. These will become available in the Site Editor for elements like background colors, text colors, button colors, and more.

“`json

{

“settings”: {

“color”: {

“custom”: false,

“palette”: [

{

“color”: “#0a2540”,

“name”: “Primary (Dark Blue)”,

“slug”: “primary-dark-blue”

},

{

“color”: “#38b2ac”,

“name”: “Secondary (Teal)”,

“slug”: “secondary-teal”

},

{

“color”: “#f7fafc”,

“name”: “Background (Light Gray)”,

“slug”: “background-light-gray”

},

{

“color”: “#4a5568”,

“name”: “Text (Dark Gray)”,

“slug”: “text-dark-gray”

},

{

“color”: “#ffffff”,

“name”: “White”,

“slug”: “white”

}

]

}

}

}

“`

Explanation:

  • settings.color.palette: This is an array of color objects.
  • color: The actual hexadecimal color value (you can also use rgb() or hsl()).
  • name: The human-readable name that will appear in the color pickers in the Site Editor.
  • slug: A machine-readable identifier, often used internally by WordPress. It’s a good practice to use this for consistency.
  • custom: false: This setting is important. Setting custom to false disables the ability for users to pick any arbitrary color. They will be restricted to the colors you define in the palette. If you want to allow custom colors, you’d set this to true or remove it (as true is the default).

Practical Tip: Think about your brand’s primary, secondary, and accent colors, as well as common UI element colors like background and text. Providing a curated palette is key to maintaining design integrity.

Applying Colors to Specific Elements

Once you’ve defined your palette, you can start applying these colors to different parts of your theme using the styles section.

“`json

{

“styles”: {

“color”: {

“background”: “var(–wp–preset–color–background-light-gray)”,

“text”: “var(–wp–preset–color–text-dark-gray)”

},

“elements”: {

“link”: {

“color”: {

“text”: “var(–wp–preset–color–secondary-teal)”

},

“typography”: {

“textDecoration”: “none”

}

},

“button”: {

“color”: {

“background”: “var(–wp–preset–color–primary-dark-blue)”,

“text”: “var(–wp–preset–color–white)”

},

“typography”: {

“fontWeight”: “700”

}

}

},

“blocks”: {

“core/button”: {

“color”: {

“background”: “var(–wp–preset–color–secondary-teal)”,

“text”: “var(–wp–preset–color–white)”

}

}

}

}

}

“`

Explanation:

  • styles.color: Sets the global background and text color for the entire site. Notice we’re using CSS variables derived from our palette slugs: var(--wp--preset--color--your-slug). This is how WordPress links your defined palette colors to actual CSS.
  • styles.elements.link: Styles for all anchor (link) elements.
  • styles.elements.button: Styles for the default button appearance.
  • styles.blocks."core/button": Styles specifically for the core button block. You can override general element styles with block-specific styles.

Practical Tip: When applying colors, always use the var(--wp--preset--color--your-slug) syntax. This ensures that if you later change a color in your palette, the changes will automatically propagate throughout your site. Experiment with button styles to make them pop.

Gradients (Advanced)

theme.json also allows you to define color gradients, which can add a nice visual flair to backgrounds and other elements.

“`json

{

“settings”: {

“color”: {

“customGradients”: false,

“gradients”: [

{

“gradient”: “linear-gradient(135deg, var(–wp–preset–color–primary-dark-blue) 0%, var(–wp–preset–color–secondary-teal) 100%)”,

“name”: “Primary to Secondary”,

“slug”: “primary-to-secondary”

}

]

}

}

}

“`

Explanation:

  • settings.color.gradients: An array to define your gradients.
  • gradient: The CSS linear-gradient or radial-gradient value. You can reference your defined palette colors here.
  • name and slug: Similar to color properties.
  • customGradients: false: Again, restricts users to your defined gradients.

Practical Tip: Gradients can be subtle or bold. Use them thoughtfully. They’re great for hero sections, buttons, or decorative elements. Remember to test how they look on different screen sizes.

Spacing Scales in theme.json

Consistent spacing is fundamental to good design. It guides the eye, creates visual breathing room, and makes your interface feel organized and professional. theme.json allows you to define a harmonious scale of spacing values.

Defining Spacing Units

You can set up a set of predefined spacing values that users can choose from for things like padding, margins, and gap between elements.

“`json

{

“settings”: {

“spacing”: {

“units”: [“px”, “em”, “rem”, “%”],

“customSpacingScale”: true,

“spacingScale”: [

{

“size”: “0.25rem”,

“name”: “Extra Small”

},

{

“size”: “0.5rem”,

“name”: “Small”

},

{

“size”: “1rem”,

“name”: “Medium”

},

{

“size”: “1.5rem”,

“name”: “Large”

},

{

“size”: “2.5rem”,

“name”: “Extra Large”

}

]

}

}

}

“`

Explanation:

  • settings.spacing.units: Defines the units users can choose from (e.g., pixels, rems, percentages). rem is generally recommended.
  • customSpacingScale: true: This allows users to input custom spacing values if they need something outside the predefined scale. If you want to restrict them to your scale, set this to false.
  • settings.spacing.spacingScale: An array of predefined spacing objects.
  • size: The CSS value.
  • name: The label seen in the Site Editor.

Practical Tip: Think about common spacing needs. A small unit for minor adjustments, a medium unit for standard padding, and a larger unit for significant separation. A good scale starts small and grows progressively.

Applying Spacing to Layout and Blocks

Now, let’s apply these defined spacing values. This makes sure that when you’re designing pages, you’re always pulling from your consistent scale.

“`json

{

“styles”: {

“layout”: {

“contentSize”: “650px”,

“wideSize”: “1200px”

},

“spacing”: {

“padding”: {

“top”: “var(–wp–preset–spacing–small)”,

“bottom”: “var(–wp–preset–spacing–small)”,

“left”: “var(–wp–preset–spacing–medium)”,

“right”: “var(–wp–preset–spacing–medium)”

},

“margin”: {

“top”: “var(–wp–preset–spacing–medium)”,

“bottom”: “var(–wp–preset–spacing–medium)”

}

},

“blocks”: {

“core/post-content”: {

“spacing”: {

“padding”: {

“top”: “var(–wp–preset–spacing–large)”,

“bottom”: “var(–wp–preset–spacing–large)”

}

}

},

“core/group”: {

“spacing”: {

“padding”: “var(–wp–preset–spacing–medium)”

}

},

“core/columns”: {

“spacing”: {

“margin”: {

“bottom”: “var(–wp–preset–spacing–extra-large)”

}

}

}

}

}

}

“`

Explanation:

  • styles.layout: Sets the maximum width for content and “wide” content.
  • styles.spacing: Applies default padding and margins globally. Again, we use CSS variables like var(--wp--preset--spacing--your-name).
  • styles.blocks: Here we’re applying spacing to specific blocks. Notice how we can set individual sides for padding and margin, or a single value for all sides.

Practical Tip: Use the Site Editor to visualize these changes. Drag and drop elements, adjust padding, and see how your spacing scale plays out. Ensure there’s enough whitespace around elements to prevent them from feeling cramped.

If you’re looking to enhance your block theme with theme.json by focusing on typography, color palettes, and spacing scales, you might also find it beneficial to explore how these elements can impact your website’s performance. For insights on optimizing your site speed, check out this informative article on Google PageSpeed Insights, which provides valuable tips to ensure your design not only looks great but also loads efficiently.

Customizing Block Settings with theme.json

Beyond global styles, theme.json lets you fine-tune the settings for individual blocks, offering more granular control over what users can and can’t do. This is crucial for creating a streamlined editing experience tailored to your theme.

Enabling/Disabling Block Features

You can control whether users can change certain aspects of a block directly within the Site Editor. For example, you might want to disable color controls for certain blocks or lock specific layout options.

“`json

{

“settings”: {

“blocks”: {

“core/image”: {

“color”: false,

“spacing”: false,

“layout”: false

},

“core/button”: {

“color”: {

“text”: true,

“background”: true

},

“typography”: {

“fontSize”: true

}

}

}

}

}

“`

Explanation:

  • settings.blocks."block-name": This targets a specific block.
  • Setting a property to false (e.g., "color": false) completely hides that control from the block’s sidebar in the Site Editor.
  • For example, for core/image, we’ve disabled color, spacing, and layout options entirely. This might be useful if you want images to strictly adhere to your theme’s defined styles and not have their colors or spacing altered manually.
  • For core/button, we’ve enabled specific color controls (text and background) and font size controls, while leaving other potential controls (like border radius, which isn’t explicitly listed here, would default to its standard behavior or be disabled if color: false was applied).

Practical Tip: Think about the core purpose of each block. If a block is meant to be very simple, disable its less important settings to avoid overwhelming users. For more complex blocks, enable the features you want users to have access to.

Setting Default Block Values

You can also set default values for specific properties of blocks. This ensures that when a user inserts a block, it already comes with your preferred styling.

“`json

{

“styles”: {

“blocks”: {

“core/heading”: {

“typography”: {

“fontFamily”: “var(–wp–preset–font-family–inter)”,

“fontSize”: “var(–wp–preset–font-size–medium)”

},

“color”: {

“text”: “var(–wp–preset–color–primary-dark-blue)”

}

},

“core/paragraph”: {

“typography”: {

“fontFamily”: “var(–wp–preset–font-family–system-default)”,

“fontSize”: “var(–wp–preset–font-size–base)”

},

“color”: {

“text”: “var(–wp–preset–color–text-dark-gray)”

}

},

“core/columns”: {

“spacing”: {

“padding”: “var(–wp–preset–spacing–large)”

}

}

}

}

}

“`

Explanation:

  • styles.blocks."block-name": As before, we target specific blocks.
  • By defining properties like fontFamily, fontSize, color, and spacing, you’re setting the default state of these blocks when they are first added to a page or post.
  • For headings, we’re using our defined “Inter” font and “Medium” size, with the “Primary (Dark Blue)” color.
  • For paragraphs, we’re using the “System Default” font and “Base” size, with the “Text (Dark Gray)” color.

Practical Tip: This is where you really bake in your theme’s identity. Ensure that default headings, paragraphs, and other common structural blocks look exactly how you intend them to. This saves considerable time in design and ensures consistency.

If you’re interested in enhancing your understanding of WordPress theme development, you might find the article on building a block theme with theme.json particularly useful, as it covers essential aspects like typography, color palettes, and spacing scales. To further explore related topics and get in touch for more insights, you can visit this page for additional resources and support.

Putting It All Together: Best Practices and Next Steps

Building a block theme with theme.json is an iterative process. You’ll likely find yourself tweaking and refining your settings as you go. Here are some best practices to keep in mind and a few pointers for what to do next.

Develop Iteratively

Don’t try to get everything perfect in one go.

  1. Start with the basics: Define your core typography, color palette, and spacing scale first.
  2. Apply globally: Set foundational styles for body, elements, and major blocks like core/post-content, core/heading, core/paragraph.
  3. Refine block by block: As you build out your templates and pages, identify any blocks that need specific styling or feature adjustments and update your theme.json accordingly.
  4. Test, test, test: View your site on different devices and browsers. Use the Site Editor to see how the controls behave.

Use Semantic Naming

For your name and slug properties in settings, use clear and descriptive names. This makes your theme.json file easier to understand and maintain. Good names help you and other developers quickly grasp the purpose of each setting.

  • Instead of color: #000000, name: Black, use color: #000000, name: Text (Black), slug: text-black.
  • For spacing, size: 1rem, name: Medium is good, but size: 1rem, name: Standard Padding, slug: standard-padding might be even more descriptive if that’s its primary use.

Leverage CSS Variables

As we saw, WordPress automatically creates CSS variables from your theme.json settings. Always use these variables (var(--wp--preset--...)) when applying styles. This ensures that any changes made in theme.json are automatically reflected everywhere those variables are used.

Consider User Experience

Your goal with theme.json is to create a powerful yet user-friendly editing experience.

  • Limit Customization Wisely: While custom: true for colors or customSpacingScale: true offers flexibility, too much freedom can lead to design inconsistencies. Strike a balance between providing options and guiding users toward a cohesive look.
  • Clear Labels: Ensure your name properties are understandable to someone who might not be a developer.

Next Steps

  1. Explore the Site Editor: Spend time in the WordPress Site Editor. Add blocks, change settings, and see how your theme.json changes affect the interface. This is the best way to understand how users will interact with your theme.
  2. Look at Core Themes: Examine the theme.json files of core WordPress block themes (like Twenty Twenty-Two, Twenty Twenty-Three, etc.). This is an excellent way to learn best practices and see how they implement their styling.
  3. Add More Blocks and Settings: As you become more comfortable, start defining settings for more blocks and exploring other theme.json features like layout, custom.spacing, and custom.typography.

By mastering theme.json, you’re not just building a WordPress theme; you’re crafting a robust design system that enhances both development efficiency and the end-user experience. It’s a bit of a learning curve, but the payoff in terms of consistency, control, and maintainability is well worth the effort.