DDSmoothmenu键盘箭头键失效及长菜单超出页面问题求助
Hey there! Let's tackle those two ddsmoothmenu issues you're facing—keyboard arrow navigation not working, and long <li> lists overflowing the page. Here's how to fix both problems step by step:
1. Adding Keyboard Arrow Key Support
DD Smooth Menu doesn't include native keyboard accessibility by default, so we'll add custom JavaScript to handle arrow key navigation, focus management, and activation.
Step 1: Ensure Focusable Elements
First, confirm all menu links (<a> tags) have tabindex="0" (they usually do by default, but double-check if any are missing). This makes them reachable via tab key.
Step 2: Implement Keyboard Navigation Script
Add this script after your ddsmoothmenu initialization code:
document.addEventListener('DOMContentLoaded', function() { const topLevelLinks = document.querySelectorAll('#divMenu > ul > li > a'); let currentFocusIndex = -1; // Handle keydown events on top-level menu items topLevelLinks.forEach((link, index) => { link.addEventListener('keydown', function(e) { switch(e.key) { case 'ArrowRight': e.preventDefault(); currentFocusIndex = (index + 1) % topLevelLinks.length; topLevelLinks[currentFocusIndex].focus(); // Open submenu if it exists openSubmenu(topLevelLinks[currentFocusIndex]); break; case 'ArrowLeft': e.preventDefault(); currentFocusIndex = (index - 1 + topLevelLinks.length) % topLevelLinks.length; topLevelLinks[currentFocusIndex].focus(); break; case 'ArrowDown': e.preventDefault(); // Open current submenu and focus first item const submenu = this.parentElement.querySelector('ul'); if (submenu) { submenu.style.display = 'block'; const firstSubLink = submenu.querySelector('li > a'); if (firstSubLink) firstSubLink.focus(); } break; case 'Escape': // Close all submenus and return focus to current top-level item closeAllSubmenus(); this.focus(); break; case 'Enter': case ' ': e.preventDefault(); // Trigger click action for the link this.click(); break; } }); }); // Handle focus entering the menu container document.querySelector('#divMenu').addEventListener('focusin', function() { if (currentFocusIndex === -1) { currentFocusIndex = 0; topLevelLinks[0].focus(); } }); // Helper functions function openSubmenu(link) { closeAllSubmenus(); const submenu = link.parentElement.querySelector('ul'); if (submenu) submenu.style.display = 'block'; } function closeAllSubmenus() { document.querySelectorAll('#divMenu ul ul').forEach(sub => sub.style.display = 'none'); } });
This script handles:
- Left/Right arrows to navigate top-level menu items
- Down arrow to open submenus and focus the first submenu item
- Escape to close all submenus
- Enter/Space to activate menu items
2. Fixing Overflowing Menu Items
When dropdowns extend beyond the viewport, we need to dynamically adjust their position to keep them visible. Here are two approaches:
Option 1: Modify the ddsmoothmenu Plugin Code
Find the section in ddsmoothmenu.js where submenus are positioned (look for code setting left or top styles). Add this logic to check viewport boundaries:
// For horizontal menus (orientation: 'h') const viewportWidth = window.innerWidth; const submenuWidth = submenu.offsetWidth; const parentRight = parentItem.getBoundingClientRect().right; // Flip dropdown to left if it would go off the right edge if (parentRight + submenuWidth > viewportWidth) { submenu.style.left = `-${submenuWidth - parentItem.offsetWidth}px`; } else { submenu.style.left = '0'; } // For vertical menus (orientation: 'v') const viewportHeight = window.innerHeight; const submenuHeight = submenu.offsetHeight; const parentBottom = parentItem.getBoundingClientRect().bottom; // Flip dropdown upward if it would go off the bottom edge if (parentBottom + submenuHeight > viewportHeight) { submenu.style.top = `-${submenuHeight}px`; } else { submenu.style.top = '0'; }
Option 2: Add a Post-Initialization Script (No Plugin Modification)
If you don't want to edit the original plugin, add this script after your ddsmoothmenu init:
ddsmoothmenu.init({ mainmenuid: "divMenu", orientation: 'h', classname: 'ddsmoothmenu', contentsource: "markup", oninit: function() { adjustSubmenuPositions(); // Re-adjust on window resize window.addEventListener('resize', adjustSubmenuPositions); } }); function adjustSubmenuPositions() { const submenus = document.querySelectorAll('#divMenu ul ul'); submenus.forEach(submenu => { const parent = submenu.parentElement; const parentRect = parent.getBoundingClientRect(); const submenuRect = submenu.getBoundingClientRect(); // Fix horizontal overflow if (parentRect.right + submenuRect.width > window.innerWidth) { submenu.style.left = `-${submenuRect.width - parent.offsetWidth}px`; } else { submenu.style.left = ''; // Reset to default } // Fix vertical overflow (if using vertical menu) if (parentRect.bottom + submenuRect.height > window.innerHeight) { submenu.style.top = `-${submenuRect.height}px`; } else { submenu.style.top = ''; // Reset to default } }); }
CSS Tweak to Prevent Clipping
Ensure submenus aren't clipped by parent elements:
.ddsmoothmenu ul ul { position: absolute; overflow: visible !important; /* Ensure submenus aren't hidden */ /* Keep your existing styles */ }
Final Tips
- Test keyboard navigation across all menu levels to ensure smooth behavior.
- Adjust the overflow logic if your menu has custom margins/padding that affect positioning.
- Check the ddsmoothmenu documentation—some versions have a built-in
dropdownalignoption you can use instead of custom code.
内容的提问来源于stack exchange,提问作者Ankur vijay

