Tutorials

Using Components to Improve Your WordPress Development Workflow

Elvis Krstulović

Notice! This is a long-read, and some sections might be considered opinionated. If you are looking for practical tutorial only, scroll to the bottom and watch the video where I show how Builderius components work.

A typical modern website is a fairly complex project. It contains many layouts and behaviors that need to be consistent in design while providing enough variety to keep the visitor engaged with the website. In addition to this, websites change and grow over time. Entire new templates are introduced, and the existing ones are modified. Sometimes these changes are global. A brand color shifts a little, or typesetting is slightly modified. Other times a part of the layout is added or removed to introduce or retire a feature from the site. This means that the initial design can easily be an overwhelming assignment due to the sheer number of features and styles that need to be built for it, especially since one needs to engineer it with maintenance and scalability in mind. 

Styles can often be easily applied and changed, if done right, by a couple of CSS rules, and these will propagate over as many pages as these rules address. But the organization of CSS selectors can become quite complex in complex websites, and it can get hard to manage them efficiently.

This is, in part, the reason component-based development is so popular and is somewhat of an industry standard. In component-based approach, wherever possible, one looks for opportunities to reuse the code they have made and modify it where it’s needed to be optimized for reuse. At its core, using components, a developer makes a piece of code or functionality “encapsulated” or self-sufficient. As such, a component can be used in more places and becomes a step in breaking down the project into smaller parts that one can use to create more variety (different layouts) while controlling and modifying them consistently.

The advantages of component-based development manifest in the application and website development in so many areas that we can see it becoming an integral part of various tools and technologies across the industry. In the JavaScript ecosystem, almost all relevant libraries and frameworks use it: React, Vue, Angular, etc. In design, tools such as Figma, Adobe XD, and the promising newcomer Penpot all recognize the component-based approach as the best practice. In low-code tools for site building WebFlow, Editor X, Framer, or an app builder Bubble all use components in their workflow. Even modern WordPress core is moving in this direction with the Gutenberg blocks, which are components themselves1.

Give me a simple example of a component-based pattern!

A screengrab showing a typical horizontal website header, consisting of logo, navigation and a search bar

Let’s take an example of a header row. A horizontal strip usually appears on the top of the website and contains several elements. A logo, navigation (a list of links), perhaps a button, and/or a search form. One could make this header so that it is added to each page as a part of the page where any change to its structure later would have to be applied to each page where it appears. 

This is why we have invented template parts.

Template parts allow us to make the header once and then include it in any place where it is needed. This means we can change some property of the header, and the change will appear on any page where it has been included. Then the template part can also have some conditional display rules where some part of the header can show or not depending on some rules we set. This has been a basic premise of the WordPress templating system we all know and love. But this has its limitations too.

Template parts are not really flexible. Typical template parts are the header, content, sidebar, and footer. And this works in many cases in that it provides an easy-to-edit system where maintainability is somewhat accounted for. We can edit any template part, and the change will propagate across the sites. But this system is rigid, and it is hard to create a variety using this approach as it is insufficiently modular. So we have page builders (or the Gutenberg blocks provided by the core). These provide us with more flexibility. One can create any layout using them, but we lose on the maintainability and consistency aspect. These builders often promote local edits and make each element unique. The result is hard to maintain as the site grows its complexity grows.

Enter components

Screengrab showing a table of components that comprise a header

If we return to an example of the header. Instead of making the header a monolithic element, we may break it down into several components: the logo, the navigation, the buttons, and the search form. Each of these will become an isolated component that can be used and reused in various places across the site. For instance, a search can be used in the header and/or the sidebar. Buttons can also be used somewhere in some sections on some pages. A logo may be used in the footer as well.

If we do this, the header becomes simply one of the wrappers for these components, the same as the footer, or some of the content template parts can become. These components used in the header can now be used to build more layouts. And we can keep creating components from other elements of site design where ever we see a potential for reuse. We can go with this componentization where it makes sense for the project.

An approach to this process can be to ask yourself, will I need to reuse this element in other places later? If yes, make a component. If the answer is maybe later. Leave it for now, and you can make it later. If the answer is no, do not make a component out of it.

The header itself becomes more flexible in this scenario, as now we can start changing it by adding, modifying, or removing its parts depending on the context in which it appears on the site. This will allow for a more dynamic and flexible website without losing its maintainability or scalability. In fact, these will improve with this process. 

How do components work? A high-level overview

A Figma "tooltip" component master with several variants pointing to top, right, bottom or right.
A Figma tooltip component master with 6 variants, from Builderius UI redesign file.

Components consist of a master and a reference. Master is a template where everything about the said component is defined, including the HTML structure, CSS and JS assets, dynamic data query logic, etc. Conversely, a component reference represents an instance where it should appear, it simply points to that master for all the aspects it should display, the HTML, CSS, etc. In a typical website, for each component, one will have one master and multiple references spread across various templates. If any modification to a component should be done, it is typically done by modifying the master. An important part of a component is variants. This allows a developer to change some behavior, parts of HTML structure, or appearance based on some conditions. For instance, on the homepage, the header can have different appearance or HTML elements than on the rest of the website. The rules for this are defined in the master component as well, and they can be made controllable in each instance by exposing some of the parameters2.

Simplification proposition of components

A screengrab showing a simple search bar component with the html structure in Builderius UI. Component consists of only 3 html elements.
A search component in Builderius builder

Components have an additional benefit to them. They help simplify the development process. It is simpler to develop a dedicated component than an entire template. In component-based development, most of the time, you are working in a simple context, a card, a search bar, a logo, or a meta section of the post. The component only HTML, CSS, and JS are typically simpler to handle than that of the entire website. This also often means that CSS is so easy to manage that the developer does not need a framework or a carefully thought out naming convention for their selectors and rules since most of the classes and corresponding CSS rules are contained in their own scope, the component in question.

How maintainable is such CSS, and how about performance?

Components are encapsulated — the HTML, data, and CSS are inside them. This means that the role of CSS classes, in part, becomes the role of the components themselves. We use CSS class-based selectors to apply style once and then attach it to any number of HTML elements via a class attribute. But if components have a master that controls the instances from one place as well, then this need is already served. Note, it is not that one does not need CSS classes anymore, they just carry less weight in the life of the website as they live in this compartmentalized space and are inherited via the component system rather than CSS itself.

Performance-wise, what this means is that CSS that gets loaded will always be just the CSS that is used at that moment, without the need to test whether a CSS rule has been used by an element or not. It’s simply there, or it isn’t.

Therefore components allow the site to grow, a developer to work simpler and faster, and to grow their component library over time, so they can reuse them across multiple websites.

Components fundamentals in Builderius

What follows is a video that demonstrates how components work in Buildeirus site builder and how this improves the site-building experience in WordPress. This demo might be interesting to users of other low-code tools and front-end developers looking for a way to develop sites with WP as a CMS while retaining their mental models working in the modern workflow as they are used to with their front-end framework o choice.

1. In my view current Gutenberg implementation of components works better for content creation than site development, but that is the topic for another article. 

2. Builderius does not have this feature yet. In our case, component variants can only be controlled by the master using some logic that takes its value from the template in which the component reference is placed. But this additional flexibility is something we are working on.

All posts