WordPress中如何仅高亮指向当前可见容器的子菜单项
嘿,这个问题我太熟了!WordPress默认的菜单高亮逻辑只会检查URL的路径部分,完全不管锚点(就是#后面的部分),所以这三个指向同一页面不同锚点的子菜单,都会被自动加上current-menu-item类,导致全部高亮。别担心,咱们一步步来解决:
第一步:先干掉WordPress默认的错误高亮
首先得让WordPress别乱给这三个子菜单加current-menu-item类,因为它只会看URL前缀匹配,不管锚点。咱们用WordPress的钩子来实现:
把这段代码加到你主题的functions.php文件里:
add_filter('nav_menu_css_class', 'remove_default_current_for_anchor_items', 10, 4); function remove_default_current_for_anchor_items($classes, $item, $args, $depth) { // 列出我们要处理的三个锚点 $target_anchors = array('#wherewework', '#whatwebelieve', '#ourpartners'); foreach($target_anchors as $anchor) { // 如果当前菜单项的URL包含目标锚点,就移除默认的高亮类 if(strpos($item->url, $anchor) !== false) { $classes = array_diff($classes, array('current-menu-item', 'current_page_item')); break; } } return $classes; }
这样一开始这三个子菜单就不会被错误高亮了。
第二步:用JS实现基于容器可见性的动态高亮
你之前的思路是对的,但缺少几个关键部分,比如判断元素是否在视口的函数,还有没有处理多个容器的逻辑。下面是完整的可运行代码:
首先定义判断元素是否在视口的工具函数:
function isElementInViewport(el) { const rect = el.getBoundingClientRect(); return ( rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.bottom >= 0 && rect.left <= (window.innerWidth || document.documentElement.clientWidth) && rect.right >= 0 ); }
然后写核心的高亮逻辑:
// 建立锚点和对应菜单项ID的映射关系 const anchorToMenuItem = { '#wherewework': 'first', '#whatwebelieve': 'second', '#ourpartners': 'third' }; function updateActiveAnchorMenu() { // 先清空所有三个菜单项的高亮类 Object.values(anchorToMenuItem).forEach(itemId => { document.getElementById(itemId).classList.remove('current-menu-item'); }); // 遍历每个容器,找到第一个在视口内的,给对应菜单项加高亮类 for(const [anchor, itemId] of Object.entries(anchorToMenuItem)) { const targetContainer = document.querySelector(anchor); if(targetContainer && isElementInViewport(targetContainer)) { document.getElementById(itemId).classList.add('current-menu-item'); break; // 如果想让所有可见的容器对应菜单项都高亮,就删掉这行 } } } // 绑定事件:页面加载、滚动、窗口大小变化时都触发更新 window.addEventListener('DOMContentLoaded', updateActiveAnchorMenu); window.addEventListener('load', updateActiveAnchorMenu); window.addEventListener('scroll', updateActiveAnchorMenu); window.addEventListener('resize', updateActiveAnchorMenu);
把这段JS代码加到你的主题自定义JS区域,或者在页面底部的<script>标签里插入就行。
额外优化:处理直接访问带锚点的URL
如果用户直接打开比如URL/who-we-are/#whatwebelieve这样的链接,上面的代码会在页面加载完成后自动高亮对应的菜单项,不用额外处理。
为啥你之前的代码没生效?
- 缺少
isElementInViewport函数的定义,逻辑根本跑不起来 - 只处理了
#whatwebelieve一个容器,没覆盖另外两个 - 只有移除类的逻辑,没有添加类的逻辑
- JS里选择器
#whatwebelieve没加引号,语法错误
这样调整后,就只会高亮当前在视口内的容器对应的子菜单项啦!
内容的提问来源于stack exchange,提问作者Yahya Hussein
相关产品推荐
相关产品推荐

