A WordPress theme should only contain that which relates to the look and feel of the site. Any core functionality belongs in a plugin.
A good rule-of-thumb is that anything a user would expect to keep after changing themes belongs in a plugin. This includes custom post types, taxonomies, custom metaboxes, shortcodes, and customizations to other plugins (like my Display Posts Shortcode snippets).
For specific functionality that’s reusable and/or the client might want to selectively disable, it’s best to build as its own plugin, like BE Events Calendar.
For everything else that’s project-specific but should be theme-independent, I put in a plugin called Core Functionality. Feel free use this as a starting point for your own core functionality plugin.
Jenny says
Hi Bill
Someone made custom changes to our original lifestyle theme version 1.0 things like content area wider, and side bars and all the aforementioned borders their colors and width and menu drop down style and look. They did the coding within the actual style sheet etc and possible sometimes php file maybe as well no doubt not the best correct way of doing such changes and wanted to know WHAT one SHOULD have done really when doing such things…
NOW, if I was to upgrade to lifestyle 2.0 latest everything will look different since we did a test view and the content words and images within the side bars all got totally jumbled and haywire……my FIRST question to you please is what would you say if we did want to upgrade to lifestyle 2.00 how best to go about doing it and where should such custom coding to have wider content side bars look etc be applied to in a way where any future upgrades won’t create the same problem – we have 4 sites all done using same Lifestyle version 1.0 right now and feel upgrading to any future versions we should perhaps be actually doing ? So as to keep everything future proof so to speak
I am not good with code but willing to make back ups and copy code once I know where to add it in what specific place or plugin you have that may aid and how to use etc.
many thanks
Bill Erickson says
Making changes to the look and feel of your site (making sidebars wider, changing font colors and sizes…) should always be done in your child theme. It sounds like your developer did it correctly.
Your child theme contains your site-specific design changes. When I build a site for a client using an existing child theme like Lifestyle, the first thing I do is rename the theme because we know we’ll be changing it.
Child themes are not designed to be updated. There is no upgrade path from Lifestyle 2.0 from Lifestyle 1. They are two completely different themes.
If you’d like to use Lifestyle 2.0, you’ll have to take the same approach you did with your first theme: Install the new theme, then hire a developer to make the changes you’d like made to it.
The core functionality plugin discussed in this post is for theme-independent features. That is, the things you would want to keep if changing to a completely different theme. The widths of sidebars belongs in a theme (design). Things like custom post types belong in a plugin (functionality).
I hope that helps.
Hans says
Great tip, Bill, makes sense. I was looking for a way to safeguard code I added to functions.php from theme-changes (having done it manually some times now), but was somewhat afraid to make my own plugins. I now find myself in serious danger of understanding the code you wrote, even the class and object you made, so I am probably ready to try it myself. I understand from the comments you now favor a normal plugin over mu-plugin, and since I don’t build for others yet, it would be the logical choice for me too.
One question. I have read you use the word rotator several times now, but am not sure what you mean by that. Is that just another word for (image)slider, or something more specific? And is the other word you use elsewhere “flex-slider” again something different, or the same? I might be missing some context here. If you would enlighten me, much appreciated. I understand it might be a bit of a newbie question, sorry for that.
Bill Erickson says
I use “rotator” interchangeably with slider and carousel to mean some form of rotating content. For a while I used Flexslider for building these rotators, but now I use Slick Carousel.
I’ve also started using the
wp_add_inline_script()
function rather than loading a separate Javascript file. See this example: https://www.billerickson.net/code/add-inline-script/Millo Lailang says
I always thought that too many plugins will make a site slower and use up all the server resources. But you have a point. Coding everything in the theme will cause rewriting of every customizations when changing the theme.
Will need to look into it further. Do you have any recommendations to avoid having the plugins use up server resource which cause database connection problems in smaller servers?
Bill Erickson says
The number of plugins installed has no effect on server resources. Whether the code is located in a theme, plugin, or 5 plugins doesn’t affect performance – it’s the code itself. One plugin with poor code can slow your site down, which is why it’s important to use high quality plugins that specifically target your needs.
Kostas Nicolacopoulos says
Hi Bill,
I’ve been using a forked version of your functionality plugin for years. Thanks for putting it together!
I noticed that you made quite a few changes to the plugin earlier this year. Can you explain why you removed metaboxes.php and CMB?
Do you not use CMB(2) anymore and do you add metaboxes elsewhere?
I know you also use ACF. Do you export the fields created in ACF to PHP so you can source control them? That’s what I usually do and keep them in the functionality plugin. Do you see any issues with that?
Thanks!
Bill Erickson says
I removed CMB2 because the code was out-of-date. When I use CMB2, I install the CMB2 plugin to ensure it’s always using an up-to-date version.
I tend to use CMB2 for most metaboxes, and ACF for very complex ones – specifically ones requiring tabbed content, or multi-section landing pages leveraging the Flexible Content field type.
If a site requires one ACF metabox and one or two others, I’ll tend to do everything in ACF just for simplicity. But I still only use it for post meta.
If a site requires an options page or term meta, I always do that in CMB2 due to the negative performance of ACF in those contexts. Term meta is stored as site options rather than actual term meta. And both term/options are all stored as individual fields rather than a single serialized array. AND they store 2 options for every 1 option you create (they have a separate one for identifying the field). So if you have a few fields including a repeater field on an options page, with CMB2 it is a single option in the DB. With ACF it could be close to 50 options.
Also, I never use the ACF frontend functions, and I disable ACF on the frontend. I noticed that even when no ACF functions were used on the frontend, ACF was responsible for most of the frontend load time on large sites with lots of content. Not sure why, but this was an easy fix.
James Burgos says
Hi Bill,
Does a CSS version of this concept exist? I’m a designer who “small d” develops and I have to say, I think the way styles.css is organized is abhorrent. I’ve been using style sheets in print and publication design via InDesign and Quark Xpress for 20 years. In that amount of time, while much has changed in how our tools work, the essential best practices for creating organized, clean and manageable stylesheets has mostly stayed the same. I understand how the cascade , nesting and specificity works but i feel that stylesheets would be easier to follow and manage if the toc was consolidated and broken out into individual files by context. The neverending traversing up and down the file along with duplication issues and all sorts of disarray drives me nuts. And this is coming from a man who likes to work efficiently. Any thoughts?
Bill Erickson says
Yes, what you’re describing is SASS. See SASS Basics and this article that describes how to structure a SASS project. Key benefits are:
Take a look at CodeKit (Mac only) or Prepos (Mac/Windows/Linux). I use CodeKit for processing my SCSS and JS files.
James Burgos says
That’s great. Just the impetus I need to dive into SASS, which I’ve been resisting. I think one of the reasons I’ve been resisting is because I’ve been thinking that I need to start completely from scratch. Is it possible to transition into SASS on an existing site without too much disruption?
thanks for the insights, Bill
Bill Erickson says
Yes, the transition can be as simple as copying your entire style.css file into style.scss (or whatever you want to call it).
It took me about 5 minutes to transition a site recently to SASS. The original stylesheet was broken down into logical sections, so I made each section a file in the “partials” directory. I then created a main.scss that included all those partials in the order they originally appeared.
James Burgos says
That’s good to know. I’ll let you know how it goes. Thanks, Bill.
Jamie says
Hi Bill, hope your great.
Have a question regarding ACF in a functionality plugin.
I’m building bigger sites now which almost exclusively use ACF for all content in page templates, (replacing the WP editor).
Currently I’m creating the desired page template (say page_team.php) ACf and markup goes in that. If it is a big page with lots of section, I’ll divide the markup into partials. (partials/team/team-section1.php) kinda thing.
But should I be putting my ACF + markup direct in the template, or should these be in a plugin, and use a conditional to check whether the template file exists, if so do the actions and hook in the ACF, if not, then just show the fields within the default WP page content.
That way, if the theme gets disabled or changed, any ACF content or images show within any theme page as normal.
Although some fields may be theme specific for aesthetics, like icons, background images etc, which would stay in the theme.
Hope this makes sense.
Bill Erickson says
When the ACF metaboxes and blocks are deeply entwined with the theme, I find it simpler to keep the ACF JSON files in there as well, rather than moving them to core functionality.
Gutenberg has increased the “grey area” between design and functionality, so I’ve been putting more of my functionality in the theme to keep it simpler and readable.
Vincent Tobiaz says
Sorry if this is here somewhere but it isn’t apparent. How do you use this plugin? I’m trying to use this plugin as per another comment of yours with adding a WPForms blacklist of email addresses. I don’t see anywhere to add the function code for that with this plugin after I installed it and activated.
Bill Erickson says
You should edit the plugin files and either add your code to an existing file, or create a new file and add it there.
It works the same as adding code to your theme’s functions.php file, except the code is now in a plugin rather than a theme.
Luis Colomé says
Hi there Bill,
I just wanted to say thank you. I’ve used your plugin in almost every proyect in the last months. It is simple, organized and great to keep functionality separete from Genesis child themes.
So I guess it is time for me to create my own Core Functionality Plugin based more on my needs.
Thanks again for your work.