Menu Image Plugin + DevDmBootstrap3 Fix

This little plugin fixes the Menu Image plugin when used with the DevDmBootstrap3 theme.

Menu Image version 2.9.0 changed the way it displays images, breaking compatibility with DevDemBootstrap3. DevDmBootstrap3 uses a custom menu walker but does not use the nav_menu_item_title filter, so the plugin quit working.

One of my contract positions uses DevDmBootstrap3 for many client sites, so I wrote a basic plugin to get it working again.

Browse the code→

To use the plugin, upload the PHP file to your wp-plugins directory and activate the plugin. That’s it!

https://gist.github.com/macbookandrew/d40a416c65c615e0e15e1b6fd0645a67

Underscores Theme Multiple Menus

If you’re using the Underscores theme (also knows as _s) by Automattic, you may have tried to add multiple menus to the page and been frustrated when they don’t work on mobile.

Here’s a bit of Javascript to add to the theme’s navigation.js file to fix the issue:

https://gist.github.com/macbookandrew/74fd6dd1d101debcf6890778052609d4

Merge + Minify + Refresh Force Clear Caches

This plugin clears other page caches/proxies when the Merge + Minify + Refresh cache is regenerated so users don’t end up missing static resources (CSS/JS files) due to a cached page trying to load old static resources.

Get the code at the GitHub repository. Continue reading “Merge + Minify + Refresh Force Clear Caches”

Hosting WordPress inside a SilverStripe Installation

I ran into a puzzling issue today. Normally I wouldn’t recommend hosting a CMS inside another CMS installation, but for various reasons, I had to set up a WordPress blog inside an existing SilverStripe installation. For sake of this article, I’ll call it example.com/blog/.

The first problem I ran into was that instead of loading WordPress, example.com/blog/ was showing the directory index:

SilverStripe WP Directory Listing

That’s obviously not ideal, as well as being a bad idea for security.

I then added Options -Indexes to the WordPress .htaccess file to disable the directory listing, but all I got was a “403 Forbidden” error when going to example.com/blog/ or example.com/blog/wp-admin/ (however, example.com/blog/?p=1 would redirect to the post URL using pretty permalinks and worked fine 🤔):

SilverStripe WP directory forbidden

I then tinkered with the SilverStripe .htaccess file, thinking it was overriding something; I added this line to make it ignore the WP blog URLs:

RewriteRule ^/blog/?.*$ /blog/index.php [L]

Still no luck.

Finally, I thought to try manually setting the index file, so added this line at the top of WP’s .htaccess file:

DirectoryIndex index.php

And that did the trick!

There must have been a server-wide setting to use some other file for DirectoryIndex (that’s the file that gets served by default when you try to access a directory URL), but I didn’t have access to the entire server.

Summary

Here’s what I ended up using:

SilverStripe .htaccess file

RewriteEngine On
RewriteBase '/'

# Added for WP blog
RewriteRule ^/blog/?.*$ /blog/index.php [L]

# Process through SilverStripe if no file with the requested name exists.
# Pass through the original path as a query parameter, and retain the existing parameters.
RewriteCond %{REQUEST_URI} ^(.*)$
### Blog Redirect ###

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* framework/main.php?url=%1 [QSA]

WordPress .htaccess file

DirectoryIndex index.php
Options -Indexes

WordPress Theme Stylesheet Auto-Cachebusting

If you’re like me and you set up server-side caching, CloudFlare (or any other proxy cache), and/or long Expires headers on your theme stylesheets, you know the hassles that go into invalidating those caches and forcing browsers to load an updated version.

One method to force browsers to pull the new version is to add/change the ver parameter in the query string (WordPress’ wp_register_script, wp_register_style, wp_enqueue_script, and wp_enqueue_style have a built-in way of doing this).

Query Strings

Defining a Constant

Here’s how I used to do it: define a constant and then manually update that, as well as the Version header in the style.css file.

The main drawback is that I had to manually update the version number in two places: functions.php and style.css.

File Modification Time

Another method I’ve used at times is to add the style.css file modification time as the query string.

This has the advantage that the cache will be invalidated every time the stylesheet file changes. For some reason, I really never cared for it that much, though. It does add a tiny bit of performance hit, as the filemtime has to go get the file and figure out the timestamp.

WordPress Theme Version

I just read about this today and I think it’s going to be my go-to method in the future. It uses one of WordPress’ built-in theme functions to get the version number from the stylesheet.

This has a bit of overhead as well due to the function call, but I like the fact that it uses the theme version number so you can easily do Semantic Versioning.

Filename Modification

However, most performance testing tools will recommend you remove query strings altogether to improve caching especially by proxy servers. Here are two automatic methods of doing that:

File Modification Time

WordPress Theme Version

Conclusion

No matter which method you choose, setting up caching can greatly improve your site speed. It’s worth a little bit of hassle to ensure your stylesheets and scripts are cached, knowing that with any of these methods, you can easily invalidate those assets.

WordPress and Responsive Images: srcset and sizes Attributes

I’ve been puzzling over a performance issue on one of my sites lately and finally got it figured out today.

A custom shortcode uses the_post_thumbnail() to include a small image (~250px square); I have a bunch of custom image sizes set up, so the srcset attribute included 16 different image sizes. (Overkill? Maybe….) However, instead of using the image closest to 250px wide, Chrome was pulling in the largest available image—sometimes as much as 1500px! Obviously, this is terrible for performance.

In addition, certain pages had dozens of these images, multiplying the effect. My test-case page was 10+MB total (way too heavy…).

Here’s a sample <img> tag for one of my images:

I finally realized that the root cause was that the sizes attribute was set to “100vw,” basically suggesting to the browser that the image might at some point be rendered at 100% width of the viewport, so my browser was happily pulling down the largest possible image so it could display it in all of its high-resolution, hundred-KB glory instead of the scaled dozen-KB file.

Since I know this particular shortcode will only show images at a max width of 250px, I needed to set the sizes attribute to “250px,” hinting to the browser that anything slightly larger than that would be perfectly adequate.

Here’s how I handled it:

  1. Added a filter to wp_get_attachment_image_attributes and checked for a named image size or array
  2. If it was an array, I set the sizes attribute to that pixel size
  3. If it was a named image size, I set the sizes attribute to that pixel size

Sample code:

This approach admittedly is a bit heavy-handed and I’m still testing out the behavior on other pages on the site, but this fixed the problem with that specific shortcode, and my test page went from 10+MB to ~5MB—it cut my page weight in half!

The moral of the story is don’t “set it and forget it,” especially when adding responsive images using custom code.

Thanks to VIA Studio for their blog post that finally made the solution click for me.

Slanted Background Stripes

Why Eat Your Coffee? page
Sample effect

While working on a recent project, I needed to use angled background stripes on a number of pages.

Here are a couple of requirements that limited my options:

  • Angled stripes with text content and a background color and/or image
  • Angled stripes stacked on top of each other

Continue reading “Slanted Background Stripes”

WooCommerce Downloadable Products: Granting Permissions to Previous Customers

If you’re using WooCommerce to provide downloadable products and add a new download, previous customers do not automatically get access to it as of v3.x.

Here are a couple of options: Continue reading “WooCommerce Downloadable Products: Granting Permissions to Previous Customers”