The Linux Page

Wordpress Twentyseventeen Theme Menu hidden by default!?!?

Screenshot of a Wordpress website with the problem fixed.I have a website where I use Wordpress as the CMS. It's good enough for that website (frankly, unless you just want a blog, it's rather limited to my point of view, but I'm crazy... that being said with the pages functionality of today, it's not that bad.)

In 2017, they created a theme called Twentyseventeen, which looks good and has most of the functionality I need. However, there is a huge bug:

The front page has a smartphone menu at the bottom of the page which opens HIDDEN. That's just plainly wrong. Either you put the menu at the top or you make sure that the menu gets shown, somehow.

Since I'm a programmer (at times I forget) I decided to look into it. I added a piece of code in the navigation.js script.

WARNING: to make changes to a theme, it is better to create a copy with a new name. In my case I called the copy twentyseventeen-child.

cd .../wp-content/themes
mkdir -p twentyseventeen-child/assets/js
touch twentyseventeen-child/style.css
touch twentyseventeen-child/functions.php
cp -i twentyseventeen/assets/js/navigation.js twentyseventeen-child/assets/js/

Notice that I create a style.css and functions.php files too. These are required to create a child theme. The style.css file must include a declaration:

/*
 Theme Name:   Twenty Seventeen Child
 Theme URI:    https://example.com/twentyseventeen-child/
 Description:  Twenty Seventeen Child Theme
 Author:       John Doe
 Author URI:   https://example.com
 Template:     twentyseventeen
 Version:      1.0.0
 License:      GNU General Public License v2 or later
 License URI:  https://www.gnu.org/licenses/gpl-2.0.html
 Tags:         light, dark, two-columns, right-sidebar, responsive-layout, accessibility-ready
 Text Domain:  twentyseventeen-child
*/

And the functions.php must have a function to load the styles:

<?php
function twentyseventeed_child_styles() {
    wp_enqueue_style(
        'twentyseventeen-style',
        get_template_directory_uri() . '/style.css'
    );
    wp_enqueue_style(
        'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        array( 'twentyseventeen-style' ),
        wp_get_theme()->get('Version')
    );
}
add_action( 'wp_enqueue_scripts', 'twentyseventeed_child_styles' );

Now I would edit the navigation.js file in the copy.

Search for the function that looks like this:

menuToggle.on( 'click.twentyseventeen', function() {
    siteNavContain.toggleClass( 'toggled-on' );

    $( this ).attr( 'aria-expanded', siteNavContain.hasClass( 'toggled-on' ) );
});

And after the $( this ).attr() call, add the following code:

if(siteNavContain.is(":visible")) {
    // make sure it is in view
    //
    var y, screen_height, max_y, scroll_top;
    y = siteNavContain.offset().top;
    //y += 50;
    screen_height = parseFloat(jQuery(window.top).outerHeight());
    max_y = y + siteNavContain.outerHeight() + 5 - screen_height;
    scroll_top = parseFloat(jQuery(window.top).scrollTop());
    if(scroll_top < max_y) {
        $("html, body")
            .stop()
            .animate(
                {
                    scrollTop: max_y < y ? max_y : y
                },
                1250,
                null,
                null);
    }
}

This block of code first checks whether the menu is now visible. If so, it calculates the bottom location of the menu and scrolls the screen accordingly if that bottom is not visible. The scrolling uses the animate() function.

IMPORTANT NOTE: The y += 50; line is commented out by default. Remove the two '/' if you add an add or AddThis at the bottom of the screen. I like to have AddThis because that way people tend to share my content a lot more. That is 50 pixels tall. Most of the things people add  there are going to be about 50 pixels tall. You can, of course, adjust that amount to more or less than 50 depending on your situation.

And finally I would install the child theme as the current theme in my wordpress website. Now the menu works as one would expect!

The var declaration could be done just after the function declaration, but with ES6 and ES7 coming out, it does not matter much. The newer versions of JavaScript properly support sub-block variable declarations.

I've Done All Of That And It Doesn't Work?

Well... That happens.

A WordPress theme may fail for many reasons.

First, go to your front page, right click, and select View Source. A new window or tab opens with the source.

Search for "navigation.js". It should be there for twentyseventeen, no matter what.

If the path to navigation.js says ".../twentyseventeen/..." instead of ".../twentyseventeen-child/..." then you may not yet have selected that new child theme as your current theme. Without that, obviously it's not going to select the new navigation.js file which is required for the scroll to happen.

Okay, assuming you have selected the theme, you should see some reference to the new theme. First you could search for the style.css file and make sure it is the one in the ".../twentyseventeen-child/..." that is currently included.

If you have the correct style.css included but not the correct navigation.js file, then check that you properly spelled the sub-path.

  • "assets" (plural)
  • "js"
  • "navigation.js"

Don't laugh. We all make mistakes when we type and it's not impossible that one of the filenames is wrong. If you did copy/paste from my page here, you should be good, though.

Finally, you may have a cache in place. That cache would possibly prevent the new theme from completely appearing because all the functions don't get called when a cache is present. In this case, clearly the cache(s) should resolve the issue.

If you are using an external cache, such as Cloudflare, then you want to reset that external cache too. Maybe even turn it off until your setup functions as expected.

Note that the menu scrolling is only going to be active on the front page. The other pages should not require it, unless your menu is really long. So if you have the ability to only clear the front page cache, try that first.