How to add responsive block styles in theme.json

For as long as there have been block themes, making a block look different on smaller screens has meant writing custom CSS with media queries, viewport-based units or functions like clamp(). Getting a better solution for this in WordPress core has been one of the most requested features since the Gutenberg plugin was first released. Now, we finally have it thanks to WordPress 7.1. With it installed, blocks support responsive styles for tablet and mobile, both in the editor and in theme.json.

In this tutorial, we’re going to take a look at how you can add responsive styles to blocks in your block theme’s theme.jsonfile – for example, to modify the padding of a Group block or the size and weight of headings on mobile.

Adding responsive styles to a block

You’ll find theme.json in the root folder of your theme. It’s where most of a block theme’s style and layout settings live. Open it in a code editor, either on your computer or over SFTP on your server. If you’re working on a theme you didn’t build yourself, make the changes in a child theme instead. Otherwise, they might be overwritten the next time you install an update to the theme, and speaking as someone who receives a lot of support requests from people who have done that, it’s best avoided.

Responsive styles go in the same place as your other block styles: styles.blocks in theme.json. Next to a block’s regular styles, we can add two new keys – @tablet and @mobile – and nest the styles that should apply on those screen sizes inside them.

Let’s say our theme gives Group blocks generous padding, which looks great on desktop but takes up too much space on a phone. Here’s how we can reduce it on smaller screens:

{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"styles": {
"blocks": {
"core/group": {
"spacing": {
"padding": {
"top": "64px",
"right": "64px",
"bottom": "64px",
"left": "64px"
}
},
"@tablet": {
"spacing": {
"padding": {
"right": "40px",
"left": "40px"
}
}
},
"@mobile": {
"spacing": {
"padding": {
"top": "32px",
"right": "20px",
"bottom": "32px",
"left": "20px"
}
}
}
}
}
}
}

Inside @tablet and @mobile, we use the exact same structure as the regular styles. WordPress takes care of turning it into CSS with the right media queries, both on the front end and in the editor.

This works with all the styles that blocks support, like typography, color, background, border, dimensions, spacing and layout. The theme.json file is set to version 3 in this example, but the responsive styles work with version 2 of theme.json as well.

By default, the mobile styles apply at 480px and below, and the tablet styles between 480px and 782px. If those breakpoints don’t match the rest of your theme, you can change them with the new settings.viewport property in theme.json. It’s a single setting for the whole theme, so the breakpoints can’t be changed per block as of WordPress 7.1:

"settings": {
"viewport": {
"mobile": "600px",
"tablet": "1000px"
}
}

Changing headings on mobile

The same approach works for any block. Here’s how we can make the Heading block both smaller and bolder on mobile. Font size could be handled with viewport-based units or clamp(), but font weight is a lot trickier – it takes some fairly obscure CSS math to tie it to the screen size. With responsive styles, it’s just another property. Add this to styles.blocks, next to the Group block:

"core/heading": {
"typography": {
"fontSize": "48px",
"fontWeight": "600"
},
"@mobile": {
"typography": {
"fontSize": "32px",
"fontWeight": "700"
}
}
}

I’m usually not a fan of switching weights between screen sizes, but headings set smaller sometimes benefit from a little extra weight to hold their own on a phone.

How the styles cascade

The regular styles are the base, and they apply on every screen size unless a viewport key overrides them. That means you only need to add the styles that should change.

There’s one thing to look out for, though. The tablet and mobile styles don’t build on each other: @tablet only applies between the mobile and tablet breakpoints, and @mobile only applies below the mobile breakpoint. If you want a value to apply on both tablets and phones, add it to both keys. A value you’ve only set in @tablet won’t carry over to mobile, which will fall back to the regular styles instead. I’m not a big fan of this, but maybe it’s a lack of imagination on my part after twenty-five years writing cascading style sheets.

Checking that it works

Save theme.json and open the Site Editor. Click the device preview button with the laptop icon in the top toolbar and switch the preview to “Tablet” or “Mobile”, and the styles should update to match your changes in theme.json. You can also modify the styles in the editor at this breakpoint by checking “Responsive styles” in the same menu. Just remember to uncheck it once you’re done making breakpoint-specific changes.

Verify that your changes have taken effect by resizing your browser window on the front end, and you’re all done.