导航栏左右逐项滚动宽度异常问题求助
解决导航栏逐项滚动的宽度计算问题
我来帮你搞定这个导航栏滚动不准确的问题!你遇到的核心问题是用了所有标签的平均宽度作为每次滚动的距离,但实际每个导航标签的文本长度不同,宽度自然不一样,再加上滚动边界判断逻辑有漏洞,就导致了滚动过度、无法逐项滚动的情况。下面是具体的问题分析和修复方案:
原代码的核心问题
- 平均宽度不适用:
widthofEachNav计算的是所有tab的平均宽度,但像"Tab1"和"Tab 10"这类标签的实际宽度差异很大,用固定平均宽度滚动必然不准。 - 滚动边界判断缺失:向右滚动时没有检查剩余可滚动的空间,可能导致列表滚动超出合理范围。
- 重复依赖引入:代码里重复引入了两个版本的jQuery,容易引发冲突;同时没正确引入Font Awesome,导致箭头图标无法显示。
- resize时的逻辑错误:
reAdjust函数里错误地操作了.item元素,而不是目标.list。
修复后的完整代码
HTML 部分(修复图标依赖和重复jQuery)
<div class="w-100 p-3"> <div class="scroller scroller-left mt-2"><i class="fa fa-chevron-left"></i></div> <div class="scroller scroller-right mt-2"><i class="fa fa-chevron-right"></i></div> <div class="wrapper"> <nav class="nav nav-tabs list mt-2" id="myTab" role="tablist"> <a class="nav-item nav-link active" data-toggle="tab" href="#tab1" role="tab" aria-controls="public" aria-expanded="true">Tab1</a> <a class="nav-item nav-link" href="#tab2" role="tab" data-toggle="tab">Tab 2</a> <a class="nav-item nav-link" href="#tab3" role="tab" data-toggle="tab">Tab 3</a> <a class="nav-item nav-link" href="#tab4" role="tab" data-toggle="tab">Tab 4</a> <a class="nav-item nav-link" href="#tab5" role="tab" data-toggle="tab">Tab 5</a> <a class="nav-item nav-link" href="#tab6" role="tab" data-toggle="tab">Tab 6</a> <a class="nav-item nav-link" href="#tab7" role="tab" data-toggle="tab">Tab 7</a> <a class="nav-item nav-link" href="#tab8" role="tab" data-toggle="tab">Tab 8</a> <a class="nav-item nav-link" href="#tab9" role="tab" data-toggle="tab">Tab 9</a> <a class="nav-item nav-link" href="#tab10" role="tab" data-toggle="tab">Tab 10</a> <a class="nav-item nav-link" href="#tab11" role="tab" data-toggle="tab">Tab 11</a> <a class="nav-item nav-link" href="#tab12" role="tab" data-toggle="tab">Tab 12</a> <a class="nav-item nav-link" href="#tab13" role="tab" data-toggle="tab">Tab 13</a> <a class="nav-item nav-link" href="#tab14" role="tab" data-toggle="tab">Tab 14</a> <a class="nav-item nav-link" href="#tab15" role="tab" data-toggle="tab">Tab 15</a> <a class="nav-item nav-link" href="#tab16" role="tab" data-toggle="tab">Tab 16</a> </nav> </div> <div class="tab-content" id="myTabContent"> <div role="tabpanel" class="tab-pane fade active show mt-2" id="tab1" aria-labelledby="public-tab" aria-expanded="true">Tab 1</div> <div class="tab-pane fade mt-2" id="tab2" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 2</p></div> <div class="tab-pane fade mt-2" id="tab3" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 3</p></div> <div class="tab-pane fade mt-2" id="tab4" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 4</p></div> <div class="tab-pane fade mt-2" id="tab5" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 5</p></div> <div class="tab-pane fade mt-2" id="tab6" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 6</p></div> <div class="tab-pane fade mt-2" id="tab7" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 7</p></div> <div class="tab-pane fade mt-2" id="tab8" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 8</p></div> <div class="tab-pane fade mt-2" id="tab9" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 9</p></div> <div class="tab-pane fade mt-2" id="tab10" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 10</p></div> <div class="tab-pane fade mt-2" id="tab11" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 11</p></div> <div class="tab-pane fade mt-2" id="tab12" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 12</p></div> <div class="tab-pane fade mt-2" id="tab13" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 13</p></div> <div class="tab-pane fade mt-2" id="tab14" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 14</p></div> <div class="tab-pane fade mt-2" id="tab15" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 15</p></div> <div class="tab-pane fade mt-2" id="tab16" role="tabpanel" aria-labelledby="group-dropdown2-tab" aria-expanded="false"><p>Tab 16</p></div> </div> </div> <!-- 正确引入依赖,去掉重复jQuery --> <link rel="stylesheet" href="http://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <script src="http://code.jquery.com/jquery-3.3.1.slim.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script> <script src="http://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
CSS 部分(微调布局)
.closeBtn:focus { outline: none; } .w-100.p-3 { max-width: 50%; } .close{ color: gray; } .wrapper { position:relative; margin:0 auto; overflow:hidden; padding:5px; height:50px; } .list { position:absolute; left:0px; top:0px; white-space: nowrap; margin-top:0px; } /* 替换min-width为white-space:nowrap */ .list .nav-item{ display:inline-block; position:relative; text-align:center; cursor:grab; cursor:-webkit-grab; color:#efefef; vertical-align:middle; } .scroller { text-align:center; cursor:pointer; display:none; padding:7px; padding-top:11px; white-space:nowrap; vertical-align:middle; background-color:#fff; border:1px solid #ddd; border-radius:4px; } .scroller-right{ float:right; } .scroller-left { float:left; } .xyzzz { max-width: 27% !important; min-width: 20% !important; }
JavaScript 部分(核心修复:逐项滚动+边界判断)
$(function() { // 获取当前可见区域第一个未完全显示的tab,或者第一个可见的tab function getNextScrollWidth(isRight) { const wrapperWidth = $('.wrapper').outerWidth(); const listLeft = $('.list').position().left; const tabs = $('.list .nav-item'); if (isRight) { // 向右滚动:找第一个右侧超出wrapper的tab,取它的宽度作为滚动距离 for (let i = 0; i < tabs.length; i++) { const tab = $(tabs[i]); const tabLeft = tab.position().left + listLeft; const tabRight = tabLeft + tab.outerWidth(); if (tabRight > wrapperWidth) { // 计算需要滚动的距离,确保刚好让这个tab完全进入可见区域 return Math.min(tab.outerWidth(), Math.abs(listLeft) + wrapperWidth - tabLeft); } } return 0; } else { // 向左滚动:找第一个左侧超出wrapper的tab,取它的宽度作为滚动距离 for (let i = 0; i < tabs.length; i++) { const tab = $(tabs[i]); const tabLeft = tab.position().left + listLeft; if (tabLeft < 0) { return Math.min(tab.outerWidth(), Math.abs(tabLeft)); } } return 0; } } function widthOfList() { let itemsWidth = 0; $('.list .nav-item').each(function(){ itemsWidth += $(this).outerWidth(); }); return itemsWidth; } function getLeftPosi() { return $('.list').position().left; } function reAdjust() { const wrapperWidth = $('.wrapper').outerWidth(); const listTotalWidth = widthOfList(); const listLeft = getLeftPosi(); // 控制右侧滚动按钮显示 if (wrapperWidth < listTotalWidth) { $('.scroller-right').show().css('display', 'flex'); } else { $('.scroller-right').hide(); } // 控制左侧滚动按钮显示 if (listLeft < 0) { $('.scroller-left').show().css('display', 'flex'); } else { $('.scroller-left').hide(); } // 如果列表总宽度小于容器,重置位置 if (wrapperWidth >= listTotalWidth) { $('.list').animate({left: 0}, 'slow'); } } $('.scroller-right').click(function() { $('.scroller-left').fadeIn('slow'); const scrollWidth = getNextScrollWidth(true); if (scrollWidth > 0) { $('.list').animate({left: `-=${scrollWidth}px`}, 'slow'); // 滚动后重新检查按钮显示状态 setTimeout(reAdjust, 600); } }); $('.scroller-left').click(function() { $('.scroller-right').fadeIn('slow'); const scrollWidth = getNextScrollWidth(false); if (scrollWidth > 0) { $('.list').animate({left: `+=${scrollWidth}px`}, 'slow'); setTimeout(reAdjust, 600); } }); $(window).on('resize', function() { reAdjust(); }); // 初始化 reAdjust(); });
关键改动说明
- 逐项滚动逻辑:新增
getNextScrollWidth函数,根据滚动方向找到需要滚动的目标tab,计算精准的滚动距离,确保每次滚动刚好让下一个(或上一个)tab完全进入可见区域。 - 修复布局问题:把
.list的min-width:3500px改成white-space:nowrap,让列表根据实际内容宽度自适应;同时修正.list li为.list .nav-item,匹配Bootstrap的结构。 - 清理依赖:去掉重复的jQuery引入,添加Font Awesome的CSS,确保箭头图标正常显示。
- 优化边界判断:滚动后重新检查按钮显示状态,避免按钮显示异常;resize时重置列表位置,确保布局正确。
内容的提问来源于stack exchange,提问作者Harsimranjit Singh
相关产品推荐
相关产品推荐

