Building Custom WordPress Blocks: A Personal Journey Using Bootstrap & Gutenberg

Update: 3/4/2025

The following blocks have also been added:

  • Carousel
    • Swiper
  • Content Wrapper
  • Enhanced cover block
    • Lazy loading options for the image and videos
    • Setting for the cover block background to extend past its container to the edge of the screen (left or right)
  • Tabbed Panels
  • Alerts

I’ve always been fascinated by how WordPress can be customized well beyond simple themes and plugins. Over the past few weeks, I decided to fully embrace Gutenberg’s block editor and Bootstrap 5. My goal was to create a set of dynamic, reusable blocks—including Rows, Columns, Accordions, and Modals—that could neatly snap into any WordPress site and offer advanced layout capabilities.

In this post, I’ll share how I brought these blocks to life, the components and files involved, and a direct link to my GitHub repository so you can explore the code yourself.


Why Custom Blocks?

As a longtime WordPress developer, I found that classic shortcodes or older page builders didn’t give me the crisp, integrated editing experience I wanted. With the Gutenberg (Block Editor) API and Bootstrap 5, I could:

  1. Leverage dynamic blocks (render.php) so the markup is generated on the server for full control.
  2. Use block.json and WordPress Scripts to structure each block.
  3. Mix the power of InnerBlocks for nested content and Bootstrap classes for columns, rows, accordions, and modals.

Breaking Down the Files & Structure

Each block follows a Gutenberg best-practice pattern:

  1. block.json – Describes the block (name, category, attributes, and references to script files).
  2. index.js – Registers the block, imports styles, and designates the edit and save (or dynamic render) behavior.
  3. edit.js – The React component used in the editor. This might have InspectorControls, FormTokenField for class selection, or a simple RichText for titles.
  4. render.php – For dynamic blocks, this file outputs the block’s final HTML with $attributes and $content.
  5. editor.scss & style.scss – SCSS or CSS for styling in both the editor and front end.
  6. view.js (Optional) – Handles front-end JavaScript if the block needs interactive behavior outside of Bootstrap’s own scripts.

Key Components We Created

  1. Row Block – A dynamic, Bootstrap-friendly <div class="row">. We set up custom token fields to allow margin, padding, align-items, and other classes—then merged them into a final additionalClasses attribute.
  2. Column Block – Manages column classes (col, col-6, etc.) with optional offsets, orders, or alignment. It too relies on dynamic attributes, uses InnerBlocks, and a render.php that merges all selected classes.
  3. Accordion & Accordion Item – A parent accordion block holds multiple accordion-item child blocks, each with collapsible content. We used InnerBlocks for the accordion item’s body. The items each have a title attribute, and they output a Bootstrap 5–compliant <div class="accordion"> structure.
  4. Modal Block – A dynamic block that renders a Bootstrap modal, including a header, body, and footer. It relies on an ID-based approach, so we can link to it using…
  5. Modal Button – A separate block (or variation of core/button) that sets data-bs-toggle="modal" and data-bs-target="#myModalId". By matching the modalId, the button triggers the modal’s display.

The WordPress Plugin & PHP Setup

All these blocks live inside a plugin structure. For instance, our main file (e.g., fs-blocks.php) registers blocks by pointing to folders in build/. Each folder has block.json, scripts, and a render_callback referencing a partial render.php. We also created a small settings page to toggle Bootstrap 5 loading in the editor or front end, ensuring everything is neatly integrated.

Render Callbacks:

  • We keep them in a separate render-callbacks.php file, each function named like fsblocks_render_row_block or fsblocks_render_modal_block.
  • For dynamic blocks, WordPress calls the relevant PHP function, passes $attributes & $content, and includes the appropriate render.php.

Explore the Code on GitHub

I’ve open-sourced the entire project here:
Custom-Blocks GitHub Repository

Feel free to clone, adapt, or star the repo. I’ve tried to comment each file and keep the code tidy so you can follow along. If you’d like to see additional enhancements—like more advanced token fields or different Bootstrap versions—pull requests are welcome!


Final Thoughts

Switching to a dynamic, Bootstrap-centric block approach has transformed how I build WordPress layouts. Instead of sprinkling shortcodes or wrestling with random editors, I can craft polished, snappy experiences natively in Gutenberg. I hope this little journey shows how a few well-structured block files, some smart attributes, and WordPress Scripts can give you a plugin that’s both developer-friendly and user-friendly.

If you’ve been curious about building custom blocks or integrating Bootstrap 5, I encourage you to give it a shot. Check out the GitHub repo, test the plugin, and let me know how it goes!

Thanks for reading—and happy block building!