In The Lab: Building a Custom Hero Block
Today we kick-off an ongoing series of posts called “In The Lab“. These are going to be fun playground posts where we build cool things with Block Lab. 🙂
For the inaugural post of the series, we’re going to build a custom Hero Block. It’s going to be nice and simple and follow the typical design patterns you expect from the Hero section of a page. There will be a couple of extra controls that let you change the styling of the block, but nothing over-the-top.
To see an example of what this custom block will be able to do, here are 4 examples.

So take note of some features of this custom block.
- Background Image
- Background Colour
- Heading & Text
- 2 x Buttons
- Left, Center, and Right alignment of the block content
- Different heading font sizes
- Light & Dark text
With this kind of block, it would make it pretty easy to beautify the first section of any of your pages.
So, before we get in to the step-by-step, here is our setup. Fresh WordPress install (v5.03). Block Lab plugin installed and active (v1.1.2). Atomic Blocks child theme installed and active.
We’re using the Atomic Blocks theme for 2 reasons.
- It’s great!
- It has a great blank “page builder” page template that works as a good blank canvas for working with a Hero kind of block.
Ok, let’s do this! By the end of this tutorial, this is what we will have built.

Step 1: Adding and Configuring the Block
- In the WordPress Admin, got to
Block Lab > Add New
- Give your new block the title
Hero
- Keep the automatically generated slug.
- Choose an icon, set a category, and add some tags.
Step 1 complete. Nice!

Step 2: Adding Fields
Ok, these are the fields we’re going to add.
Field Label | Field Type | Field Location |
Heading | Text | Editor |
Text | Textarea | Editor |
Button 1 Text | Text | Editor |
Button 1 URL | URL | Editor |
Button 2 Text | Text | Editor |
Button 2 URL | URL | Editor |
Background Color | Color | Editor |
Background Image | Text | Editor |
Background Darken | Range | Inspector |
Text Color | Select | Inspector |
Heading Size | Range | Inspector |
Orientation | Select | Inspector |
In the admin, they will look like this:

Take note of the field locations. Rule-of-thumb is that content fields belong in the editor and settings/configuration fields belong in the inspector.
For our background image field, we’re using a Text field. A Media field is coming to the plugin very soon, which would actually be used here. In the meantime, we just paste an image’s URL in to a Text field.
Add all these fields to your block, and hit Publish.
Step 3: Building the Block Template
Time to open a text editor. I use VSCode, but there are plenty you can choose from.
In our Block Building screen in the WP Admin, you’ll see over on the right that the plugin is looking for the block template file for your new block. As we’ve only just added it, it’s telling us it can’t find it. Helpfully it’s also telling us exactly what it’s looking for.
Copy the file block-hero.php
Add a folder called blocks
.
In this new folder, add a new file and paste in block-hero.php
as its file name. Hit save.
Switch back to our block editor in WP Admin and hit refresh just to make sure it’s picking up the new file.
Success!

Now, we build the template. We’re going to write some simple CSS, HTML, and PHP in our template file. There are other ways to do this, including building a preview template file for the block, but for simplicity’s
We’ll have 2 sections in our file. CSS at the top, and HTML and PHP at the bottom.
Let’s stub out the HTML for our block. The structure will include
- a
section
to wrap the whole block - a
div
to use as our background darkening overlay - a container
div
to contain our content within the max content width of the site - a wrapper
div
to position the content of the block - and our Hero content
<section class="block-hero">
<div class="block-hero_background-darken">
<div class="block-hero_container">
<div class="block-hero_wrapper">
<h1 class="block-hero_heading"></h1>
<p class="block-hero_text"></p>
<div>
<a class="block-hero_button-1"></a>
<a class="block-hero_button-2"></a>
</div>
</div>
</div>
</div>
</section>
I’ve also added CSS classes to each HTML element.
Next step is to add the content of our block using Block Lab’s available functions. With block_field
block_value
Our block template file now looks like this.
<section class="block-hero">
<div class="block-hero_background-darken">
<div class="block-hero_container">
<div class="block-hero_wrapper">
<h1 class="block-hero_heading"><?php block_field( 'heading'); ?></h1>
<p class="block-hero_text"><?php block_field( 'text'); ?></p>
<div>
<a class="block-hero_button-1" href="<?php block_field( 'button-1-url'); ?>"><?php block_field( 'button-1-text'); ?></a>
<a class="block-hero_button-2" href="<?php block_field( 'button-2-url'); ?>"><?php block_field( 'button-2-text'); ?></a>
</div>
</div>
</div>
</div>
</section>
By using the block_field
function, we echo out the value stored in the database in that particular field.
Let’s take a quick stock-take of what we have. We should now actually be able to add our custom block in a new post or page in WordPress, add in content, and have it work in both the editor and frontend.
So, in the WordPress admin, go to Pages > Add New. Now add a new block and look for our “Hero” block. Add it to the page and fill in the fields.

Now click away from the block to see the preview in the editor.

And then click the preview button to view on the front end.

Hey presto. We have a functioning custom block. Now to make it pretty and customisable.
We’re going to add our CSS to the block template itself to keep it simple. Alternate and
So our CSS looks like this:
<style>
.block-hero {
background-size: cover;
}
.block-hero_container {
max-width: 1080px;
margin: auto;
display: flex;
min-height: 90vh;
align-items: center;
justify-content: space-between;
padding: 40px 20px;
}
.block-hero_wrapper {
max-width: 600px;
}
.block-hero_heading {
color: #fff;
}
.block-hero_text {
color: #fff;
margin-bottom: 40px;
}
.block-hero_button-1,
.block-hero_button-2 {
display: inline-block;
padding: 8px 24px;
border-radius: 0;
border: solid #fff 2px;
background-color: transparent;
color: #fff;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 10px
}
.block-hero_button-1 {
margin-right: 10px;
background-color: #fff;
color: inherit;
}
</style>
Our CSS is fairly simple. It’s mostly about giving the Hero section the proper amount of space and alignment on the page. The buttons also get a bit of attention to make sure they actually look like buttons (we’re using anchor tags) and work well against the background images or
Additionally we’re going to add some in-line CSS to section.block-hero
to pull in the background image and background color. So that particular line now looks like
<section class="block-hero" style="background-image: url('<?php block_field( 'background-image'); ?>'); background-color: <?php block_field( 'background-color' ) ?>;">
With this styling, we have basically completed the block! With the image added to the background field, this is what we see.

This here is looking really good. We could finish right here if we wanted.
However, let’s add some block settings that let the user tweak the block to make it better suit their case-by-case needs.
So the block fields we added earlier that will handle the settings are:
- background-darken – This lets the user darken the background image to improve contrast with overlaid text
- heading-size – This lets the user increase the text-size of the heading
- text-color – This lets the user select between light and dark text based on the image or color they have in the
backgroun - orientation – This lets the user select between left, right, and center orientations for the block content
We will be writing some basic PHP to handle these. Our code looks like:
<?php
$background_alpha = block_value( 'background-darken') / 100;
$heading_size = block_value( 'heading-size') / 10 + 2;
$orientation = block_value( 'orientation' );
$text_color = block_value( 'text-color' );
if ( $text_color == 'dark' ) {
$font_color = '#272c30';
} else {
$font_color = "#fff";
}
if ( $orientation == 'left' ) {
$justify_content = 'flex-start';
} elseif ( $orientation == 'center' ) {
$justify_content = 'center';
} else {
$justify_content = 'flex-end';
}
?>
So depending on the values input in to our block in the editor, we are given different values we use within our CSS. Our updated HTML/PHP part of the template now looks like:
<section class="block-hero" style="background-image: url('<?php block_field( 'background-image'); ?>'); background-color: <?php block_field( 'background-color' ) ?>;">
<div class="block-hero_background-darken" style="background-color: rgba(0,0,0, <?php echo $background_alpha ?>);">
<div class="block-hero_container" style="justify-content: <?php echo $justify_content; ?>">
<div class="block-hero_wrapper" style="text-align:<?php echo $orientation; ?>">
<h1 class="block-hero_heading" style="font-size: <?php echo $heading_size; ?>em; color:<?php echo $font_color; ?>"><?php block_field( 'heading');?></h1>
<p class="block-hero_text" style="color:<?php echo $font_color; ?>"><?php block_field( 'text'); ?></p>
<div>
<a class="block-hero_button-1" href="<?php block_field( 'button-1-url'); ?>"><?php block_field( 'button-1-text'); ?></a>
<a class="block-hero_button-2" style="color:<?php echo $font_color; ?>" href="<?php block_field( 'button-2-url'); ?>"><?php block_field( 'button-2-text'); ?></a>
</div>
</div>
</div>
</div>
</section>
With this in place, we can go to our page and edit the block. For our cycling block, we will
- Darken the background slightly
- Switch the text colour to light
- Increase the heading size a bit
- Set the orientation to center
And now, without further ado. Here is our block.

And with just changing the content and tweaking the settings, you can create more hero sections on any page or post as diverse as these. 🙂

Our final template file, with all our styling and templating looks like:
<style>
.block-hero {
background-size: cover;
}
.block-hero_container {
max-width: 1080px;
margin: auto;
display: flex;
min-height: 90vh;
align-items: center;
justify-content: space-between;
padding: 40px 20px;
}
.block-hero_wrapper {
max-width: 600px;
}
.block-hero_heading {
color: #fff;
}
.block-hero_heading:after {
color: #fff;
}
.block-hero_text {
color: #fff;
margin-bottom: 40px;
}
.block-hero_button-1,
.block-hero_button-2 {
display: inline-block;
background-color: #fff;
padding: 8px 24px;
border-radius: 3px;
color: #333;
border-radius: 0;
border: solid #fff 2px;
background-color: transparent;
color: #fff;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 10px
}
.block-hero_button-1 {
margin-right: 10px;
background-color: #fff;
color: inherit;
}
</style>
<?php
$background_alpha = block_value( 'background-darken') / 100;
$heading_size = block_value( 'heading-size') / 10 + 2;
$orientation = block_value( 'orientation' );
$text_color = block_value( 'text-color' );
if ( $text_color == 'dark' ) {
$font_color = '#272c30';
} else {
$font_color = "#fff";
}
if ( $orientation == 'left' ) {
$justify_content = 'flex-start';
} elseif ( $orientation == 'center' ) {
$justify_content = 'center';
} else {
$justify_content = 'flex-end';
}
?>
<section class="block-hero" style="background-image: url('<?php block_field( 'background-image'); ?>'); background-color: <?php block_field( 'background-color' ) ?>;">
<div class="block-hero_background-darken" style="background-color: rgba(0,0,0, <?php echo $background_alpha ?>);">
<div class="block-hero_container" style="justify-content: <?php echo $justify_content; ?>">
<div class="block-hero_wrapper" style="text-align:<?php echo $orientation; ?>">
<h1 class="block-hero_heading" style="font-size: <?php echo $heading_size; ?>em; color:<?php echo $font_color; ?>"><?php block_field( 'heading');?></h1>
<p class="block-hero_text" style="color:<?php echo $font_color; ?>"><?php block_field( 'text'); ?></p>
<div>
<a class="block-hero_button-1" href="<?php block_field( 'button-1-url'); ?>"><?php block_field( 'button-1-text'); ?></a>
<a class="block-hero_button-2" style="color:<?php echo $font_color; ?>" href="<?php block_field( 'button-2-url'); ?>"><?php block_field( 'button-2-text'); ?></a>
</div>
</div>
</div>
</div>
</section>
I really hope you’ve found this tutorial interesting and helpful. If you have any ideas of what you’d like to see in future ones, please let me know in the comments below.
Happy block building. 🙂