Gutenberg Theme Development

I have built many websites using WordPress’ new block-based editor, code-named Gutenberg.

I’ll walk you through the technical details you need as a WordPress developer building a Gutenberg website. I’ll then share how we approach these projects and provide some real-world examples.

Building a Gutenberg theme

For the most part, a Gutenberg-optimized theme is just like any other WordPress theme. Your current WordPress theme will likely work great with Gutenberg.

Wide/Full Alignment

add_theme_support( 'align-wide' );

This adds “wide” and “full” options to the left, right, and center alignment options. This will be used primarily for images, but other blocks also support these alignment options.

You’ll need to add CSS to your theme for these alignment options to actually work, in the same way you have to style .alignleft for left-aligned images to work.

Editor Font Sizes

When editing paragraph text, a user can select different sizes in the settings panel on the right. This lets you define what sizes should be available.

// -- Disable custom font sizes
add_theme_support( 'disable-custom-font-sizes' );

// -- Editor Font Sizes
add_theme_support( 'editor-font-sizes', array(
		'name'      => __( 'Small', 'ea_genesis_child' ),
		'shortName' => __( 'S', 'ea_genesis_child' ),
		'size'      => 12,
		'slug'      => 'small'
		'name'      => __( 'Normal', 'ea_genesis_child' ),
		'shortName' => __( 'M', 'ea_genesis_child' ),
		'size'      => 16,
		'slug'      => 'normal'
		'name'      => __( 'Large', 'ea_genesis_child' ),
		'shortName' => __( 'L', 'ea_genesis_child' ),
		'size'      => 20,
		'slug'      => 'large'
) );

You’ll also have to add CSS to your theme for this to work. Rather than hardcoding the font size on the paragraphs, Gutenberg adds a CSS class like .has-small-font-size. This helps keep the content separate from the styling and will simplify redesigns in the future.

Theme Colors

// -- Disable Custom Colors
add_theme_support( 'disable-custom-colors' );

// -- Editor Color Palette
add_theme_support( 'editor-color-palette', array(
		'name'  => __( 'Blue', 'ea_genesis_child' ),
		'slug'  => 'blue',
		'color'	=> '#59BACC',
		'name'  => __( 'Green', 'ea_genesis_child' ),
		'slug'  => 'green',
		'color' => '#58AD69',
) );

Gutenberg includes a color picker in certain blocks like paragraph and button. Rather than letting clients pick any color they want, we disable the color picker and define a few brand colors.

Like all the other theme options, these require additional CSS to function properly. When a block has the “Background Color” set to one of your theme colors, it adds a class of .has-{color}-background-color. Likewise, when the “Text Color” is set, it adds a class of .has-{color}-color.

Block Style Options

Each block type can have multiple style options. For instance, the Quote block comes with “Regular” and “Large” styles, while the Button block comes with “Round”, “Square”, and “Outline” styles.

You can add your own block styles using registerBlockStyle, and you can remove existing style options using unregisterBlockStyle.


I can’t imagine building a Gutenberg theme without SASS. You need to generate a frontend stylesheet and editor stylesheet, both with differing amounts of CSS.

For the Theme Colors feature described above, we use SASS loops to build the styles (see here).

Editor Styles

If your theme has defined editor styles, these are not automatically be loaded into Gutenberg, but you can turn it on with add_theme_support(). They will be prefixed with the correct CSS classes to target only the editor.

// Editor Styles
add_theme_support( 'editor-styles' );
add_editor_style( 'assets/css/editor-style.css' );

Alternatively, you can load a separate stylesheet using the enqueue_block_editor_assets hook, but you will need to prefix your CSS yourself so it only applies to the editor (not the WP backend menu, metaboxes…).

Do not load your entire frontend stylesheet in Gutenberg. You should only load styles relevant to the editor. In my editor-style partial, I only load my base, block-specific, and editor-specific styles.

Set block width in Gutenberg

Gutenberg already has some base styling applied to blocks, but their max-width doesn’t match the max-width we are using on the site. We use the following in a _gutenberg.scss partial to update the size of normal, wide, and full width blocks in the Gutenberg editor. $content-width is a SASS variable we have defined in _base.scss.

These styles should match your frontend styles. I’ve also added styles for customizing the post title.

/* Post title width */
.editor-post-title__block.wp-block {
	max-width: $content-width;

	/* Post title styling */
	.editor-post-title__input {

/* Main column width */
.wp-block {
    max-width: $content-width;

	/* Wide column width */
	&[data-align="wide"] {
		max-width: none;

		@include media(">=medium") {
			max-width: none;
			margin-left: calc(25vw - 25%);
			margin-right: calc(25vw - 25%);

	/* Full column width */
	&[data-align="full"] {
		max-width: none;

Creating block templates

You can simplify the writing experience by pre-populating the editor with a set of default blocks.

You can even customize what appears in each block by default. We used this on an attorney’s website so all case summaries had the same overall structure.

You can decide how strict you want to make the template. You can lock it completely (no new blocks, can’t remove/reorder existing blocks), lock insertions (no new blocks, but current blocks can be re-ordered), or have no locks and used the template as a starting guide.

Building Custom Blocks

The biggest question most theme developers will have is “Should I build my custom blocks from scratch in JavaScript, or use a plugin like Advanced Custom Fields?”

I think metaboxes make a great analogy. When I’m building a custom plugin that will be distributed and used by many, like Genesis Title Toggle, I build my metabox from scratch. This removes a plugin dependency (ACF) or a bundled library (CMB2) and keeps the plugin lean.

When I’m building a bunch of metaboxes for a specific client’s site, it’s better to leverage an existing tool like Advanced Custom Fields, Carbon Fields, or CMB2. I’m able to provide a higher quality result much faster than if I were to build everything from scratch.

I use the same approach to Gutenberg blocks. For client sites, I’m building my custom blocks with Advanced Custom Fields. When I release a public plugin that includes a block, it will be built from scratch.

More Tutorials

Here are some great Gutenberg-related tutorials from around the web:

Types of Gutenberg websites

There are really two types of Gutenberg websites: simple and custom.

Simple Gutenberg Websites

Gutenberg is a huge step forward for simple content sites. Clients can easily build beautiful and engaging pages of content with the core blocks. The theme development process for these sites is mostly CSS. We ensure the core blocks look great, match the client’s brand, and can address all their content requirements.

This is perfect for non-profits who need a low-cost, high-impact website. We used this approach for CARAS and College Discount Cards.

We start by designing a style guide featuring all the core blocks. Our designer then works with the client to mock up the key pages using these blocks. Once the designs are approved, I style the blocks and build the pages like legos.

Custom Gutenberg Websites

These sites follow our traditional web development process. Rather than letting the technology constrain our design and functionality, we first examine the client’s specific needs and document the desired features and user experience. We then design the user interface, mockup all the blocks (both core and custom), and mockup the page layouts necessary to build the site.

In addition to styling the core blocks, we build custom blocks to implement features not currently in core. The above example of Free Together includes a “Table of Contents” block that dynamically lists and links to each heading in the article.

On RCP we built many custom blocks including a Feature Box, Icon Links, and Downloads.

Is Gutenberg the right choice?

You have to consider the value proposition for each project. We use the block editor on all websites. If we disable Gutenberg, it’s typically on a single template.

The benefits of Gutenberg include:

  • Building a simple Gutenberg site will save us from building a more complex website that relies heavily on custom metaboxes. We can deliver a better product faster and cheaper.
  • Many websites require complex content elements that are easy to implement as custom blocks but difficult to do with TinyMCE. For instance, the RCP project required 9 custom blocks. Before Gutenberg, these would be a mix of shortcodes with Shortcode UI, custom TinyMCE plugins, and metaboxes.
  • We’d rather future-proof our projects by using the new editor rather than locking clients into outdated technology.

Here’s the “Feature Box” block we built on RCP. This is a great example of how Gutenberg can make content creation easier. Something like this would be difficult and complicated to insert in TinyMCE. See my article on Building Gutenberg blocks with ACF for more examples.

Frontend / Backend Preview
Backend Edit

Gutenberg is not a page builder

Gutenberg is a block-based content editor, not a page builder. It’s hard to describe, but it will become more clear as you use it in the real world.

While the columns block does allow you to nest blocks inside of blocks, it’s fairly primitive and difficult to set up. The editing experience can be painful and you’ll need custom CSS to make it mobile responsive. It works for simple sites, but is not a replacement for true page builders like Beaver Builder or flexible content areas.

We use Gutenberg for most content pages on the site; it replaces a lot of custom page templates we would have developed previously. But for visually complex pages like the homepage and landing pages, sometimes we will disable Gutenberg for those templates and build a true page builder with Carbon Fields or Advanced Custom Fields.

It’s not that Gutenberg can’t be used for complex pages, it just might not be the easiest interface to use in those instances. As Gutenberg becomes more powerful, this will become less of an issue.

My website – including the homepage – is built completely with Gutenberg. It can be done.

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson


  1. David says

    Great post, Bill. Thanks for sharing. Just did my first theme with Gutenberg this week, looking forward to seeing this software evolve.

  2. Damien Carbery says

    Custom blocks with ACF looks great and seems to greatly simplify the process. The downside is having to install ACF again – as you’ve written previously, ACF is slow. I moved a number of sites to CMB2 so it’ll feel like a backwards move.

    • Bill Erickson says

      I’ve been told ACF has fixed most of its performance issues, but this is my first time using it in years so I haven’t tested it for myself. I’d like to do some performance testing at some point to compare it to other solutions.

      Carbon Fields, my preferred metabox solution (see here), will have block support soon. I’m sure there will be more block building plugins over the next year or two as Gutenberg matures.

  3. Mike England says


    I agree with a lot of your points about things to be aware about when building a site with Gutenberg. I’ve built two now, and have learned quiet a bit each time. I had a question and just wanted to get some feedback and idea share.

    When it comes to spacing out the content area, I came up with a unique way to make spacing for the content area to allow for centered, wide width, and full width without sacrificing the wrapper padding. For example if my content container has padding: 0 4em and I apply margin-left: -4em; margin-right -4em; to my full width class it does align as expected and works well on devices. It seems to work very with especially when combined with Sass.

    Just wanted to share this in case it’s helpful for someone else. What are your thoughts on this idea? I can share an example site with you if you like.

    • Bill Erickson says

      Yes, that would definitely work. But it sounds like you are still not setting a max-width on the content area, just adding additional left/right padding.

      The “wrap” I refer to is usually: .wrap { max-width: 980px; } defining the maximum width of the content area.

      If you have a fixed max-width and a variable page width (ie: you don’t know how wide the user’s browser is), it makes negative margins difficult.

      • Mike England says

        That is a good point, I typically don’t set too many max widths so it does seem to work well my style, I’ll keep that in mind for future sites where max-widths may be used more frequently.

        Thanks for taking the time to reply. I look forward to reading more about your experiences on Gutenberg.

  4. Peninah says

    Thank you so much for sharing your Gutenberg experiences and tips! I’m really nervous about how this will all play out; having your background and opinions is very helpful.

  5. Henk van den Bor says

    Thanks so much for sharing and giving me a chance to see the code in action!

    nb. has got horizontal scrollbar on all browsers I checked.
    You did not use display:grid? For example the block with the 3 buttons would have been more simple with layout grid? Is the a specific reason you only used flex?

    • Bill Erickson says

      That’s strange. I’ve tested in a bunch of browsers and am not seeing a horizontal scrollbar. Can you identify what element is sitting off screen and causing the scrollbar?

      The styling for the columns block comes from Gutenberg itself. Gutenberg originally built it using CSS Grid, but recently rebuilt that block to use flex. I’m not sure why they rebuilt it, but that change broke all the instances of columns on this site (especially the additional grid styling I added for mobile).

      We built College Discount Cards about 6 months ago. If I were to rebuild it today, I would create a custom block using ACF for that area so I could have complete control of the styling. And yes, I’d use CSS grid for that 🙂

      Sometimes getting the core blocks to behave the way you’d like is more work than building something custom.

      • Henk van den Bor says

        Scrollbar on all browsers in WIndows10 – not on Mac!
        When I remove ‘width: auto’ from .alignfull (_style-guide.scss:340) the scrollbars disappears. (did not test further)

        Your experience with the changes is why I as a one-man band keep an eye on Gutenberg, but I do not want to use it on live sites yet, just too much work/risk. That makes your posts very valuable to me… so thanks again 🙂
        I did spend time to learn about css grid, so your confirmation that you would do it different is confirmation that I learned those lessons well 🙂 (Sofar way more excited about grid then about Gutenberg)

  6. Ibraheem says

    This is a very useful post for us devs preparing for the WP5 rollout. Thank you Bill.

    I’m curious to know what method you are using to process SASS in your setup. Are you using a plugin?

    • Bill Erickson says

      I use CodeKit for SASS and JS processing. It works great when you’re a solo developer.

      If I’m working as part of a team (rare for site development, more common for our public plugins like Shared Counts) we use Gulp to ensure consistent processing across team members.

  7. Sarah Hills says

    Thank you for sharing – in particular I was interested to read your take on building custom blocks – ACF vs from scratch. It’s something I’m grappling with currently.

    ACF somehow feels like ‘cheating’ (I think because I read somewhere that using ACF is only a temporary ‘stop-gap’ solution – which makes me nervous of using it on projects where the site could be in existence for say 5+ years). But it’s perhaps the most pragmatic approach for smaller projects. How concerned do you think we need to be that using ACF means we’re moving back away from a WYSIWYG editing experience (one of the main goals of Gutenberg)??

    I’m also scratching my head about whether it’s ok to store structured data in standard block attributes (i.e. that aren’t set to save to post meta). Take the use case of a custom post type (e.g. project) for which we create a block template with a mixture of core/custom blocks. If you then wanted to pull out a grid of ‘most recent projects’, which included e.g. a ‘client name’ attribute, is that doable? I haven’t found a way yet (although guess in theory it’s possible to parse through the whole of the CPT content) – other than setting the attribute to save to post meta ( Reading ACF’s post (, it seems their scope is limited to post content, rather than meta.

    Sorry for the long-winded ‘thinking out loud’ comment! It’s very helpful to hear from other devs working on this…

    • Bill Erickson says

      You bring up some great points.

      We’re entering the wild west of block creation right now, and I think it will take a year or two for best practices to become accepted.

      ACF is the first “block builder” plugin on the market, but it won’t be the last. I know Carbon Fields is adding block support. I expect to see more plugins that are purely block builders, rather than metabox plugins that are adding block support.

      I think these newer block builders will be more true to the goals of Gutenberg, providing a visual editor experience that closely mirrors the presentation, rather than ACF’s “data entry as a metabox” model.

      Gutenberg itself is still changing rapidly. I can’t justify building a custom block from scratch for a client right now because I don’t want to constantly refactor it over the coming months as Gutenberg itself changes.

      If you want to build a custom block right now, I think ACF is the best option. 3-6 months from now, who knows tools will be available.

      I also assume ACF will soon support saving attributes as metadata rather than in the post content. That’s really the core of what ACF is, so I’m surprised it’s not in the first beta releases.

      My bigger concern is when you’re working with other plugins that add their own blocks and you want to access their data, but they didn’t store it as meta. The Gutenberg Block Object plugin will be useful here. It stores all the blocks and their attributes as post meta. You can then access the post’s content in a more structured manner.

      As I said up in the post, I still lean towards not using Gutenberg unless we think it’s worthwhile for this project. A project with a lot of structured data would likely be a better fit for Classic Editor + Metaboxes than Gutenberg currently.

      • Sarah Hills says

        Thanks for such a comprehensive answer and sorry for the slow reply – it went off my radar for a while! I think your approach is a sensible one. Note to self that I need to stop looking for a 100% perfect solution and make a pragmatic case-by-case decision on the best approach currently available!

        Thanks for the pointer to the Gutenberg Block Object plugin too. Sounds interesting, although like you say, right now it’s probably going to make sense to stick with ACF or similar for post types/projects with lots of structured data.

        Appreciate you sharing your thoughts.

  8. Jozek says

    Hi Bill, first, thank you for that really interesting post.
    I have a question, if you can show me the right direction.
    I’m trying to get my Summary block (table of content) to be as smooth as yours on Freetogether website.
    The automatic summary with Heading is working but it’s not smooth at all, it’s just going straight to the part, no smooth scrolling down.
    Should i do this with css or javascript?

    Thank you !

  9. Nick Meagher says

    Hey Bill,

    Thank you for such a detailed writeup on this since it’s still so new to me.

    We’ve been messing around with ACF + Gutenberg blocks on a new client project and it seems to work but we’re worried since it’s still so early and that we’re having to use a beta version of ACF to achieve this that we’ll run into issues in the future.

    You mention still using ACF + Flexible Content fields which is exactly what we’ve done in the past, is the ACF + Gutenberg approach the right choice for future-proofing our client’s websites or should we stick with the Flexible Content approach? Our fear is we’re setting up our clients with old technology if we stick with the Flexible Content structure.

    • Bill Erickson says

      We still use ACF + Flexible Content for very complex pages, typically a homepage, but about 90% of what we used to use Flexible Content for is now done with blocks. I don’t think you’re necessarily setting them up with old technology, but you do limit what can be done with those pages when you use ACF + Flexible Content.

      I try to select the tool that will ensure the site is easy for the client to manage. When a page has multiple full width sections, each with multiple columns, complex content structure, and multiple breaking points, it’s too difficult to build that in an easy to manage way with blocks. It becomes a fragile system where adding or moving a block breaks things.

      Building blocks (where they make sense) provide the client with way more flexibility.

      • I don’t have to build an entire block-based content editor for them (ie ACF + Flexible Content). I just build the specific custom blocks they need and we can leverage the built-in features of WP.
      • Features built for one page are immediately available for all others.
      • You can leverage useful core tools like Reusable Blocks with your custom blocks.

      The most important thing you can do is educate your designer to understand what’s possible with the core blocks, and what can be done easily with custom blocks. Our modular, mobile-first design approach naturally works well with blocks.