WordPress Customizer: Supporting 600 Theme Options – a Case Study
Converting 600 Theme Options to the WordPress Customizer
This post describes the process of converting the traditional WordPress “Theme Option” interface of the Weaver Xtreme WordPress theme to the WordPress customizer interface. Beginning in the fall of 2015, the WordPress.org theme standards require that themes use the Customizer interface rather than the long-time, traditional theme Settings API for theme options.
When this change was announced in early 2015, there was a huge outcry of protest. Arguments against ranged from the difficulty in converting a lot of existing work, to the many perceived limitations of the Customizer interface, most especially the limited width and limited number of standard controls supported.
I must admit that I was among the many objectors to this requirement. After all, my theme has over 600 options, and that is a lot of code conversion. There is a “loophole” in the requirement – theme developers are allowed to use the legacy theme options interface via a theme support plugin.
That was my plan – add a few options via the Customizer interface to meet the basic requirement, but keep the legacy option interface via a plugin. In the end, that plan turned out to be only half right. You still can use the Weaver Xtreme Theme Support plugin to get the legacy interface. But, in the process of trying a few basic settings with the Customizer, I was converted, and ended up moving the entire option interface to the Customizer.
The newly released Weaver Xtreme Version 2.0 theme supports every single theme option using the Customizer. What happened? How did I go from one of the most strident objectors to the new requirement to become a total advocate? Well, as Samuel Wood (aka, Otto) put it in an e-mail to me – “It is one of those things you can’t un-see.” Bottom line, it is the WYSIWYG design paradigm, especially with “live update” options, of the Customizer that have become totally compelling to me. Moving the mouse over the color selector and watching it change instantly on the site preview is just something you can’t give up once you’ve seen it. Compared to the set a value, switch browser tab, refresh the page approach required to use the legacy theme options interface, watching your site instantly update is something that becomes impossible to live without.
The rest of this article describes the process of converting over 600 theme options to use the Customizer process. It definitely was not an easy process. The shear volume of Weaver options also exposed a serious problem with the pre-WordPress 4.4 code that led to a major change in the core customizer code for WP 4.4 that will greatly improve the Customizer performance of all themes using it. I also will address some other issues I have with the Customizer, and some solutions I was able to implement.
First, a little history of Weaver.
Weaver Theme – Let the user control the design
I created the first version of the Weaver WordPress theme back in 2010 based on one simple idea: any WordPress site creator should be able to totally control the design of their site without needing to know how to create custom CSS rules, write PHP code to create child themes, or understand the core WordPress code interface.
There are a whole lot of WP designers out there that think that that 600 options is completely out of line – that anything beyond a nicely designed basic theme should require the services of a professional designer who can create a custom theme requiring custom CSS and PHP code. I don’t agree. That approach can produce great sites, but if you look at a sample of the many thousands of Weaver sites, you’ll can see just how creative even a novice can get with a complete set of options.
Over the years, the original Weaver 2010 theme has evolved into the current Weaver Xtreme theme. In the process, a very large and devoted following for Weaver has developed, and there are probably over 100,000 sites using either the previous Weaver II version, or the current Weaver Xtreme version.
From perhaps a hundred or so options in Weaver 2010, with a steady stream of suggestions and requests from the Weaver user community, the latest version of Weaver Xtreme has over 600 selector, color picker, checkbox , or fill-in-the-blank options. That is a lot, and certainly has presented an interface design challenge on my part.
The Weaver Legacy “Theme Options” Interface
Ever since the beginning, Weaver has supported a traditional interface from the Appearance -> Theme Options menu. The options are organized into a section of tabs. The core set of options are on the “Main Options” tab, with further options placed on sub-tabs generally based on a “where” organization: Wrapping Areas, Sidebars, Header, Menus, Content, Posts, and the Footer. Under each of those area tabs, the options are organized into additional sub-areas and a menu at the top to jump to a sub-area. Finally, the actual options controlling “what” would be set are grouped under each sub-area. Almost all of the “what” options include an icon in the left column to help find the correct option.
In addition to the option values themselves, each option also includs a fairly detailed description of what the option does. Many closeley related “what” options such as font settings are combined into a tightly grouped set of related options. All of the options are laid out using the full width of the screen.
Converting to the WordPress Customizer
Just where does one start in converting more than 600 options in a large existing code base to totally new code for the Customizer? First, it took some motivation. I already described my Eureka! moment at seeing the magic of colors instantly updating in from the customizer. Once I was hooked, it was really a matter of just doing the work. The conversion took a bit over 3 months, and involved something over 7000 lines of new code – this for mostly by a single programmer.
How Do You Organize 600 Options?
The WordPress Customizer interface has some significant design limitations. First, it is somewhat limited in how wide it can be in the left column. While one can make it wider, there still must be room for the site preview on the right. So, this limitation inherently translates to a bunch of options stacked vertically in the column. The traditional interface demonstrated in the image above allows one to see many options is a relatively small vertical space. The legacy Weaver interface relies on seeing a lot of options on a single screen, and the ability to visually locate relevant options via the icons. The Customizer, on the other hand, does not allow very many actual options to appear at once – all that information (value, label, explanation) that was available horizontally now must be vertically aligned.
The second issue is that the number of built-in controls supported by the Customizer is somewhat limited. In addition, there is an expected style to the options that is wise to use a guideline for other options. It is possible to fairly easily build some custom controls, but for consistency, it is also good design to use the standard controls. This limitation, however turns out not to be the real issue. The real limitation is the vertical space required for showing more than 3 or 4 options at a time.
Fortunately, this vertical space limitation really applies only to controls. The Customizer allows one to organize actual setting controls under single line menus. The Customizer has 3 levels of interface components: a top level Panel, which is really a somewhat standard vertical menu. So, you can get quite a few (10 to 15) top level menu items to fit quite nicely and visibly on the first level of the Customizer interface. The second level is called Sections, and those serve as a sub-menu to the Panels, with the same feature: 10 to 15 easily accessible menu items organized vertically. Each Section serves as a host for actual Controls to set option values. Controls are things like color pickers, checkboxes, text input, etc. When the user opens a Section menu, they are presented with a vertical display of some number of options. Depending on the option, and the need for an option description, any specific option will consume anywhere from 3 or 4 “lines” of space, up to the entire visible portion of the Customizer vertical space. There is a vertical scroll bar to scroll to any of the options displayed in the given Section.
So how does one get 600 options to fit into the Customizer architecture in a fashion that any specific option is at most 3 clicks away? Obviously, it involves somehow organizing the 600 options into groups that logically belong in a section of a top level panel.
The design breakthrough for me was to realize that rather than the “where” area-oriented organization of the legacy Weaver option design, a “what” based hierarchy worked much better. So the top level of Weaver’s customizer interface is organized by “WHAT” – what kind of option does the user want to change (e.g., colors, spacing, typography, and so on). Under each WHAT top level panel is a section menu listing WHERE the what can be changed. Each WHERE menu is virtually identical for each WHAT selection. And at the bottom level of the menu hierarchy are the specific options that apply to each WHAT:WHERE location. The number of options vary somewhat at the bottom, and range from just one or two, to a more typical 10 or so options. A few sections have many more options that apply to specific areas.
But in the end, it really is quite easy for the user to drill down to exactly the option needed. In essence there are really only about 20 choices for the user to learn: 11 WHATS, and the same 10 WHERES under each WHAT. Once the user is at the proper option section, the consistent Customizer control option interface is present. Note that the top level set of panels will also contain some of the “standard” WordPress option sets such as Custom Menus, or customizer options from other plugins.
For example, this is the menu hierarchy to get to the color options for the site header area. Note the use of Dashicons to help identify each WHAT option level (the brush for colors, for example).
This option organization seems pretty good. There are still over 600 options, so it will still take a bit of a learning curve to find them all. But having the instant updating of the site preview makes the learning curve significantly easier than with the legacy theme options interface.
But this interface also demonstrates what is, in my opinion, a serious user interaction problem with the customizer interface. While it is easy to drill down to the options level, going back up the hierarchy can be somewhat difficult if the user needs to scroll down on the bottom options level – a very common occurrence. In that case, to go back up, the user must scroll the options section up, then click the < back button at the top of the column, then clikc once more to get back to the very top level of the Customizer hierarchy. This potentially means a scroll, click (up a level), click (up to the top level), click (down a level), and a final click to open the new options level – a somewhat tedious 5 operations. Most of this is caused by the up a level < button being scrolled off the top of the Customizer column.
To get around this annoyance, Weaver Xtreme has added a new “Quick Jump” menu at the top of the Customizer column on the “Save” bar. There is a new Menu button that opens a standard drop down menu with the standard top level WHAT items and the second level WHERE items that allows direct navigation to any set of options. As a side benefit, the Quick Jump menu also supports an alternative organization of navigation based on a WHERE/WHAT order.
Technical Details of the Conversion
This section is more oriented toward some of the technical issues involved with the conversion.
WordPress Customizer API Issue
From all indications, Weaver Xtreme, with its 600+ options, is making more use of the Customizer API than any other theme I can find. Certainly none of them even approach the total number of options supported. Not too far into the conversion, it became apparent that there was a serious code speed issue with the WP implementation.
The other, far more serious, problem involved a very elegant but flawed method of overriding the original theme setting values vs. the new, trial settings as set in the Customizer interface. Each option used by the Previewed view of the site is filtered to return the new value, and those new values sanitized. The original Customizer core implementation used a standard WP filter for each option. While elegant, the ALL filters were run every time an option was used. This turned out to be an exponentially growing computation. So, with say 40 options processed, that would result in 1,600 executions of the filters. A hundred options would be 10,000 executions, and so on. Thus, each refresh of the preview window would take longer and longer as more options were added to the Customizer interface. We’re talking about over 30 seconds of real time computation per refresh as the number of options went over about 300. Fortunately, there was a way to override the responsible Customizer PHP class for at least part of this behavior, and I was able to get the 600 options to refresh in just 7 or so seconds. Fortunately, after I reported this issue, the main WP core Customizer developer, Weston Ruter, found an alternate algorithm for this process, and the refresh panel now refreshes essentially instantly (a second or two) no matter how many options there are. This new code will be available in WP 4.4. Even though it was Weaver’s 600 options that demonstrated the need for a fix, the fix really helps all themes with more than even 20 customizer options, so this was big win for everyone, and will in the end save uncountable hours of combined time of users waiting for the preview to update. Thanks, Weston!
Live Update vs. Refresh
One of the features of the Customizer is that it supports two kinds of updating when a user changes a value of an option. The easiest is the Refresh method, which causes a full refresh of the preview window whenever a value is changed. This is often okay. But the Live Update (postMessage) method is just so much better for the user. Values change in essentially real time, so a color or margin or font family will change instantly. This is the real Wow factor in the Customizer.
For many options, it is fairly easy to implement Live Update via a bit of boilerplate jQuery code. Of course, with so many options in Weaver, this still amounts to thousands of lines of code to implement. And depending in the complexity of the option, it is not always possible to use jQuery to make the required live updates to the preview window, and the full refresh method is required. For example, the layout of sidebars requires extensive revision of the generated HTML output of the site, and refresh was the only reasonable way to accomplish this.
Even so, I made a huge effort to make as many options a possible to use Live Update. While this is really nice for colors, margins, font options, and others, it is especially useful for Weaver’s more advanced users who add their own custom css rules. Watching a custom CSS rule live update as you type the rule into the custom CSS box is just amazing.
Converting from Theme Options
For all the whining there was going on about the new required use of the Customizer, in the end, I personally found most of the complaints not really all that on target. Perhaps the most relevant was the need to rewrite any option interface to work with the Customizer. That indeed takes a lot of time to do right to take full advantage of the Customizer. In some ways, maximizing support for Live Preview was the most difficult, but also the most important.
But as far as limitations on the kinds of controls, or the width of the column, in the end I found these to be pretty much irrelevant. The real solution to making an interface work with the Customizer is to get a really good organization of the menu structure. Fortunately, after 5 years of input from thousands of users, I was able to build what I think is a logical and easy to learn option structure. I’ve looked at many other themes, and think that many of them could use a bit of revision in the logical structure of the menus to better take advantage of the Customizer.
And since most themes don’t have hundreds of options, I think the time to rewrite an options interface will not really be that long for most themes, while efforts to add full live preview will be well worth the effort. Live preview supported by the Customizer is really at the heart of an enhanced user experience, and its uses should be the main goal of any theme using the customizer.
Inherent Navigation Usability Issue
As I described earlier, the Customizer has an inherent design/usability issue. While it is fairly easy to navigate down the menu once on the top level, it can be quite tedious to navigate back up and then back down again. This is mostly caused because the “back” button scrolls off the top of the Customizer window if the user has scrolled down to look at options. What would help would be to have the back button on the top Save bar, or to not have the Back button scroll off. As noted, my solution was to add a complete “Quick Jump” drop-down menu at the top. I think a menu like this could easily be dynamically generated based on the current panel/section/options hierarchy, and something like it would greatly enhance the usability of the interface.
Initiating non-Customizer Actions from inside Customizer
One of the very frustrating missing features of the Customizer control API is an easy way to initiate “outside”, non-Customizer actions from within the Customizer interface. Weaver Xtreme has an excellent example of this – saving and restoring settings to/from the user’s computer. This is not particularly difficult, but does require the proper response to clicking a Save or Restore button in the interface. Finding a work around for this was quite complex, involving dynamically creating forms via jQuery, creating custom nonces, and triggering a full browser refresh.
Hybrid Preview Refresh
There are instances where a live (postMessage) update works really well, and easily most of the time, but on some special cases is unable to easily modify the DOM correctly. It would be really great to have a way to force a preview refresh from the postMessage jQuery script in some instances. The transport would be ‘postMessage’, but the actual ‘postMessage’ hander should be able to trigger a refresh as needed.
EDIT: This functionality is available now. Please see this article: Implementing Selective Refresh in the Customizer