Block Theme Development, Part 2: Page Templates and Custom Styles

A web designer at a standing desk

In the first part of this block theme exploration, I looked at getting started with block theme development using the Create Block Theme plugin. This post picks up where we left off, focusing on building out page templates, enabling custom functionality through functions.php, and making custom style adjustments that can’t quite be handled in the site editor styles.

Setting up page template structure

Reviewing my template needs, the site requires two main page templates: one with a featured image and page title hero pattern and another for special pages like the homepage. Custom archive views are also necessary for specific category archive views and custom post types. I will need a single view for some of those with the ability to include custom blocks and ACF content.

The parent theme I’m using (Greyd) has with two basic templates for page content: “Pages” (the default) and “Page with Title.” But, because the default “Pages” template doesn’t have a page title at all, I needed to swap how these templates function.

Note: Your page title is an H1

Example of the title block showing the H1 setting

When I added the title block to my page template in the previous post, I noticed it was an H2. That’s appropriate for post titles in loops, but for the main page title, it needs to be an H1 for proper heading hierarchy and accessibility. The fix was straightforward in the block editor. Opening up my page template, I selected the Post Title block and changed the heading level to H1 in the block settings.

There should only ever be one H1 heading on your page and this should be your page title. Headings do have a minor SEO value but their semantic function is more important: headings help organize your content and your H1 heading describes the main content on your page. Don’t use more than one H1 per page (even if everyone else is doing it).

Learning something new about spacing and layout behavior

Watch me learn something new – exploring block spacing settings.

Spacing in block themes can be confusing because there are multiple systems working simultaneously:

  • Block padding and margin: can be applied to individual blocks
  • Block spacing: controls the gap between blocks within a group
  • Layout spacing: a global settings that describes how inner blocks are spaced within a group or container

Go with the flow…

Working in the editor, I want to try to exert the least amount of control and get it to do the thing because it just feels more stable that way. If I have to futz around with design elements, that just becomes tedious.

Me

With block-level dimension settings, we can add all kinds of margin and padding and spacer blocks (still!) to effect a specific layout. However, I see a lot of developers and clients get stuck over-engineering a design solution. If you feel like you are fighting with block styles, take a deep breath and consider how flex and grid containers want to operate. Rather than applying lots of manual margin or padding adjustments to force a specific result, maybe you need to try a different block, or inspect the front-end to understand what is actually happening. Manual block-by-block adjustments are less maintainable and much more tedious to create.

To better understand spacing in WordPress, we can first take a look at the CSS Box Model. This describes how browsers will calculate space around every HTML element. Each element is in a “box” with four layers (from inside to outside). This is a conceptual box, not a visible box, but if you inspect your code you will see how margin, padding and gap spacing are highlighted within a “boxed” element or layout.

  1. Content – the actual content inside your element box (EX: this could be a paragraph, heading, image, or a group)
  2. Padding – space between the content and the edge of the box
  3. Margin – space outside the border that separates this element from others
  4. Gap spacing – the CSS gap property creates space between flex or grid elements

How spacing works in WordPress:

  • Padding expands the element itself (background colors and borders extend through the padding area)
  • Margin creates empty space between elements (background colors and borders do not extend into margin)
  • TIL– Block spacing in WordPress is not exactly the same as gap spacing. Block spacing adds space between child elements within a flex or grid container (gap spacing) AS WELL AS adding an equal amount of margin to the top of any default block-level elements inside the container (like a paragraph block).
    • If a container is display: flex; – like the Columns block – the block spacing control changes the default gap spacing between columns.
    • If an element is display: block; – like a paragraph – it will get the same amount of spacing as margin-block-start: var(--wp-preset-spacing-value); since gap won’t affect elements that aren’t using flex or grid.

Block spacing controls are also available to the theme in the site editor under layout settings. The block spacing setting here will determine the space between all of the blocks on all of your templates across the site.

In WordPress blocks, we’re manipulating these properties through the visual “dimensions” settings panel. Padding and margin affect the space inside and outside a box (or block), respectively. Block spacing affects the gaps between elements within that group or container block (group, columns, grid, cover block) and the margin-block-start for elements within those containers.

Thinking about it now, this does seem the most logical way to handle space equity among things that may have a different display modes – but it was not immediately obvious to me. I’m sure its documented, one of my fatal flaws is that I never read instructions first.

Learn more about spacing settings:

Adding breadcrumbs to the header

Breadcrumbs are added to templates using the Yoast Breadcrumb Block.

Looking at the current site design, I decided to add breadcrumbs to the Page Title Hero pattern rather than above the page content as it is on the current site. I’m using Yoast Breadcrumbs here but there are other plugins that can do this like SEOPress. The Yoast Breadcrumb block does not have any style options available in the editor so I will need to add some custom styles to a separate stylesheet or in the Advanced CSS panel.

I also want the breadcrumbs to left-align with other header elements, using the wide alignment shared by the navigation menu. This involves working with flex containers and understanding how the cover block centers its content. The cover block is a flex container that aligns items center by default. This was overriding my attempts to space elements using justify-content: space-between.

Adjusting the position of elements inside a cover block using custom css.

After experimenting with height settings and flex properties, I realized I needed to add a custom class to override the default align-items center property. Sometimes blocks can get you most of the way there, but for specific design requirements, you may still need to add custom CSS.

Learn about flex properties: CSS Flexbox Layout Guide

Enabling page excerpts with a function

The design calls for an optional excerpt to appear below the page title in the hero pattern. WordPress doesn’t enable excerpts for pages by default, so I needed to add this functionality.

There’s no functions.php file included by default in my child theme but I can add one. I just need a basic file to add excerpt support for pages:

add_action('after_setup_theme', function() {
    add_post_type_support('page', 'excerpt');
});

After adding this code and reloading the editor, I am able to add excerpts to pages through the page settings panel. I can also use the excerpt block on the Pages template and adjust the visual style in the editor. But – what if a page doesn’t have an excerpt?

Function tweak: conditional excerpt display

Having the excerpt field available was only half the solution. I wanted the excerpt to display only if it had been manually created, not auto-generated from page content. The excerpt block doesn’t have a built-in conditional setting for this.

**
 * Enable excerpt for pages - Only show excerpt if manually created
 */
function themename_block_filter_excerpt( $excerpt ) {
	if ( ! has_excerpt() ) {
		return '';
	}
	return $excerpt;
}
add_filter( 'get_the_excerpt', 'themename_block_filter_excerpt' );

I asked Claude.ai for an assist. Initially, it produced an overly complex solution involving PHP template files, which would defeat the purpose of building a block theme. The second option it provided was much simpler: adding a filter to the excerpt content that returns an empty string if no manual excerpt exists.

The code checks if there’s content in the excerpt field, and only outputs it if content exists. This allows the excerpt to remain an optional element in the page template.

Working with custom CSS in block themes

For my next design challenge, I wanted to add a drop shadow to my page title. Since this is text over an image, I want to make sure it’s legible and has good contrast. WordPress has shadow support, but it applies box-shadow (to a block container) not text-shadow. My first instinct was to add this to the style.css file referenced in functions.php but that’s like sledge hammer when I just need a small, block-specific style, say, a tack hammer for this operation.

A great article to understand using styles in the editor on CSS Tricks.

In the site editor, each block has an “Advanced > Additional CSS” field where you can add properties directly. Instead of writing a full selector in an external stylesheet, you just add the property and value:

text-shadow: 0 2px 7px rgba(0,0,0,0.5);

This approach is cleaner for one-off block styles. It keeps the styling close to the block it affects and previews immediately in the editor. Save the external stylesheet for the things that you can’t do in the editor at all.

Wrapping Up

This phase of development involved a lot of problem-solving around layout and spacing. Working with a classic theme migration with existing content and styles is a lot more complicated than I had anticipated…

Key lessons from this session:

Block themes offer flexibility through the visual interface, but there will still be times you need to reach for functions.php and custom CSS for specific functionality and fine-tuned control.

  • Functions.php in block themes should be minimal and focused on functionality you can’t achieve through theme.json or the block interface.
  • Block-level custom CSS is often preferable to external stylesheets for one-off “utility” styles.
  • Visual interfaces are powerful but have limitations. Understanding when to use theme.json, functions.php, and custom CSS is all part of the fun!

I’ll try to get back to the archive templates and custom post types next. Since these use a lot of custom fields – I may need to convert these to ACF field groups to blocks that can be used in the editor.

About the author