Adding sections or headings to WordPress Menus – Making use of the walker_nav_menu_start_el filter

The WordPress menu builder makes it easy to add nested menu item links to a named menu, and display it in pre-defined theme location. However, as of writing in Jan 2019, there’s not an easy or built-in way to add menu sections or section headers. Here’s my solution:

The Design

Example visual to be recreated as a WordPress menu
Example visual to be recreated as a WordPress menu

The adjacent image shows the design that I’ve been asked to translate to a WordPress native menu. The orange items are page links. The white items are section headers and should not be active in any way. They are simply visual cues to aid navigation.

The Challenge

‘Out of the box’ WordPress doesn’t provide a place for menu section headers like ‘Services’ and ‘Products’ to be entered. It is possible to add them based on a menu item’s class or ID using the CSS ‘content‘ property, or an absolutely positioned image, but this is tacky and hard-coded, so site owners and admins can’t easily change the menu section headers without a developer type person or some Additional CSS hackery.

We need to find a way of adding section headers that uses the WordPress menu builder and remains editable.

Hidden Options

In many WordPress admin screens there is a Screen Options link/tab/button, usually at the top right. The options available depend on the item being edited. In the Menu Builder, there are several ‘Advanced menu properties’ available, and the one we want is ‘Description’.

Description setting in Screen Options area
Description can be enabled under the ‘Screen Options’ tab in the edit screen.

Once ‘Description’ is selected, a new field will be available when editing a menu item. For our example design we want a section header called ‘Services’ to appear before the ‘Investigative Consulting’ menu item, so “Services” is entered into the description, and the menu us saved/published.

Description field in menu builder
Entering the desired section name in the newly activated Description field in the menu builder

The section head is now part of the menu object but without further theme modification, it won’t appear anywhere.

Theme Mods

Next we want to modify the WordPress theme to allow our description to show in the menu as a section header. To do this we’ll be editing the theme functions.php file.

Many articles aimed at modifying WordPress menu output suggest using a custom ‘walker‘ class . This would work, but it’s overkill for what we’re doing. The walker_nav_menu class applies a filter called walker_nav_menu_start_el and that’s what we’re going to use instead.

The Code

The walker_nav_menu_start_el filter can edit each menu item’s “starting output” i.e. the menu link element (<a ... > </a> etc) and any ‘before‘ and ‘after‘ attributes which have been set when the menu is called. For a discussion of menu attributes, see the wp_nav_menu article.

By adding the following code to the functions.php file of the active theme a span containing the menu item’s Description is placed before the menu link when the menu is rendered:

// somewhere in the theme's functions.php file

function mqf_menu_descriptions( $item_output, $item, $depth, $args ){
    if ($depth == 0 && $item->description) {
        $item_output = '<span class="menu-item-description">' . $item->description . '</span>'.$item_output;
    return $item_output;

add_filter( 'walker_nav_menu_start_el', 'mqf_menu_descriptions', 10, 4);

The if statement checks that the menu item is a top-level item with $depth == 0 and also that a description is set.

If this filter should only effect menus in certain locations, i.e. ‘primary’, then the if statement might look like this:

if ('primary' == $args->theme_location && $depth == 0 && $item->description) {

The Output

description output before the menu item but unstyled Now that the filter is added, when the menu is viewed it should output the description that’s been set immediately before the menu item. In the example we started with it appears as white text (see the adjacent image).

In order to style it up a bit, the following CSS improves things:

.section_description {
    display: block;
    text-transform: uppercase;
    font-size: 1.4rem;
    padding: 0.6rem 0 0.4rem;
    color: rgb(240, 240, 240);

The final result with some more section headers and menu items added is shown here:

Finished menu showing styled section headers
Finished menu showing styled section headers.

Hope that’s helped someone. If you have questions, corrections or criticisms please leave a comment below. Or just let me know what you thought with a click/tap on a thumb: Nope, not helpful...Yep, more useful than not! - +1 thumb, 1 overall.

Remove all account data, stored mail and attachments from Postbox app (Mac OS)

The problem with stored Postbox data

I use Postbox, the Mail Client as a tool for checking problems with customer’s email accounts, and migrating mail data. When I have finished using it I don’t want to retain their data, nor do I want it taking up space on my machine. Just removing the ‘accounts’ doesn’t actually remove the data, it sits in Application Data forever (well maybe not forever, but a long time).

The solution might be user profiles

While searching for the location of stored mail data, I chanced across the Postbox Profile Manager. This allows complete profiles to be added and removed.

Enabling the Postbox Profile manager:

  1. Preferences > General > ‘Show Profile Manager on startup’ (tick checkbox).
  2. Restart Postbox.

Once restarted the following dialogue box will be shown:

Postbox profiles dialogue box

From here you can right-click on a profile name to delete the profile.

Beware: Deleting a profile removes all the account data stored in it. If the deleted profile is the main/default one, Postbox will think it’s just been installed and prompt you for account data at next startup.

An idea

Instead of sticking with one profile, deleting it when a body of work has been finished, why not add a per-job or per-client profile before you begin? Then at the end of work, the profile can be deleted without completely resetting Postbox:

A client profile added to postbox

If you’ve found this useful please let me know with a click: Nope, not helpful...Yep, more useful than not! (No Ratings Yet)
If not, please leave questions, comments or corrections below.

Manually verifying created users when using Laravel Email Verification

Laravel 5.7 ships with bundled Email Verification. This is great if you want to make sure a user’s email address is valid (or at least that the user can access it) before allowing them access.

What if you want to manually verify a user without sending them an email address? For example you might want to add or import a load of existing ‘known-good’ users to a migrated app. Or you might be creating Admin or System users that don’t really have accessible email addresses. There could be many reasons.

At present as soon you register a user, the sendEmailVerificationNotification method is called. There’s a good breakdown of how this works in this Stack Overflow answer. If a user is manually created, then when they try to log in they’ll still see the “Verify your email address” message:

Laravel's email verification message

Whether a user has verified their email address or not is indicated by a timestamp in the email_verified_at column of the User table¹. If this column is set to a valid timestamp upon user creation, the user will be ‘validated’ and no email will be sent. So… how can we set that timestamp?  Continue reading “Manually verifying created users when using Laravel Email Verification”

Fixing “[vue-loader] vue-template-compiler must be installed as a peer dependency”

Whilst attempting to upgrade an old Laravel project, I hit the following error.

Module build failed (from ./node_modules/vue-loader/lib/index.js):
Error: [vue-loader] vue-template-compiler must be installed as a peer dependency, or a compatible compiler implementation must be passed via options.

After some searching of GitHub and stackoverflow, it turns out that The vue and vue-template-compiler module version must be the same. Here was my existing package.json:
Continue reading “Fixing “[vue-loader] vue-template-compiler must be installed as a peer dependency””

Stop WordPress installing new bundled themes and plugins when the core is upgraded.

Problem: Every time WordPress updates to a newer major version it tries to install the newest default Theme too, i.e. WP5.0 arrived with the theme Twenty Nineteen.

In many – maybe MOST cases – we aren’t going to want this to happen on an existing WordPress installation, especially if you are already using a custom theme.

Solution: Thankfully there’s a config value to stop this happening. The value is:


…and if you add this line to your `wp-config.php` file (usually found in the root of your site) it will skip new bundles items when the core is upgraded, as the name suggests.

Please let me know if this post was useful with a click, be honest 🙂
Nope, not helpful...Yep, more useful than not! - +1 thumb, 5 overall.

Vacuum hose tee and better routing on the GT6

Problem: The routing of the vacuum hose on the GT6 is a bit poo. Actually I don’t know what it was like from the factory, but most engine bays I’ve seen recently have it draped around the rocker cover or across it, and that can lead to problems.

Solution: I wanted to fix the hose to one of the rocker shaft studs as a more secure solution but couldn’t find a suitable hose clamp with an appropriate drilling. Hence this:

Step one: Source a small brass tee, 4mm O.D, and some nitrile rubber hose to suit (eBay for both, £5 delivered).

Step two: Find something to clamp to the stud that can be bonded to the tee. I found that a solder terminal for an earth strap worked quite well.

Step three: Some two-part epoxy adhesive like Araldite does the trick. Here I used their ‘Rapid Steel’ offering which comes out looking a little like metal and is good for bonding most metals.

Step four: Fill the terminal with enough mixed-up adhesive to not spill out when the tee is pressed into it.

Step five: Press the tee into the terminal, making sure that it’s level and straight.

Step six: Support the items until they set. For Araldite Rapid this needed 45 mins undisturbed. For non-rapid types I believe it’s 24h.

Step seven: Fit to the engine! Happy with this. The tee holds the hose just clear of the rocker cover, and the short hose lengths either side don’t allow it to droop on the manifolds.

Please let me know if this post was useful with a click, be honest 🙂
Nope, not helpful...Yep, more useful than not! (No Ratings Yet)

Vacuum advance hose fix with WD40 nozzle

Problem: On a trip home from North Wales, the vacuum hose in my GT6 came loose and fell on the exhaust, melting and fusing it. Nasty sluggish acceleration  resulted.

Solution: I had no tools besides a knife and no spare hose, but DID have a small can of WD40 in the boot.  Continue reading “Vacuum advance hose fix with WD40 nozzle”

GT6 / Spitfire DIY alternator bracket improvement

Problem: Years back when I first did an alternator conversion on the GT6 the very rudimentary ‘pull it hard and tighten the nut’ fan belt tensioning method really annoyed me. It seemed there should be a way to achieve finite adjustment, and not risk noisy, slack or dangerously tight belt tension.

Solution: I don’t remember where now, but somewhere I saw a rigging screw (sometimes called a Turnbuckle). They are available in a load of sizes, lengths and materials from chandlers (sailing suppliers). So I used one of these to solve the problem. I then went on to sell them for a while on eBay under the name Mere Components. Continue reading “GT6 / Spitfire DIY alternator bracket improvement”

Flush the DNS Cache on Mac OS El Capitan (using a nice quick alias)

Updated June 2016: For OS X / 10.11 / El Capitan

Problem: I’ve updated some Name Server records on a domain and I want to check they’ve propagated using Dig. When I dig ns I keep getting the old results.

Solution: The local DNS cache on the machine needs to be cleared. As far as the OS is concerned, it’s already looked up that domain name and doesn’t need to do a fresh lookup until the domain record’s TTL (time to live) has expired.

On OS X 10.11 El Capitan there are two things needed. Firstly clearing the Directory Service cache and secondly forcing mDNSResponder to restart. This can be done using two commands in Terminal¹:

$ dscacheutil -flushcache
$ sudo killall -HUP mDNSResponder

Continue reading “Flush the DNS Cache on Mac OS El Capitan (using a nice quick alias)”

DIY Torque Wrench recalibration (with another one)

Problem: My old cheap Draper torque wrench was last used 7 years ago, and in that time I left it set to 40NM. Stoopid! Now I have no idea if it’s reading correctly and don’t want to risk snapping the studs on my head.

Solution: I borrowed a good (Digital Snap-On… oh my…) Torque Wrench from a mechanic mate to test mine against. Here’s the method that worked for me: Continue reading “DIY Torque Wrench recalibration (with another one)”