Webflow dropdown menu to Wordpress nav menu

Hey all!

Do you think there’s a way to make the Webflow dropdown component works in my Wordpress nav? I tried selecting the dropdown element as “menu item with dropdown” but I get all sorts of glitches. Someone had this issue before?

image

1 Like

I have fought with this very issue for a long time and just gave up and used a plugin to recreate my Menus.

Webflow menus are only detected and converted if you have not included any dropdown elements. Even though Pinegrow says it will do it, I’ve found many other people who have mentioned that it doesn’t work. Maybe it’s some hidden setting or trick to make it work.

I can say that after wasted hours, I finally had to give up on this and do it via plugin to recreate the menu which sucks to have to depend on a plugin after all this… but at least the site works.

Menus are a beast to create without some sort of helper. Even a video of me making a super-simple one with alpine.js ended up being 95 minutes long.

Building Responsive and Accessible Navigation Menus with Alpine.js (youtube.com)

The best way to go if you don’t want to subject yourself to that, in my opinion, is to use a plugin like Max Mega Menu. It’s very configurable, reasonably priced, and is one of the only menu plugins that gets a nod from the accessibility community.

@Chimpojones @adamslowe

I have succeeded with the help of ChatGPT and some custom code.

Here’s my menu structure in Webflow, using unordered lists:

image

The HTML structure of a WordPress navigation menu typically uses an unordered list (<ul>) to represent the menu items. Each menu item is a list item (<li>) within this unordered list. If your menu has sub-items, they are usually nested within another unordered list inside the corresponding parent list item.

Here’s a basic example of a WordPress navigation menu structure:

<nav id="site-navigation" class="main-navigation">
    <ul id="primary-menu" class="menu">
        <li class="menu-item"><a href="http://example.com/page1">Page 1</a></li>
        <li class="menu-item"><a href="http://example.com/page2">Page 2</a>
            <ul class="sub-menu">
                <li class="menu-item"><a href="http://example.com/page2/subpage1">Sub Page 1</a></li>
                <li class="menu-item"><a href="http://example.com/page2/subpage2">Sub Page 2</a></li>
            </ul>
        </li>
        <li class="menu-item"><a href="http://example.com/page3">Page 3</a></li>
    </ul>
</nav>

In this example:

  • nav is the navigation section of your website.
  • ul with the class menu represents the main menu.
  • Each li with the class menu-item represents an individual menu item.
  • Sub-menus are nested within ul with the class sub-menu.

Here’s the custom code I had to use to make the dropdown menu animation:

// Wait for the DOM to be fully loaded
document.addEventListener('DOMContentLoaded', function() {
    // Select all dropdown triggers and dropdown menus
    var dropdownTriggers = document.querySelectorAll('.dropdown-icon');
    var dropdownLinks = document.querySelectorAll('.menu-link.has-dropdown');
    var dropdowns = document.querySelectorAll('.sub-menu');

    // Function to close all dropdowns
    function closeAllDropdowns() {
        dropdowns.forEach(function(dropdown) {
            dropdown.classList.remove('open');
        });
    }

    // Function to toggle a dropdown
    function toggleDropdown(event) {
        closeAllDropdowns(); // Close all other dropdowns first
        var dropdownContent = event.currentTarget.nextElementSibling;
        // Open the dropdown if it is not already open
        if (dropdownContent && !dropdownContent.classList.contains('open')) {
            dropdownContent.classList.add('open');
            event.stopPropagation(); // Prevent the click from reaching the document
        }
    }

    // Function to add hover and mouseleave listeners for desktop
    function addEventListenersForDesktop() {
        dropdownLinks.forEach(function(link) {
            link.addEventListener('mouseover', desktopHoverHandler);
        });

        dropdowns.forEach(function(dropdown) {
            dropdown.addEventListener('mouseleave', desktopMouseLeaveHandler);
        });
    }

    // Function to remove hover and mouseleave listeners for desktop
    function removeEventListenersForDesktop() {
        dropdownLinks.forEach(function(link) {
            link.removeEventListener('mouseover', desktopHoverHandler);
        });

        dropdowns.forEach(function(dropdown) {
            dropdown.removeEventListener('mouseleave', desktopMouseLeaveHandler);
        });
    }

    // Handler for hover event on desktop
    function desktopHoverHandler(event) {
        closeAllDropdowns();
        var sibling = event.currentTarget.nextElementSibling;
        // Traverse to find the corresponding submenu and open it
        while (sibling) {
            if (sibling.matches('.sub-menu')) {
                sibling.classList.add('open');
                break;
            }
            sibling = sibling.nextElementSibling;
        }
    }

    // Handler for mouseleave event on desktop
    function desktopMouseLeaveHandler(event) {
        event.currentTarget.classList.remove('open');
    }

    // Adjust dropdown behavior based on window size
    function adjustDropdownBehaviorBasedOnWindowSize() {
        if (window.innerWidth > 992) { // Check for desktop size
            addEventListenersForDesktop();
        } else {
            removeEventListenersForDesktop();
        }
    }

    // Add click event listener to each dropdown trigger
    dropdownTriggers.forEach(function(trigger) {
        trigger.addEventListener('click', toggleDropdown);
    });

    // Click outside any dropdown to close all dropdowns
    document.addEventListener('click', function(event) {
        var isClickInsideDropdown = Array.from(dropdowns).some(function(dropdown) {
            return dropdown.contains(event.target) ||
                   (dropdown.previousElementSibling && dropdown.previousElementSibling.contains(event.target)) ||
                   (dropdown.previousElementSibling && dropdown.previousElementSibling.previousElementSibling && dropdown.previousElementSibling.previousElementSibling.contains(event.target));
        });

        if (!isClickInsideDropdown) {
            closeAllDropdowns();
        }
    });

    // Listen for window resize events to adjust dropdown behavior
    window.addEventListener('resize', adjustDropdownBehaviorBasedOnWindowSize);
    adjustDropdownBehaviorBasedOnWindowSize(); // Initial adjustment based on current window size
});
  • The DOMContentLoaded event ensures the script runs after the entire DOM is loaded.
  • The adjustDropdownBehaviorBasedOnWindowSize function checks the window width and applies the appropriate event listeners based on whether the device is considered a desktop or not (based on width).
  • Event listeners for ‘click’, ‘mouseover’, and ‘mouseleave’ are managed to provide the correct behavior for dropdown menus.

CSS to show/hide the dropdown

/*nav dropdown*/
.sub-menu {
    display: flex;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.5s ease, visibility 0.5s;
    flex-direction: column;
}

.sub-menu.open {
    opacity: 1;
    visibility: visible;
}

This Webflow menu with dropdown is fully compatible and manageable inside WordPress. I hope this helps!

1 Like

Nice, trying to do the same here with a TW header block.

Did you use the Multilevel Option in the Menu Smart?

Screenshot 2024-03-11 at 10.02.17

Thanks

Yes I used it to target the class .sub-menu in my example code. You want to target your nested unordered list element.

1 Like