The HTML lang attribute and how to overwrite it

Since I have stopped my current project with the new theme, I am now allowing myself to blog about other topics again. This week, I want to write about an important global HTML attribute: the lang attribute.

Maybe some of you have never (actively) used this attribute, but it’s quite important. Not only does it tell a search engine, what language the content on your website is written it, it also tells an assistive technology, like a screen reader, which voice to use when reading the text. It can even be set inline for a single word or parts of a text.

The main lang attribute however is set on the <html> tag. In WordPress, this is handled by the language_attributes() function, you would usually find in a header.php file in a classic theme. In a block theme, this is handled automatically in Core.

Reasons to overwrite the lang attribute

You would usually not want to change the value of the lang attribute, since WordPress will use the correct one, based on the language setting of your website. But there are cases in which you might want to change it.

Multilingual websites

WordPress can only have one frontend language, unless you install a multilingual plugin. I use MultilingualPress, which is based on multisite. In a WordPress multisite, you can set language per sub-site. This will automatically use the correct lang attribute in each site.

If your website does not use a multilingual plugin, but you have one page with a different language, you could overwrite the lang attribute with some code.

Loading of external code

Another use-case is when you use plugins, that would use the lang attribute to load some external data. I came across a cookie banner plugin this week, which would load the text for the banner from an external resource. It would use the exact value of the lang attribute, but it expects a value like en, so only with two characters. WordPress however is using a value like en-US, which would not work for this cookie banner. So we need to strip the second part of the value.

CSS using the attribute

A good example for a use-case in CSS is the quotes property. Different languages are using different quotation marks. When you want to use the proper quotation marks in a <q> HTML tag, you usually don’t have to do anything, since the browser will handle that for you, as the value is set to quotes: auto. But if you want to overwrite this, you could do the following:

q {
	quotes: "Β«" "Β»" "β€Ή" "β€Ί";
}

This would always use quotes that are used in French and other languages, even if your lang attribute is set to en.

Some CSS libraries to use the lang attribute to change styles, but they might be doing it like this:

[lang="en"] q {
	/* Some styles */
}

This would not work, if the value is en-US for the lang attribute. There is the CSS :lang() pseudo-class that would work here:

:lang(en) {
	/* Some styles */
}

If you use en here, it would also work for en-US, en-GB, etc. But if you use en-US, it would not work for only en as well.

As the CSS from such a framework might be static, overwriting it might be a bit too complicated, so you might also want to change the value of the global lang attribute of the <html> tag.

How to change the value?

Let’s say, we want to change the value to a static other value for a specific page, you could do something like this:

function my_static_lang_attribute( $output ) {
	$object = get_queried_object();
	if ( $object && str_contains( $object->post_name, 'english' ) ) {
		return 'lang="en-US"';
	}

	return $output;
}

add_filter( 'language_attributes', 'my_static_lang_attribute' );

This would overwrite the lang attribute of any page/post with “english” in the permalink to lang="en-US" for the <html> tag.

As you can see from the function, the filter would not only return the value, but also the attribute name. If you look at the full code of the get_language_attributes function, you can see that the function may return other attributes like dir as well:

function get_language_attributes( $doctype = 'html' ) {
	$attributes = array();

	if ( function_exists( 'is_rtl' ) && is_rtl() ) {
		$attributes[] = 'dir="rtl"';
	}

	$lang = get_bloginfo( 'language' );
	if ( $lang ) {
		if ( 'text/html' === get_option( 'html_type' ) || 'html' === $doctype ) {
			$attributes[] = 'lang="' . esc_attr( $lang ) . '"';
		}

		if ( 'text/html' !== get_option( 'html_type' ) || 'xhtml' === $doctype ) {
			$attributes[] = 'xml:lang="' . esc_attr( $lang ) . '"';
		}
	}

	$output = implode( ' ', $attributes );

	/**
	 * Filters the language attributes for display in the 'html' tag.
	 *
	 * @since 2.5.0
	 * @since 4.3.0 Added the `$doctype` parameter.
	 *
	 * @param string $output A space-separated list of language attributes.
	 * @param string $doctype The type of HTML document (xhtml|html).
	 */
	return apply_filters( 'language_attributes', $output, $doctype );
}

And plugins could also hook into this filter, so overwriting the $output with something static might not work. Unfortunately, there is no filter to change the $lang value only, and hooking into get_bloginfo(), to overwrite the language might break some other places, where this code is used. If you want to strip the second part of the value, you could use some regular expression like this:

function my_dynamic_lang_attribute( $output ) {
	return preg_replace( '/lang="(\w+)([^"]+)"/', 'lang="$1"', $output );
}
add_filter( 'language_attributes', 'my_dynamic_lang_attribute' );

If you need something even more complex, it’s probably best to just overwrite the whole function.

Conclusion

The lang attribute is a very important attribute every website should always set. But the value might not always be, what you need it to be. In those cases, you have a filter you can use to overwrite its value, but always make sure not to return something invalid.

Too much custom CSS: I have to stop!

My last blog post was back in July. I was not able to keep my usual rate of a new blog post every two weeks. This had many different reasons, some personal and some regarding people I care about. But one other reason was the slow pace on getting my new theme ready enough. And today I have to say: stop!

I used the demo content I usually use to design a theme and tried to replicate every little element “as pixel perfect as possible”. But since I’m now at ~900 lines of custom CSS code, and this would prevent people from overwriting styles in the Site Editor, this approach is not going to be a good one.

How to continue with this project?

As my main goals were to create a theme that is usable by as many users of the original Waipoua theme as possible, with as few “migration steps” as possible, I have to realize that it’s simple not feasible. I always knew that I would also need to offer a “companion plugin” as well, preserving all the shortcodes Waipoua was offering. But is that really worth it? How many users are there still who use Waipoua and who would be brave enough to migrate?

Option 1: Offering two different versions of my theme

My first thought, even some time ago, was to offer two variants of my theme. One that would try to be almost “pixel perfect” not breaking the styles of elements on existing sites. And one that would leverage the Site Editor to its fullest, by only adding styles through the Site Editor using the theme.json file.

In this approach, the first variant would load this ~900 lines of CSS file, the second one would only load one, that is necessary to style the header with the search. Or it would not try to replicate the search exactly how it is, and instead just offers a different search in the header.

Option 2: Taking this as a learning opportunity and move on

This project was really fun! But it was also very frustrating at times. One main thing I learned from it: writing a great theme is not easy! And my respect for the work of Ellen and Manuel grew with every hour I’ve tried to replicate their work.

Going forward

I still plan to create a new theme that would look similar enough to Waipoua, so people would recognize my page, and maybe not even realize it is a different theme. If you don’t compare the new and old version side by side, and just look and the colors, fonts and structure, you will probably just think there were some minor changes in the current theme.

I really don’t like the idea to add any custom CSS to my very first theme, that cannot be overwritten in the Site Editor by any user. And I would also like to not force users to use a companion plugin to make it work with their current content. I am one of these users myself, since I have used some shortcode in old blog posts, as there was no Block Editor around that would allow you to create “buttons” or columns in the text.

Help me with your feedback!

I often ask in my blog posts for comments, and most of the time I don’t get any. But this time I would really appreciate your feedback. Even more if you use Waipoua on one of your site. What would you like me to do? Create a theme with two variants (Option 1)? Or just try to create a real Block Theme that would not try to “support legacy content” (Option 2)?

Goal missed: I had to add some CSS to the theme

When I’ve started this project, I had the goal to only use the Site Editor to rebuild the theme. I wanted to see how far I can come without using custom CSS. My final opponent was the header. Just using the options from the Site Editor and Core blocks, it was simply impossible to get the same overall look. Especially the Search block is too limited in its options.

Adding a CSS file

Just getting the search input with a custom background color (transparent) and styling the search icon was not possible. Trying to set the styles and effect for the input focus and styling the placeholder text, I came to the point at which it was just impossible to only use the theme.json so I finally had to abandon my goal and add a style.css file to the theme.

Some changes later, I’ve recognized that I had to use quite long repetitive CSS selectors and I got to the conclusion that I should use SASS as well.

After this sacrifice, things got a lot easier. Knowing who to write custom CSS code made styling the header so much easier. I was working on the header and the rest of the theme for the past four weeks, and the current state looks pretty close to the original theme.

The header

As mentioned above, the header was the reason to introduce a CSS file, but some of the styles were possible using the Site Editor only. In my first attempt, I even managed to get the Home Link icon in place, using the "css" property in the "core/home-link" block styles. Still, adjusting all the styles to match the original theme took me ~100 lines of CSS. But the result looks very good:

The original header

Screenshot of the original Waipoua theme header, showing the navigation with the search on the right, the site title and subtitle, and the social media icon in the second row.

The new header

The new header showing the same elements with some minor differences, mainly in spacing.

Can you spot the differences? You would probably need to use a tool to visualize them. The elements shift a few pixels, but overall it looks very similar. For the home icon, I had to create an SVG using the original (very small) PNG as a reference.

One difference you might have spotted is the usage of “down carets” after the nav items with a sub-navigation. This is an option you can disable using the “Display > Submenus > Show arrow” toggle in the Navigation block settings. But since I also want to improve the accessibility of the theme by default, I will keep this option enabled.

Creating additional templates

After I’ve finished the initial design, I continued with some templates. The first two I’ve created were “Single Posts” and “Pages”.

The posts template

I thought this would be quick. Just add the date and comments count (with an anchor link to the comments form) to the “entry header” and the categories, tags, and comments to the “entry footer”. I was so wrong. πŸ™ˆ

When developing a new theme, I usually use the “Theme Unit Test” XML import file. This will create a lot of content and menus you can use to test your design. To test the different HTML tags and their styling in the new theme, I’ve used the “Template: Comments” blog post. This is when a large amount of custom CSS came into the theme. Elmastudio beutifully styles all the differently elements you can have in your content, like lists, quotes, tables, etc. And they also styled them (differently) for comments, to accommodate for the smaller width you would have in the comment content. This meant that I had to copy all these styles. And since you can only style very few native HTML elements using the theme.json I had to do this with more custom CSS code. I’ve ended up writing ~160 lines for those elements in the content and another ~100 lines for adjustments in the comment content. I now realize how much work and thought go into designing a theme with great styles, and I have even more respect for what Ellen and Manuel did with all their themes.

Introducing a new template part: comments

Since the theme is using the comments listing and comments form on posts and pages, I’ve created a new template part it. It contains the “Comment Template”, “Comments Pagination” and “Comments Form” blocks.

For the comments form, I also had to add ~75 lines of CSS (even using SASS) and it once again showed me, how frustrating it is to style form elements:

Click here to display content from Twitter.
Learn more in Twitter’s privacy policy.

But hey, in the end it was “only” ~75 lines and I got to practice using CSS grid a bit more.

Post navigation buttons

Two other blocks I were not happy about in their current implementation were the “Previous post” and “Next post” blocks. They do offer an “Arrow” style variant, but this only adds an arrow before/after the link, which is not clickable. Since I wanted to have that “button design”, I had to use that “pseudo-content trick” to extend the clickable area of the link to the while “button”. Also, adding a background color for the button was not that easy, since the block wrapper div would also be visible if the link would not be there. So, in summary, these blocks could also receive some improvements in future versions of the Block Editor.

The pages template

After finalizing the Single Posts template, creating the Pages template was pretty straight forward. All I had to do was removing the date and comments link from the “entry header” and the categories and tags from the “entry footer”. The rest of the template is the same. Having introduced the “comments” template part before made it even easier, if I have to change some styles on that part.

The footer

After finishing the “entry content” part of posts and pages, I finished the footer. But since it’s mostly static content, that was done rather quickly. Only when saving the changes to the theme using the Create Block Theme plugin, I experienced some issues.

Static text would be wrapped in translation function, which is amazing! Only those are not escaped at all. And the year would also be hard coded. Even when you change that into dynamic code and escape it properly, it would get reverted back any time you make more changes to the footer part.

Escaped and dynamic footer

Here is some part of the footer code I have improved to be more secure and dynamic:

<p>&copy; <?php echo date( 'Y' ); ?>&nbsp;</p>

<!-- ... -->

<p><?php echo wp_kses_post( __( 'Proudly powered by <a href="https://wordpress.org/">WordPress</a>', 'kauri' ) ); ?></p>

<!-- ... -->

<p class="has-text-align-center">
	<?php echo wp_kses_post( __( 'Theme: Kauri by <a href="https://kau-boys.com">Bernhard Kau</a>, based on Waipoua by <a href="https://www.elmastudio.de/en/">Elmastudio</a>', 'kauri' ) ); ?>
</p>

<!-- ... -->

<p class="has-grey-color has-text-color has-link-color">
	<a href="#top"><?php echo esc_html__( 'Top', 'kauri' ); ?> ↑</a>
</p>

This is what the Create Block Theme plugin created/overwrites on changes:

<p><?php echo __('Β© 2024&nbsp;', 'kauri');?></p>

<!-- ... -->

<p><?php echo __('Proudly powered by <a href="https://wordpress.org/">WordPress</a>', 'kauri');?></p>

<!-- ... -->

<p class="has-text-align-center">
			Theme: Kauri by <a href="https://kau-boys.com">Bernhard Kau</a>, based on Waipoua by <a href="https://www.elmastudio.de/en/">Elmastudio</a>		</p>

<!-- ... -->

<p class="has-grey-color has-text-color has-link-color">
	<a href="#top">Top ↑</a>
</p>

As you can see, the escaping is missing completely. And the last two paragraphs are not translatable anymore. I didn’t have the time to look at the code producing these lines, but there might be a solution for that. In the meantime, I have to revert these changes, any time I update the footer template part.

Conclusion

Creating a full theme is a lot of work! Even “just” re-implementing a Classic Theme as a Block Theme takes a lot of time, since there are so many details you must think about. And I even haven’t rigorously tested the theme on mobile – first test look good though.

There is still a lot of work to do, but I still hope that I can make the switch in two weeks. Even if the theme is not perfect at that time.

If you want to see all the other changes I made and didn’t mention in this update, or follow along with the further implementation, check out the commits on the GitHub repository. I am really happy with where the current implementation is at right now and can’t wait to finish the theme. πŸ™Œ

A fifteen-year-old teen who doesn’t know what to wear

Readers of my German blog know this tradition of “blog birthday blog posts”. Another year has passed, and I’ve been blogging on this site for 15 years now. In that time, 401 posts have come together, but I only translated 188 into English, which I plan to change. So today is not the end of me blogging.

Closing More Plugins

A year ago, I announced that I had my first plugin closed. Since then, I’ve had four more removed from the Plugin Directory because either their functionality is now included into Core, or the technology behind them is no longer used. I’ll close another one when Preferred Languages finally lands in Core.

The numbers for the past year

Unfortunately, visits on the German site have also decreased by almost 18%, while on the English site, it was only 2% less. I can’t know exactly why this happened, but I hope that everyone who reads actively also finds the right content. If not, feel free to wish for a topic. Hopefully I don’t only get more readers, if I write something about AI. πŸ˜…

The number of visits on the English site continues to be higher than on the German one and increased from 53.4% to 57.8%. That’s why I’ve translated this blog post as well (I usually write English first, but only wrote the birthday blog posts in German).

Top3 in the past year

  1. Repair a broken Git Repository file system
  2. Create users in WordPress using the REST API
  3. Update all composer dependencies to their latest versions

It’s interesting to see, that hugely different blog posts made it into the Top3 compared to my German blog. As I haven’t really did a Top3 for past years, I can’t tell how they have changed. I might update this section, after I translated the previous birthday blog posts. A quick check on the statistics of last year shows the same three blog posts, only position 1 and 2 have changed.

Still no new theme

A year ago, I announced here that I wanted to work on a new theme. And as you could follow in previous posts, I’m making very good progress. I actually planned to use the new theme today for my blog’s birthday, but it’s not as good as I’d like it to be.

I’m writing this post from a hotel on the way back from WordCamp Europe 2024. That’s also why I couldn’t work on it as much. Just yesterday, I finally finished the footer on the train, and with the progress I made, all parts were newly created. But when exporting everything into the theme files, the footer suddenly broke. I was able to fix that today, but there are still many small details to be designed. Currently, I’m working on the comments section below the blog posts. But basic styles, like lists, tables, and similar content, also need to be adjusted. More on that in future posts.

And then I realized that my blog’s birthday isn’t the perfect day for the new theme, because 12 years ago, I was also looking for a new theme on the blog’s birthday and then activated it exactly a month later. So mark 12 July in your calendar.

Conclusion

So there’s still a lot going on, and I use many of my free minutes in my spare time to keep working on the blog. I hope the final theme also be something other people enjoy and use.

Oh yes, while I’m typing these lines, the soccer European Championship is on the TV in the hotel room. But those who know me, should also know that I don’t really into watching soccer. So there’s no video on that topic, but instead writing this from Switzerland, here’s the video with the announcement for the next WordCamp Europe, which I’ll definitely attend as well:

Click here to display content from YouTube.
Learn more in YouTube’s privacy policy.

Building and styling the new header

The header was always the part of the theme, I wasn’t sure I can easily replicate. But with every new Core or Gutenberg version, there have been more options to accomplish what I want to have as an end result. I still think that I need to add some custom CSS for some changes. But let’s take a look at how far I came.

The original header

Before I show you my first result, which I achieved just using the Site Editor and all available settings, let’s take a look at the original header again:

The actual “header” of the Waipoua theme is only row with the red background. The site title, site description and the “Header Widget Area” with the “Social Links Widget” are in the “wrapper” element for the content. But for the new theme, I decided to treat the whole area shown as the header.

The new header

So without further ado, let’s take a look at how far I came, rebuilding it with the Site Editor only. This is the first result:

You can already spot some clear differences. It starts with the “Home Link” block, the first element of the navigation, which does not support an icon. I will probably fix this with some custom CSS and a background image, and making the “Home” text “visually-hidden”.

The other clear difference is the search field. In the Waipoua header, this field has a transparent background. The icon is just a background image, and the search form does not have a “submit button”. When focused, the input grows a bit in width, and the background becomes white, while the icon and placeholder text become gray. This is a nice effect, and the “Search” block even supports something similar, but because it is right aligned, it would “jump to the left and grow to the right”. That was not really nice. It was also less accessible this way. That’s why I decided against it. I may still change the background color, as described before, but this is not possible with the block settings. Only the background and icon color of the button could be changed. I was also not able to reduce the height of the input field.

When it comes to the “second header row”, the site title looks different, since it’s underlined and not large enough. This is also something I couldn’t change in the Site Editor for some reason. The Core styles are just more specific and would therefore overwrite any settings made in the block settings.

The icons look pretty much the same. They are 1px smaller (the “normal” size in Core is just smaller), but the icons are also centered better than in the original theme, and they use the current icons (e.g. for YouTube or Instagram). Unfortunately, there is no icon for the “Comments RSS”. I don’t know how I would solve that on my blog. But is anyone using this RSS feed anyway? πŸ€”

The structure of the header

Now that we have seen the result in the frontend, let’s take a look at the structure in the Site Editor and which blocks I have used:

Most things are not surprising. But some details might be new to you. Did you know, for example, that you cannot only use links inside the navigation block, but also blocks like “Home Link”, “Search” or many other blocks? This is really nice, because when on a smaller screen, those block would also be in the “hamburger menu”.

The second “header row” is also quite basic in most parts. To align the site title and site description at the bottom – which I could find out how to do previously – I could simply use the “Change vertical alignment” setting.

The more interesting part is probably the social links. As mentioned earlier, this was the “Header Widget Area” in Waipoua, so I made this another template part, similar to how we did with the sidebar.

Conclusion: a lot of available settings

It’s hard to explain every step I took to implement the current header. It was just so many settings to use to come to this result. You can find the changes in the current commit to the Git repository for this theme. I was quite surprised that all settings were just saved into the template parts. I only added a new templateParts entry to the theme.json, so it would read “Header Widget Area” in the “List View” and not the slug, as in the screenshot.

My next step is trying to fix all those small differences in the header, I wasn’t able to do in the Site Editor alone. Let’s see how far I can come and how to explain, what I had to do, in the next blog post. As I just started my journey to WCEU, and have some more trains rides before me, the next blog post might come next week already.

Moving the sidebar into a theme pattern

I initially planned to continue with the header, as mentioned in the last blog post, in which we’ve created a sidebar for our theme in the Site Editor using a “Synced Pattern”. But since this has some downsides I wanted to address before creating more pattern, we are going to improve the current solution first.

The sidebar as a synced pattern

For the “Index” template, we’ve created a two-column layout and placed the sidebar in the right column. If we show the source code for the front page, this is what we will see:

<!-- wp:column {"width":"300px","style":{"spacing":{"padding":{"top":"0","bottom":"0","left":"0","right":"0"}}}} -->
<div class="wp-block-column" style="padding-top:0;padding-right:0;padding-bottom:0;padding-left:0;flex-basis:300px">
<!-- wp:block {"ref":1842} /-->
</div>
<!-- /wp:column --></div>

The sidebar is referenced by an ID. This is the post ID of that Synced Pattern with has a post_type of wp_block. The post_content is the blocks we’ve added to the sidebar:

<!-- wp:group {"style":{"spacing":{"padding":{"top":"20px","bottom":"20px","left":"20px","right":"20px"}}},"backgroundColor":"background-secondary","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-background-secondary-background-color has-background" style="padding-top:20px;padding-right:20px;padding-bottom:20px;padding-left:20px"><!-- wp:search {"label":"Search","showLabel":false,"buttonText":"Search","buttonPosition":"button-inside","buttonUseIcon":true} /-->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Recent Posts</h3>
<!-- /wp:heading -->

<!-- wp:latest-posts /-->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Recent Comments</h3>
<!-- /wp:heading -->

<!-- wp:latest-comments {"displayAvatar":false,"displayDate":false,"displayExcerpt":false} /-->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Categories</h3>
<!-- /wp:heading -->

<!-- wp:categories /-->

<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Archives</h3>
<!-- /wp:heading -->

<!-- wp:archives /--></div>
<!-- /wp:group -->

This shows another issue the current solution has: all headings are hard coded into the sidebar. This might be OK for a single site, but since my blog is multilingual, and I want to create a theme that can be used by anyone in any language, we want to be able to translate those strings. How do we do that?

Transforming the synced pattern into a template/pattern

The first step of this is to take the last code snippet and move it into a file. We could use an HTML file here, but if we want to translate it, we have to use a PHP file. Since the sidebar is only a part of a template, like the “Index” template, it makes sense to store it in a different directory. The best one here is the patterns directory, which is also quite logical, since it was a pattern before.

Creating the pattern

So let’s create a file patterns/sidebar.php and copy the synced pattern from the Site Editor (stored in the database):

<?php
/**
 * Title: Sidebar
 * Slug: kauri/sidebar
 * Inserter: no
 */
?>
<!-- wp:group {"style":{"spacing":{"padding":{"top":"20px","bottom":"20px","left":"20px","right":"20px"}}},"backgroundColor":"background-secondary","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-background-secondary-background-color has-background" style="padding-top:20px;padding-right:20px;padding-bottom:20px;padding-left:20px"><!-- wp:search {"label":"Search","showLabel":false,"buttonText":"Search","buttonPosition":"button-inside","buttonUseIcon":true} /-->

	<!-- wp:heading {"level":3} -->
	<h3 class="wp-block-heading"><?php esc_html_e( 'Recent Posts', 'kauri' ); ?></h3>
	<!-- /wp:heading -->

	<!-- wp:latest-posts /-->

	<!-- wp:heading {"level":3} -->
	<h3 class="wp-block-heading"><?php esc_html_e( 'Recent Comments', 'kauri' ); ?></h3>
	<!-- /wp:heading -->

	<!-- wp:latest-comments {"displayAvatar":false,"displayDate":false,"displayExcerpt":false} /-->

	<!-- wp:heading {"level":3} -->
	<h3 class="wp-block-heading"><?php esc_html_e( 'Categories', 'kauri' ); ?></h3>
	<!-- /wp:heading -->

	<!-- wp:categories /-->

	<!-- wp:heading {"level":3} -->
	<h3 class="wp-block-heading"><?php esc_html_e( 'Archives', 'kauri' ); ?></h3>
	<!-- /wp:heading -->

	<!-- wp:archives /--></div>
<!-- /wp:group -->

Every pattern should get a header comment properties, like Title, Slug and other things. As we don’t need this pattern to show up in the patterns list in the Site Editor, we set Inserter: no in the header comment.

You can also see that our headings are now wrapped in translation functions. Now we are ready to use this new pattern in a template.

Using the pattern

Since we’ve used the “Create Block Theme” plugin, we have already overwritten our templates/index.html file, when we saved changes from the Site Editor to the theme files. As shown in the first snippets, this contains the following line:

<!-- wp:block {"ref":1842} /-->

In order to use the pattern file from the theme instead, we replace it with a line like this:

<!-- wp:pattern {"slug":"kauri/sidebar"} /-->

We could go ahead and use this in our templates/index.html file directly, but we will add another step in between. Instead, we create a new file called parts/sidebar.html and save this single line in here.

Why do we do that? Besides pattern, we have a second type of “reusable templates”. The other type is “templates parts”, which are considered “areas” in your templates. The two parts we already have are “header” and “footer”. Our “sidebar” is nothing different, so it makes sense to use a template part here as well. We should therefore also add it to the theme.json in the templateParts section:

{
	"templateParts": [
		{
			"area": "header",
			"name": "header",
			"title": "Header"
		},
		{
			"area": "footer",
			"name": "footer",
			"title": "Footer"
		},
		{
			"area": "uncategorized",
			"name": "sidebar",
			"title": "Sidebar"
		}
	]
}

Now, when finally adding this template part to the index.html template, you will see the other benefit. This is how we do it:

<!-- wp:template-part {"slug":"sidebar","tagName":"aside"} /-->

With the tagName attribute, which is not available for the wp:pattern block, we can wrap the sidebar in an <aside> tag for better accessibility.

Cleanup

Since we’ve moved the sidebar into a pattern in the theme, you can now safely navigate to “Appearance > Editor > Patterns” and delete the synced pattern (stored in the database).

Conclusion

While building a theme/layout, it’s great to quickly do this inside the Site Editor. But once you are done, you should save all changes into your theme files. While many changes can be saved automatically using the “Create Block Theme” plugin, some tasks need to be done manually.

You can find all the changes in the current commit to the Git repository for this theme. I’m positive that we can now move on to work on the header of the theme.

Bringing some structure into the theme: The Sidebar

Now that we have fonts and colors, we can start with the structure of the theme. Giving a page a clear structure is fundamental to enable it to be responsive later on.

Waipoua structure

The Waipoua theme is roughly structured as followed:

  • header (red background)
    • home icon
    • navigation
    • search
  • wrapper
    • second header
      • site title
      • site tagline
      • alternative: site icon added through theme options page
      • social media icons
    • content
    • sidebar (light gray background)
    • footer

The main idea of the wrapper is getting some padding on the left and right, when the display gets smaller. The red header will at a certain breakpoint become a single hamburger menu icon, that it will open a vertically sliding down navigation and search (the home icon is missing in this menu).

Blank theme structure

Now let’s look on the structure from our blank theme. This is what you get from the boilerplate (simplified):

  • header
    • site icon
    • site title
    • site tagline
    • navigation
  • content
  • footer

Comparing this to the Waipoua theme, it is a lot simpler. But we can already see something missing: the sidebar.

Adding a sidebar

Sidebars are something you don’t see too much anymore on current websites. But for a blog theme, they still make sense in my opinion. And since I’m rebuilding a theme that has one, I have to add it. Well, the theme even has an option to have two sidebars. The second one site between the content and the main sidebar showing all sticky posts:

A screenshot showing the front page with the content on the left, taking up about 40% of the width, the sidebars with the headline "featured posts" in the middle and the main sidebar on the right.

I couldn’t find a way to allow a selection of which template to use for all pages. Therefore, I decided to go with the single main sidebar for the first version of the theme.

But how do we even get a sidebar? We need an element, that we can use on multiple templates and that would always show the same content. The answer is: we need a “Synced Pattern”. You can create it at “Appearance > Editor > Patterns” where you click on the plus icon next to “Patterns” and select “Create pattern”. In the modal, use a name like “Sidebar” and make sure the “Synced” toggle is activated. After clicking “Create”, we can fill the sidebar. I did this in the following example with the default “widgets” from the classic theme:

Screenshot of the "List View" with all the blocks, each prepended with a heading block and all grouped. On the right in the block settings, a background color and paddings are set.

For the widget titles, I’ve used heading blocks. Some blocks need some settings being adjusted. For the Search block, I put the search button into the field and used the icon. On the Latest Comments block, I deactivated all settings, so it also shows the name and the blog post title.

One thing I’ve missed, when first creating the sidebar: adding a background color and some padding. So we also group the blocks in the sidebar, set the background color to “Background Secondary” and set the “Dimensions > Padding” to “20px” vertically and horizontally.

Placing the sidebar on the page

Now that we have the sidebar, we have to place it on every single template. Let’s start with the front page. We navigate to “Appearance > Editor > Templates” and select “Index” on the right, the only template we have so far. As mentioned earlier, the template is rather simple. It only used a “Query Loop” block as the content. This would be our “left column”. And indeed, we will use the Columns block to get our “content | sidebar” layout. The left columns will contain the Query Loop, the right one the Sidebar pattern. This is the result:

Screenshot of the "Index" template with the "List View" showing the "Query Loop" in the left column and the "Sidebar" pattern in the right one.

Let’s try to explain all the things I did here. First, I put the “Query Loop” into a left column and the “Sidebar” in a right column. The “Columns” block had the “Dimensions > Block Spacing” set to “50px” horizontally. The right “Column” block has a “Settings > Width” of “300px”, as the sidebar has a fixed width. The left “Column” however has an empty width value. This will allow it to take up the remaining width. So we get a responsive left column and a fixed width right column.

The group around the columns block is needed to give it a specific width. Instead of setting the width of this specific group on the “Index” template, we set it in the “Styles > Layout > Dimensions” (using the white/black icon in the top right). Here we set a fixed “Content” width of “1100px”.

The result

OK, after finishing all these steps, let’s see what we got now when visiting the front page of our new theme:

The frontend view of the front page with the two columns: content on the left, sidebar on the right with a light gray background.

Nice! Isn’t it? OK, not really the end result we want. The blocks in the sidebar still don’t look great, but as for today, we should be happy to have our layout with the content and sidebar next to each other done.

Conclusion

When trying this layout for the first time, I struggled a bit to get it as I wanted it. I couldn’t find a way to get those “50px” in between the two columns. I had to add a middle column with “2px” width, which would get “50px” in total with the default “24px” gap. Now, with the newer version of WordPress, we have been able to just set the gap to “50px” and get the result we want. Twenty Twenty-Four is still using columns to get the correct gap. It is even using “empty columns” left and right for some padding. Fortunately, we don’t need that anymore.

For next week, I think I will continue styling the header. We will also need a “widget area” there to place the social media links, and we will also align the elements. This might be tricky, since I haven’t yet found out how to align elements at the bottom.

Adding some colors to the Block Theme

Due to some personal topics, wasn’t able to work on the new theme, or write a new blog post for that matter. But now I’m back and will probably speed up a bit and write more frequently than just every second week. I still want to have my new theme ready by June for the blog birthday.

Adding colors

For many people, having the right (brand) colors makes a theme more recognizable. So let’s start with the main colors first. But before we start adding colors, we first have to deal with one of the hardest things in computer science: naming things.

Color names

There are different philosophies in how to name your colors. Some would go with primary, secondary, tertiary, etc. But as a non-native speaker, and being dyslexic, even the 3rd one is hard to spell correctly. And what is the 4th, 5th, etc. are named? So that why others use named like base, contrast, accent and for multiple variants, they add a numbered suffix, like contrast-2, contrast-3, etc. This is how Twenty Twenty-Four is doing it.

To be honest, I have no idea what the best way to name my colors is. But since this is a “revival” of a ElmaStudio theme, I checked how Ellen and Manuel are doing it right now. Looking at their latest themes Mugistore and SolarOne, they use combined color names like background-primary, font-primary, accent-primary, etc. So I try to go with this as well.

Assigning color values to color names

Now that I decided on which naming scheme to use, I wanted to assign all colors from the Waipoua theme to a color name in the new theme. So I first searched for all colors in the theme and found 26 different colors. That’s quite a lot! But some of those were only used for very specific CSS selectors, and others were used for colored buttons or boxes using shortcodes.

After researching every single color and where they are used, I came up with the following color definitions:

{
	"settings": {
		"color": {
			"defaultPalette": false,
			"palette": [
				{
					"slug": "black",
					"color": "#000000",
					"name": "Black"
				},
				{
					"slug": "white",
					"color": "#ffffff",
					"name": "White"
				},
				{
					"slug": "grey",
					"color": "#909090",
					"name": "Grey"
				},
				{
					"slug": "red",
					"color": "#F55243",
					"name": "Red"
				},

				{
					"slug": "background-primary",
					"color": "#ffffff",
					"name": "Background Primary"
				},
				{
					"slug": "background-secondary",
					"color": "#f6f6f6",
					"name": "Background Secondary"
				},
				{
					"slug": "background-tertiary",
					"color": "#b3b4ae",
					"name": "Background Tertiary"
				},
				{
					"slug": "background-quarternary",
					"color": "#909090",
					"name": "Background Quartenary"
				},

				{
					"slug": "font-primary",
					"color": "#333333",
					"name": "Text Primary"
				},
				{
					"slug": "font-secondary",
					"color": "#4c4a4a",
					"name": "Text Secondary"
				},

				{
					"slug": "primary",
					"color": "#f55243",
					"name": "Brand Primary"
				},

				{
					"slug": "border-primary",
					"color": "#ececec",
					"name": "Border Primary"
				},
				{
					"slug": "border-secondary",
					"color": "#dddddd",
					"name": "Border Secondary"
				},

				{
					"slug": "input-background",
					"color": "#ffffff",
					"name": "Input Background"
				},
				{
					"slug": "input-background-hover",
					"color": "#fcfcfc",
					"name": "Input Background Hover"
				},
				{
					"slug": "input-border",
					"color": "#999999",
					"name": "Input Border"
				},

				{
					"slug": "social-icons-background",
					"color": "#b3b4ae",
					"name": "Social Icons Background"
				},
				{
					"slug": "social-icons-background-hover",
					"color": "#333333",
					"name": "Social Icons Background Hover"
				},

				{
					"slug": "red-btn-box",
					"color": "#e22727",
					"name": "Red Button & Box"
				},
				{
					"slug": "green-btn-box",
					"color": "#71b247",
					"name": "Green Button & Box"
				},
				{
					"slug": "blue-btn-box",
					"color": "#56b3b7",
					"name": "Blue Button & Box"
				},
				{
					"slug": "yellow-btn",
					"color": "#f9d93a",
					"name": "Yellow Button"
				},
				{
					"slug": "yellow-box",
					"color": "#f7ec69",
					"name": "Yellow Box"
				},
				{
					"slug": "white-box",
					"color": "#fff",
					"name": "White Box"
				},
				{
					"slug": "lightgrey-box",
					"color": "#f6f6f6",
					"name": "Lightgrey Box"
				},
				{
					"slug": "grey-btn-box",
					"color": "#d3d3d3",
					"name": "Grey Button & Box"
				},
				{
					"slug": "dark-box",
					"color": "#333",
					"name": "Dark Box"
				},
				{
					"slug": "black-btn",
					"color": "#000",
					"name": "Black Button"
				}
			]
		}
	}
}

In total, these are 29 color definitions. If you open up the color picker in the block editor, like on a paragraph block, this is what you would see:

The color picker with the 29 defined colors, with some of them being shown multiple times.

Some of the colors are “double”, but this is also how the other ElmaStudio themes do it, and I think it’s a good idea. Let’s say you want to change the social icons color only, then you can do this by changing the two specific color values. It would also be possible in the “style book”, but this is easier, especially in a customization or child theme.

Using the colors

Now that we have some colors, let’s use some of them. To get a bit more “branding” into the theme, we could start with the color for the header. As we will create the correct markup for it a bit later, let’s start with setting them in the site editor:

Screenshot of the Site Editor with the header template opened and the colors for the first group block set as described.

How do we get to this result? First, we navigate to “Appearance > Editor”. Then click into the header twice and click on the “Edit” button. Another way to get into the header template is “Appearance > Editor > Patterns >Header”, then select the header you want to edit (we currently have only one) and either click on the “edit icon” (the pencil) in the top left or simple on the header in the main window.

We now open the “List View” and select the top “Group” block. On the right, we select the “Block” settings and the “Styles” tab (the black/white circle). For the “Background” color, we select the “Brand Primary” color (red). Then we click on the “Text” color.

Since the Waipou theme is using a white with a 75% opacity, we first select “White” (the second color in the top row). After that, we click on the “preview area”, this is the white (in the screenshot with the “checkered pattern”) square above the one with “White #FFFFFF” (in the screenshot “Custom #FFFFFFBF”) in it. Now we can either type in a HEX code with an opacity (in this case “#FFFFFFBF”), or we click on the dropdown and select RGB or HSL and change the “A” value to “75”. This should give us the result in the screenshot.

I hope you were able to follow along. Having screenshots for every single step would have been too much. Maybe next time I have to record a video. πŸ˜€

Save changes to the theme

All the changes we have done to the header are saved into the database. They do not reflect in our theme files. To get the changes from the header template, we could just copy the raw HTML from the site editor and save it to our file. We can then safely reset the customizations in the site editor.

An easier way is using the Create Block Theme plugin again. It adds an icon into the site editor, that allows you to download the current state of the theme as a ZIP file or to save the changes directly into the theme’s folder. But be aware that this overwrites all the files. I hope you are all using version control and a good IDE, then it’s not too much of an issue, but still be careful.

Screenshot showing the "Create Block Theme" options to "Save Changes" and "Export Zip" with an alter indicating, that changes have been saved successfully.

After clicking on the “wrench” icon, it will open the “Create Block Theme” plugin page. You can now click on the “Save Changes” button. This will save everything – not just the current template/part – to the theme and reset the customizations in the database.

We are going to use this option every time we made any changes to the theme using the Site Editor. Sure, we could always just write code directly into the theme.json or other files, but why would we, when instead we can more easily just build the theme in the Site Editor with a live preview.

Conclusion

Setting some colors sounds easy, but there is some planning involved as well. You want to make sure you got this right, before you start using your colors all over the place, as changing this later on might add a lot of extra work.

Now that we have made our first changes using the Site Editor, we are going to set the layout in the next step. That would be columns/sidebars, page width, elements in header and footer, etc. There were some things I didn’t though would be possible, but with WordPress 6.5 just being released, it might become easier. If that worked out, you will see in the next blog post.

Adding fonts to our block theme

After we’ve created the raw theme in the last blog post, it’s time to add some basic things to our theme. To quickly get some similar appearance, let’s start with fonts.

My blog is using the default fonts from Waipoua, but I have changed the main colors in a child theme. This is how the theme looks like with no customizations:

Screenshot of the original design of the Waipoua theme, showing the blog listings front page with social icons in the top right and the gray sidebar on the right.

As you can see here, I’ve changed the red tone of the header, the background color of the sidebar, and I’ve also colored the social icons in the top right widget area. The rest looks pretty much like in the parent theme.

Adding the fonts

Now, this is an interesting chapter. As of today, you would usually do the following:

  1. Download the fonts – for Google Fonts, I usually use theΒ google-webfonts-helper and download all variants
  2. Save fonts in a folder in your theme
  3. Define the fonts in the theme.json file

If you want to follow this manual path, there is an excellent guide from Carolina on the “Full Site Editing With WordPress” site.

But since there is a new way of adding fonts to a block theme coming up, let’s try this way. With the current WordPress version 6.4, you have to install the Gutenberg plugin in order to use this option, since it is not yet “final” and therefore hasn’t been merged into Core with WordPress 6.4, so we have to wait a little longer.

With Gutenberg installed and activated, navigate to “Appearance > Manage Theme Fonts”. Here you will find the following view:

Screenshot of the "Manage Theme Fonts" admin page, showing the current fonts in a list on the right, a preview area in the middle and buttons to add Google and local fonts.

Here you find an overview of all theme fonts on the right as well as preview area for these fonts. In the top right, you can use the buttons “Add Google Font” or “Add Local Font” to add a new font family to your theme.

Let’s add the font family for headlines first, which is the Google Font “Oswald”. We click the button “Add Google Font” and then search in the “Select Font” dropdown for the font. We are then presented with all available variants. I’ve just clicked the checkbox in the table header to select all of them:

Screenshot of the "Add Google font to your theme" admin page, showing the available variants.

The Waipoua theme only included the 400 weight variant, but as with a block theme you have more control on which font you use where, I think it’s best to have all the variants available, so which ever weight (and style, if available) is used, the text looks best.

After clicking the “Add Google fonts to your theme” button, you should see a success message like “Oswald font added to Kauri theme”. Now we do the same for the “PT Sans” font, again selecting all the variants.

If we navigate back to the “Manage Theme Fonts” admin page, we should see those new fonts in the right sidebar and a preview of them. In total, we have added 2 fonts with a total of 10 variants and a total size of 1.5 MB:

Screenshot of the "Manage Theme Fonts" admin page, showing the fonts imported in the previous step.

Result of the fonts import

Now what did we get after this step? Let’s take a look at the themes folder structure first:

$ tree .
.
β”œβ”€β”€ assets
β”‚Β Β  └── fonts
β”‚Β Β      β”œβ”€β”€ oswald_normal_200.ttf
β”‚Β Β      β”œβ”€β”€ oswald_normal_300.ttf
β”‚Β Β      β”œβ”€β”€ oswald_normal_400.ttf
β”‚Β Β      β”œβ”€β”€ oswald_normal_500.ttf
β”‚Β Β      β”œβ”€β”€ oswald_normal_600.ttf
β”‚Β Β      β”œβ”€β”€ oswald_normal_700.ttf
β”‚Β Β      β”œβ”€β”€ pt-sans_italic_400.ttf
β”‚Β Β      β”œβ”€β”€ pt-sans_italic_700.ttf
β”‚Β Β      β”œβ”€β”€ pt-sans_normal_400.ttf
β”‚Β Β      └── pt-sans_normal_700.ttf
β”œβ”€β”€ parts
β”‚Β Β  β”œβ”€β”€ footer.html
β”‚Β Β  └── header.html
β”œβ”€β”€ readme.txt
β”œβ”€β”€ screenshot.png
β”œβ”€β”€ style.css
β”œβ”€β”€ templates
β”‚Β Β  └── index.html
└── theme.json

We do have a new folder “assets/fonts” and in this folder we can find the Google fonts. As these can only be downloaded in the TTF format from fonts.google.com, this is what we also get with the (current) font management solution in Gutenberg.

But let’s take a look at the theme.json file, because this is the more interesting part of this whole step. You should now see something like this:

{
	"settings": {
		"typography": {
			"fontFamilies": [
				{
					"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif",
					"name": "System Font",
					"slug": "system-font"
				},
				{
					"fontFamily": "Oswald",
					"slug": "oswald",
					"fontFace": [
						{
							"fontFamily": "Oswald",
							"fontStyle": "normal",
							"fontWeight": "200",
							"src": [
								"file:./assets/fonts/oswald_normal_200.ttf"
							]
						},
						{
							"fontFamily": "Oswald",
							"fontStyle": "normal",
							"fontWeight": "300",
							"src": [
								"file:./assets/fonts/oswald_normal_300.ttf"
							]
						},
						{
							"fontFamily": "Oswald",
							"fontStyle": "normal",
							"fontWeight": "400",
							"src": [
								"file:./assets/fonts/oswald_normal_400.ttf"
							]
						},
						{
							"fontFamily": "Oswald",
							"fontStyle": "normal",
							"fontWeight": "500",
							"src": [
								"file:./assets/fonts/oswald_normal_500.ttf"
							]
						},
						{
							"fontFamily": "Oswald",
							"fontStyle": "normal",
							"fontWeight": "600",
							"src": [
								"file:./assets/fonts/oswald_normal_600.ttf"
							]
						},
						{
							"fontFamily": "Oswald",
							"fontStyle": "normal",
							"fontWeight": "700",
							"src": [
								"file:./assets/fonts/oswald_normal_700.ttf"
							]
						}
					]
				},
				{
					"fontFamily": "PT Sans",
					"slug": "pt-sans",
					"fontFace": [
						{
							"fontFamily": "PT Sans",
							"fontStyle": "normal",
							"fontWeight": "400",
							"src": [
								"file:./assets/fonts/pt-sans_normal_400.ttf"
							]
						},
						{
							"fontFamily": "PT Sans",
							"fontStyle": "italic",
							"fontWeight": "400",
							"src": [
								"file:./assets/fonts/pt-sans_italic_400.ttf"
							]
						},
						{
							"fontFamily": "PT Sans",
							"fontStyle": "normal",
							"fontWeight": "700",
							"src": [
								"file:./assets/fonts/pt-sans_normal_700.ttf"
							]
						},
						{
							"fontFamily": "PT Sans",
							"fontStyle": "italic",
							"fontWeight": "700",
							"src": [
								"file:./assets/fonts/pt-sans_italic_700.ttf"
							]
						}
					]
				}
			]
		}
	}
}

Following the “System Font” we can find our two new font families with one definition per variant. This is a lot of code that was created for us automatically, so we don’t have to.

If you refresh the page now, we won’t see any change. That’s because we have only imported the fonts into our theme and defined it in the theme.json file, but we are not using them.

Set fonts for body and headings

You can set a font family for the whole page, some “types” of elements or for individual blocks. To get the result we want, the following has to be added to the theme.json file:

{
	"styles": {
		"elements": {
			"heading": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--oswald)",
					"fontWeight": "400"
				}
			}
		},
		"typography": {
			"fontFamily": "var(--wp--preset--font-family--pt-sans)",
			"fontWeight": "400"
		}
	}
}

This will set the font for the body and all headlines, so inside the content, as well as the core/site-title, and other “headlines” blocks. We have to fine tune this later, but for the moment, we have the following result:

The front page with the two fonts.

As for fonts, this now looks a lot more like the original theme. But it’s just the first step. We still need to work on many aspects.

Bonus: Use WOFF2 instead of TTF fonts – or both

With the current solution, I really don’t like that it is using TTF fonts. They are usually used on desktop, not on the web. And even though most browsers can use them, they are a lot larger.

Using the google-webfonts-helper, I’ve downloaded all fonts in the WOFF2 format and adjusted the theme.json file accordingly. I’ve also put each font family files into a subfolder, to better organize them.

With these changes, the size of the web fonts could be reduced from 1.5 MB to only around 590 KB, for all variants. So while this step is not absolutely necessary, I would highly recommend to use WOFF2 files. Unless you have to support some really old browsers. Then you can always decide to download them in a different format with the google-webfonts-helper.

You can also keep the TTF files as a fallback. It would then look like this as an example:

{
	"fontFamily": "Oswald",
	"fontStyle": "normal",
	"fontWeight": "200",
	"src": [
		"file:./assets/fonts/oswald/oswald-v53-cyrillic_cyrillic-ext_latin_latin-ext_vietnamese-200.woff2",
		"file:./assets/fonts/oswald/oswald-v53-cyrillic_cyrillic-ext_latin_latin-ext_vietnamese-200.ttf"
	]
}

You can find the full example in the themes’s GitHub repository.

Hidden gem using the “Manage Theme Fonts” functionality

When committing the changes to the theme, I’ve recognized that the readme.txt file was change as well. First I thought, that I’ve probably changed something in this file as well. But then I saw these additions:

Oswald Font
Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) 
This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: https://scripts.sil.org/OFL 
License URL: https://scripts.sil.org/OFL 
Source: http://www.sansoxygen.com
-- End of Oswald Font credits --

PT Sans Font
Copyright Β© 2009 ParaType Ltd. All rights reserved. 
Copyright (c) 2010, ParaType Ltd. (http://www.paratype.com/public), with Reserved Font Names "PT Sans", "PT Serif" and "ParaType". 
License URL: http://scripts.sil.org/OFL_web 
Source: http://www.paratype.com
-- End of PT Sans Font credits --

So not only does the functionality take care of downloading the fonts, storing them in your theme, updating your theme.json file. It does also make sure that you have the credits to legally use those fonts in your readme.txt file. How cool is that?! πŸ€“

Summary

Adding Google fonts (or fonts from other sources) can be done in two ways: manually and with the “Manage Theme Fonts” functionality. While the latter is still not “finished”, it worked pretty well with this theme. If they also add an option to download different file formats (or change the default), I can’t wait to see this land in core.

I initially planned to also write about how to set colors and the site width in this blog post, but I think the fonts topic is enough for this one.

Kickoff for my new blog theme

This will be the start of the blog series for my new blog theme. As mentioned in the previous blog post, the goal is to create a theme that comes as close as possible to the current design, while using the Site Editor to create all necessary styles and templates.

Creating the theme

When I developed from scratch in the past, I’ve usually used _s (underscores), but since this is a classic starter theme, I needed something different. Fortunately, there is the “Create Block Theme” plugin, you can use to create a theme from your WordPress installation.

After installing and activating the plugin, navigate to “Appearance > Create Block Theme” and choose the “Create blank theme” option on the left. You are then presented with a form on the right, asking you for name, description, etc. for the new theme. This is the data that is usually found in the style.css header comment.

After filling out the form, click the “Generate” button in the bottom left. This will create the new theme in the WordPress installation. Now you can activate the theme for your site. The result would look like this:

The frontend result of the theme with the site title in the top left, a navigation sith "Sample Page" in the top right, the "Hello World" blog post in the middle, and the "Proudly Power by WordPress" in the bottom, all with no styles.

Isn’t that beautiful? OK, not quite what we need. But we do have a full Block Theme now, and can start adding all the styles we need.

The theme’s file structure

But before we start working on the theme, let’s take a look at what we have. This is the initial file structure of our new theme:

$ tree
.
β”œβ”€β”€ parts
β”‚Β Β  β”œβ”€β”€ footer.html
β”‚Β Β  └── header.html
β”œβ”€β”€ readme.txt
β”œβ”€β”€ screenshot.png
β”œβ”€β”€ style.css
β”œβ”€β”€ templates
β”‚Β Β  └── index.html
└── theme.json

2 directories, 7 files

Not all that much. But we do have template parts for a header and a footer. The only “page template” we have is an index.html file. The style.css file is basically empty, it mainly consists of the header comment with the data from the form. Interestingly, we find a line Requires PHP: 5.7 in this file, even though this PHP version never existed. πŸ˜…

The most important file however is the theme.json file. In this base version, it is only 35 lines long and has definitions for the layout sizes, spacing units, a system font family and the header and footer template parts.

In the next blog posts of this series, we will work with this file quite a lot.

The name of the new theme

You might have recognized, that I have chosen the name “Kauri” for the new theme (and the development site). The current theme of my blog is named Waipoua. Elmastudio named many of their themes after things in New Zealand or Asia. Waipoua Forest is a forest in the Northland Region of New Zealand. This forest shows some examples of kauri trees. And by now you should know why I’ve chosen this name. 😊

Next steps

In the next episode, we will make our initial changes to the theme.json file, maybe adding the fonts or setting the general width of the theme. So stay tuned.

If you want to follow along with the code, you can find the current state on GitHub. But please don’t create any issues or pull requests, before this blog series is finished. 😁