IE浏览器表格滚动条内置致列错位问题的排查与修复
问题原因分析
咱们先来拆解下为什么Chrome表现正常,但IE会出现列错位的问题:
- 表格原生布局被破坏:你把
<thead>和<tbody>设置为display:block,直接打破了表格默认的列对齐逻辑——原本表格的列是基于<table>统一计算对齐的,改成块级元素后,表头和表体变成了两个独立的块,宽度各自计算,失去了原生的对齐关联。 - IE滚动条的特殊行为:IE浏览器中,给块级元素设置
overflow:auto时,滚动条会占用元素的内部内容宽度(大概17px),而Chrome等现代浏览器的滚动条要么不挤占内容宽度,要么在元素外部渲染。这就导致<tbody>的实际可用宽度比<thead>少了滚动条的宽度,列自然就错位了。 - Bootstrap Table未解决的原因:大概率是没有针对IE的滚动条行为做兼容处理,或者依然依赖了块级化的表头/表体布局,没回到表格原生的对齐机制上。
修复方案(兼容IE的最优解)
推荐采用双表格分离表头和表体的方案,既保留固定表头的效果,又利用表格原生的布局机制保证列对齐,完美兼容IE:
步骤1:调整HTML结构
把原来的单表格拆成两个:一个单独放表头(固定在顶部),另一个把表体放在滚动容器里:
<!-- 固定的表头表格 --> <table id="TableDo1-header" class="tablesorter" style="table-layout: fixed; width: 100%;"> <thead> <tr class="size13px"> <th class="1611 1 IHM odd textAlignCenter noBorderLeft"></th> <th class="1024 1 IHM odd textAlignCenter header"></th> <th class="1205 1 IHM odd textAlignCenter header"></th> <th class="1012 1 IHM odd textAlignCenter header"></th> <th class="jJLib odd textAlignCenter header"> ${myForm.today} </th> <th class="jUnLib odd textAlignCenter header" > ${myForm.todayOne} </th> <th class="jDeuxLib odd textAlignCenter header"> ${myForm.todayTwo} </th> <th class="jTroisLib odd textAlignCenter header" > ${myForm.todayThree} </th> <th class="jQuatreLib odd textAlignCenter header"> ${myForm.todayFour} </th> <th class="jCinqLib odd textAlignCenter header"> ${myForm.todayFive} </th> </tr> </thead> </table> <!-- 带滚动条的表体容器 --> <div id="table-body-container" style="max-height: 120px; overflow-y: auto; margin-top: -1px;"> <table id="TableDo1-body" class="tablesorter" style="table-layout: fixed; width: 100%; border-top: none;"> <tbody> <c:if test="${empty myForm.myList}"> <tr> <td colspan="8"><span class="1184 1 IHM"></span></td> </tr> </c:if> <c:if test="${not empty myForm.myList}"> <c:forEach items="${myForm.myList}" var="document" varStatus="status" > <tr class="Do1 size12px"> <td class="textAlignCenter"> <a class="tri" onclick="submitActionForm('myForm','myID','${document.myID}','doListeDetailFourn')"> <img src="<c:url value='/resources/img/picto_plus.png' />" class="afficheCursor"> </a> </td> <td class=" textAlignLeft" > ${document.myID} - ${document.myName} </td> <td class=" textAlignRight" > <input type="hidden" class="monTotDo1 ${document.change}" value="${document.accountOri}"/> ${document.account} </td> <td class="change1 textAlignCenter" > ${document.change} </td> <td class=" textAlignRight" > <input type="hidden" class="jJDoVal ${document.change}" value="${document.jJOri}"/> ${document.jJ} </td> <td class=" textAlignRight" > <input type="hidden" class="jJDoVal1 ${document.change}" value="${document.jUnOri}"/> ${document.jUn} </td> <td class=" textAlignRight"> <input type="hidden" class="jJDoVal2 ${document.change}" value="${document.jDeuxOri}"/> ${document.jDeux} </td> <td class=" textAlignRight"> <input type="hidden" class="jJDoVal3 ${document.change}" value="${document.jTroisOri}"/> ${document.jTrois} </td> <td class=" textAlignRight" > <input type="hidden" class="jJDoVal4 ${document.change}" value="${document.jQuatreOri}"/> ${document.jQuatre} </td> <td class="textAlignRight" > <input type="hidden" class="jJDo5 ${document.change}" value="${document.jCinqOri}"/> ${document.jCinq} </td> </tr> </c:forEach> </c:if> </tbody> </table> </div>
步骤2:调整CSS样式
更新列宽度的选择器,同时移除原来的display:block设置,给IE单独做滚动条兼容:
* { box-sizing: border-box; } /* 给两个表格的列设置完全一致的宽度 */ #TableDo1-header th:nth-child(1), #TableDo1-body td:nth-child(1) { width: 72px !important; } #TableDo1-header th:nth-child(2), #TableDo1-body td:nth-child(2) { width: 170px !important; } #TableDo1-header th:nth-child(3), #TableDo1-body td:nth-child(3) { width: 95px !important; } #TableDo1-header th:nth-child(4), #TableDo1-body td:nth-child(4) { width: 65px !important;} #TableDo1-header th:nth-child(5), #TableDo1-body td:nth-child(5) { width: 90px !important; } #TableDo1-header th:nth-child(6), #TableDo1-body td:nth-child(6) { width: 90px !important;} #TableDo1-header th:nth-child(7), #TableDo1-body td:nth-child(7) { width: 90px !important;} #TableDo1-header th:nth-child(8), #TableDo1-body td:nth-child(8) { width: 90px !important; } #TableDo1-header th:nth-child(9), #TableDo1-body td:nth-child(9) { width: 90px !important; } #TableDo1-header th:nth-child(10), #TableDo1-body td:nth-child(10) { width: 90px !important;} /* 恢复表格原生布局模式,移除之前的display:block */ #TableDo1-header thead { display: table-header-group; } #TableDo1-body tbody { display: table-row-group; } /* IE专属:给滚动容器加右侧padding,抵消滚动条占用的宽度,保证列对齐 */ _:-ms-lang(x), #table-body-container { padding-right: 17px; }
为什么这个方案有效?
- 原生表格布局:两个表格都设置
table-layout: fixed,列宽度严格按照你定义的数值计算,完全依赖表格原生的对齐机制,不会出现块级元素的宽度偏差。 - 滚动条隔离:滚动条放在容器div上,而不是表体内部,不会影响表格的宽度计算,表头和表体的宽度完全一致。
- IE兼容处理:通过CSS hack给IE单独添加padding,抵消滚动条的宽度占用,保证列对齐完美。
内容的提问来源于stack exchange,提问作者Unity
相关产品推荐
相关产品推荐

