Building Block Theme From Scratch

Summary: Learning about building a Block Theme from scratch in WordPress.

Block Theme

Block Themes are built entirely using the block editor’s features, embracing a more modular and flexible approach compared to traditional PHP-based themes. They utilize index.html files as templates, theme.json for configuration, and template-parts for reusable sections like headers and footers.

  • Full Site Editing (FSE): Allows editing all parts of the site using blocks.
  • Template System: Uses HTML templates instead of PHP files.
  • Theme.json Configuration: Centralized theme settings for styles and settings.
  • Template Parts: Reusable sections like headers, footers, and sidebars.
  • Block Patterns: Predefined block layouts for common page structures.

Theme Structure

  • style.css
  • theme.json
  • index.html
  • 404.html
  • functions.php
  • header.html
  • footer.html
  • screenshot.png
  • /template-parts/
  • /assets/

style.css

The style.css file contains metadata about our theme and can also include global styles.

/*
Theme Name: My Block Theme
Theme URI: https://example.com/my-block-theme
Author: Your Name
Author URI: https://example.com
Description: A custom block theme built from scratch.
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: my-block-theme
Tags: block-theme, full-site-editing, custom-theme
*/

/* Global Styles */
body {
  margin: 0;
  padding: 0;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

theme.json

The theme.json file centralizes theme settings, including color palettes, typography, layout options, and more. It’s a powerful tool that allows for extensive customization without writing additional CSS.

{
  "version": 3,
  "settings": {
    "color": {
      "palette": [
        {
          "name": "Primary",
          "slug": "primary",
          "color": "#3490dc"
        },
        {
          "name": "Secondary",
          "slug": "secondary",
          "color": "#ffed4a"
        },
        {
          "name": "Success",
          "slug": "success",
          "color": "#38c172"
        },
        {
          "name": "Danger",
          "slug": "danger",
          "color": "#e3342f"
        }
      ],
      "custom": false,
      "customGradient": false,
      "defaultPalette": true
    },
    "typography": {
      "fontSizes": [
        {
          "name": "Small",
          "slug": "small",
          "size": "0.875rem"
        },
        {
          "name": "Normal",
          "slug": "normal",
          "size": "1rem"
        },
        {
          "name": "Large",
          "slug": "large",
          "size": "1.25rem"
        },
        {
          "name": "Huge",
          "slug": "huge",
          "size": "2rem"
        }
      ],
      "customFontSize": false
    },
    "layout": {
      "contentSize": "800px",
      "wideSize": "1200px",
      "spacing": {
        "padding": {
          "top": "20px",
          "bottom": "20px",
          "left": "20px",
          "right": "20px"
        }
      }
    },
    "spacing": {
      "units": ["px", "em", "rem", "%", "vh", "vw"]
    }
  },
  "styles": {
    "color": {
      "background": "#ffffff",
      "text": "#333333",
      "link": "#3490dc",
      "linkHover": "#1d72b8"
    },
    "typography": {
      "fontFamily": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif",
      "fontSize": "1rem",
      "lineHeight": "1.5"
    },
    "spacing": {
      "padding": {
        "top": "20px",
        "bottom": "20px",
        "left": "20px",
        "right": "20px"
      }
    }
  }
}

index.html

The index.html serves as the fallback template for our theme.

<!-- index.html -->
<!-- wp:template-part {"slug":"header"} /-->

<!-- wp:group {"tagName":"main"} -->
  <main>
    <!-- wp:post-content /-->
  </main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer"} /-->

single.html

<!-- single.html -->
<!-- wp:template-part {"slug":"header"} /-->

<!-- wp:group {"tagName":"main"} -->
  <main>
    <!-- wp:post-title /-->
    <!-- wp:post-content /-->
    <!-- wp:post-navigation /-->
  </main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer"} /-->

404.html

<!-- 404.html -->
<!-- wp:template-part {"slug":"header"} /-->

<!-- wp:group {"tagName":"main"} -->
  <main>
    <!-- wp:heading {"level":2} -->
      <h2>Page Not Found</h2>
    <!-- /wp:heading -->
    <!-- wp:paragraph -->
      <p>Sorry, but the page you were looking for doesn't exist.</p>
    <!-- /wp:paragraph -->
    <!-- wp:search {"label":"Search"} /-->
  </main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer"} /-->

header.html

<!-- template-parts/header.html -->
<!-- wp:group {"tagName":"header","style":{"spacing":{"padding":{"top":"20px","bottom":"20px","left":"20px","right":"20px"}}},"backgroundColor":"primary","textColor":"white"} -->
  <header>
    <!-- wp:site-title {"level":1,"style":{"typography":{"fontSize":"2rem"}}} /-->
    <!-- wp:navigation {"layout":{"type":"flex","justifyContent":"space-between"}} /-->
  </header>
<!-- /wp:group -->
  • wp:site-title: Displays the site’s title.
  • wp:navigation: Inserts the site’s navigation menu.

footer.html

<!-- template-parts/footer.html -->
<!-- wp:group {"tagName":"footer","style":{"spacing":{"padding":{"top":"20px","bottom":"20px","left":"20px","right":"20px"}}},"backgroundColor":"secondary","textColor":"black"} -->
  <footer>
    <!-- wp:site-title {"level":3} /-->
    <!-- wp:paragraph -->
      <p>&copy; 2024 Your Company. All rights reserved.</p>
    <!-- /wp:paragraph -->
  </footer>
<!-- /wp:group -->
  • sidebar.html: For sidebar content.
  • header-navigation.html: If separating navigation from the header.
  • footer-widgets.html: For footer widget areas.

functions.php

<?php
// functions.php

/**
 * Enqueue block styles and scripts.
 */
function my_block_theme_enqueue_assets() {
    // Enqueue the main stylesheet.
    wp_enqueue_style(
        'my-block-theme-style',
        get_stylesheet_uri(),
        array(),
        wp_get_theme()->get('Version')
    );

    // Enqueue block editor styles if needed.
    wp_enqueue_style(
        'my-block-theme-editor-style',
        get_template_directory_uri() . '/assets/css/editor-style.css',
        array(),
        wp_get_theme()->get('Version')
    );

    // Enqueue scripts if needed.
    wp_enqueue_script(
        'my-block-theme-script',
        get_template_directory_uri() . '/assets/js/main.js',
        array('jquery'),
        wp_get_theme()->get('Version'),
        true
    );
}
add_action('wp_enqueue_scripts', 'my_block_theme_enqueue_assets');

function my_block_theme_editor_assets() {
    wp_enqueue_style(
        'my-block-theme-editor-style',
        get_template_directory_uri() . '/assets/css/editor-style.css',
        array(),
        wp_get_theme()->get('Version')
    );
}
add_action('enqueue_block_editor_assets', 'my_block_theme_editor_assets');

Theme Supports

<?php
// functions.php

function my_block_theme_setup() {
    // Add support for block styles.
    add_theme_support('wp-block-styles');

    // Add support for responsive embeds.
    add_theme_support('responsive-embeds');

    // Add support for editor styles.
    add_theme_support('editor-styles');
    add_editor_style('assets/css/editor-style.css');

    // Add support for wide alignment.
    add_theme_support('align-wide');

    // Add support for custom color palettes.
    // Handled via theme.json.

    // Add support for custom logo.
    add_theme_support('custom-logo', array(
        'height'      => 100,
        'width'       => 400,
        'flex-height' => true,
        'flex-width'  => true,
    ));

    // Add support for custom header.
    add_theme_support('custom-header', array(
        'default-image' => get_template_directory_uri() . '/assets/images/header.jpg',
        'width'         => 1200,
        'height'        => 600,
        'flex-width'    => true,
        'flex-height'   => true,
    ));

    // Add support for custom background.
    add_theme_support('custom-background', array(
        'default-color' => 'ffffff',
        'default-image' => '',
    ));
}
add_action('after_setup_theme', 'my_block_theme_setup');

Loading Process of Block Theme Templates

Template Hierarchy in Block Themes

Block Themes utilize a block-based template hierarchy, which differs from traditional PHP-based themes. The hierarchy determines which template file to use based on the type of content being displayed.

  1. Template Selection: When a page is requested, WordPress determines the appropriate template from the block-templates/ directory based on the query (e.g., single post, archive, page).
  2. Fallback Mechanism: If a specific template isn’t found, WordPress falls back to more generic templates, ensuring that the site always has a layout to display content.

Loading Template Files

  1. Main Template Files: WordPress loads the relevant HTML-based template file from the block-templates/ directory (e.g., single.html for single posts).
  2. Template Parts: Within these templates, reusable template parts are loaded from the template-parts/ directory. For example, header.html and footer.html are included in multiple templates to maintain consistency.
  3. Nested Blocks: The templates use nested blocks to define sections and layouts. For example, a group block might contain columns blocks, which in turn contain individual content blocks.

Rendering the Blocks

  1. Block Parsing: WordPress parses the blocks defined in the template files, interpreting the HTML comments that define block boundaries and attributes.
  2. Server-Side Rendering: For dynamic blocks (blocks that require server-side processing), WordPress executes the necessary PHP callbacks to generate content.
  3. Client-Side Rendering: Static blocks are rendered directly on the client side using the defined block structure and styles from theme.json.
«
»

Leave a Reply

Your email address will not be published. Required fields are marked *