Five common WordPress patterns I avoid

I write quite opinionated front-end code. It’s one of the advantages of working in the industry for around twenty years, I know what does and doesn’t work. Working in a rapidly developing industry long term has taught me to be open-minded too, to listen to new ideas and to be prepared to adapt them. I’ve learnt the only constant is change.

That said, despite my opinions I dislike declaring something an anti-pattern or is considered harmful. If there was one function in WordPress I could rename, it would be doing_it_wrong.

The five common WordPress patterns that follow are five patterns I avoid when developing themes and plugins. Below I explain why I avoid them, I’d love to know which of these ideas work for others.

Default body and post classes

WordPress’s default body_class and post_class functions return a large number of HTML classes by default.

Taking this post as an example, the default body class would be single single-post postid-3198 single-format-standard and the default post class would be post-3198 post type-post status-publish format-standard hentry category-code tag-wordpress.

None of these class names match my naming convention, so I like to strip them down substantially. I prefix my body classes with t- (for template) and aim to reduce the classes to either t-List or t-Singular. You can find the code for this in an earlier post on controlling the body class.

The post class gets a similar treatment, although it is reduced down to the component name I have chosen for the site and any required microformats class. On this site I start with Article, hentry and h-entry (microformats 2).

Using microformat classes for styling

Microformats are class names Google and other popular search engines use to understand the data on a web page. A list of posts will contain several hentry blocks to indicate each post, and each post will contain an entry-title to indicated the post’s title.

A common example for styling these is to attach the styles to the microformat class:

.entry-title {
  font-size: 1.5rem;
  margin-bottom: 0;
}

As search engines support multiple forms of structured data, I like to treat the microformat classes as hooks for the search engine only. Down the track, should I decide to replace the microformats with schema.org, the microformat classes can be removed without the need to alter the CSS.

Testing the body class for JavaScript conditionals

Some of the most useful PHP functions in WordPress are the conditional tags; is_single() and is_front_page() (to name two of many). Most of these conditional tags are reflected in the body class, i.e. is_single() adds the single class and is_front_page() adds the home class. Unfortunately, these functions have no JavaScript equivalent. As a result, you often see code testing the body class as a proxy:

isSingle = -1 < document.body.className.indexOf( 'single' );
if ( true === isSingle ) {
  // do stuff
}

As themes and plugins can filter the body class, it’s not possible to be 100% certain the presence of body.single matches the output of the PHP function is_single(). In most cases it probably does but I don’t like to depend upon a probability.

Instead, I use the JavaScript localisation features of WordPress to pass such tests directly from PHP to JavaScript. For an enqueued script with the handle pwcc-functions, the result will be:

wp_localize_script( 'pwcc-functions', 'pwccConfig', array(
  'is' => array (
    'single' => is_single(),
  ),
) );

As a nice side-effect, in JavaScript the test becomes clearer:

if ( true === pwccConfig.is.single ) {
  // do stuff
}

This approach is less likely to result in errors if a theme or plugin changes the body class in ways that haven’t been considered. It’s coding defensively.

Just use jQuery

If a script depends on jQuery in WordPress, it needs to list it as a dependency when registering or enqueuing it:

wp_enqueue_script(
  'pwcc-functions',  // handle
  '/path/file.js',   // source
  array('jquery'),   // jQuery
  '20150530-31',     // version
  true               // load in footer
);

This actually enqueues two external files, jQuery and jQuery migrate. jQuery migrate adds a backward compatibility layer that may not be needed for your site.

For reasons of backward compatibility, WordPress loads jQuery and jQuery migrate in the HTML header. Each file blocks rendering of your site and slows it down for your visitors. Allowing jQuery migrate to load will slow it down further.

If you maintain your JavaScript to avoid deprecated jQuery functions, you can remove the reliance on jQuery migrate and save your visitors an HTTP request by listing jquery-core as a dependency.

In general, I think there is an over reliance on jQuery and other libraries in web-development but that’s a story for another day.

Starting with more than two templates

As the section on the body class indicated, I consider WordPress themes to be constructed of two main templates: a singular template covering pages, posts and attachments, and a list template covering archives, the blog index and search results.

My themes start with singular.php (introduced in WordPress 4.3) and index.php.

A complex theme may require additional templates, in which case I will build up the theme rather than start with complexity built in.

What are your practices?

These are the common patterns I avoid, it’s what works for me. My approach is to start simply, to code defensively and to build up from there.

Leave a comment letting me know what works for you. If you think something on the list above is doing_it_wrong (for want of a better name), tell me why. I can learn from other’s experience as much as my own.

5 thoughts on “Five common WordPress patterns I avoid”

  1. Pingback: Thorsten
  2. Before entering into WordPress Theme business, I’ve researched and went through couple of iteration of what should I practice for a premium themes. While my initial thoughts match your preference, I found,

    Striping body classes isn’t a good choice for a Theme Author since many plugins depends on them. I don’t like it, but keeping them intact is the way to go, with adding few more, while keeping the additional classes as low as possible- means eventually, me too started using defaults classes for CSS/JS.

    I think Microformat is a mandatory part now a days for a Site due to Search Engines loves it- while styling using those classes, I prefer to reference with a parent class. This helps to target specific class while reusing same pattern for all my themes.

    If I were to develop a site which would controlled entirely by me, your lists is a good one. Thanks for the article.

  3. The term “theme” can cause confusion, because it can mean a theme meant for large distribution (i.e. premium, hosted on WordPress.org,…) or a specific theme created for a particular site.

    I used to be much stricter and “do it by the book” when it comes to both types. However with experience, I found out that when it’s your project you can pretty much do whatever you want. You are the developer, and able to figure out when going off the beaten path of best practices is not working out like you expected.

    But when it comes to themes meant to run on a large number of disparate sites, with additional customization introduced via Custom CSS, child themes, or other plugins then all these tips–except the last one–don’t work out.

    First of all, because a lot of code is going to expect things being how they are out of the box, and if they aren’t there then weird things can happen.

    Only using microformats for search engines is nice, but users likely won’t make that distinction. In general you should not change classes or markup once a theme is released because additional user generated CSS is going to rely on it. I also think that when you go through the trouble of changing the schema of the microformats, you can handle a bit of search-and-replace in the CSS. Finally I’m not a fan of having two classes if I can have one, so I use what’s there, even if it has a larger significance than just being a styling hook.

    When it comes to templates, having more is better, because conditionals inside templates make code difficult to read. Sure, various archive views often look the same, but that’s where template parts come in. You can look at how _s does it.

    Front-end development in WordPress, just like the back-end development, can be difficult to get used to, just because the software is so wacky. But those who have worked a lot with themes, and I’ve done pretty much nothing else for the last two years, know that the most efficient way is to let WordPress do as much work for you as possible, and stay on the cow paths.

    1. I agree, there is a nuance to avoiding these common coding patterns. I use the word avoid because a concrete declaration these patterns should never be used is harmful to development.

      Avoiding jQuery migrate may require a version_compare to ensure jQuery is in the same branch as when the code was last checked against deprecated functions.

      Passing the results of PHP conditionals to JavaScript in place of testing the body class is probably unsafe if WP_Query has been altered.

      In many case, you are right, it’s probably safer to add to the body classes rather than reset them. It’s a case by case consideration, rather than a hard rule.

      1. Agreed. However, when you do have 100% control of plugin usage and are not distributing the theme, these recommendations are f-ing rad. Thanks Peter!

Leave a Reply

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