在写毕设的时候遇到了一个看起来很难搞的问题。假设有如下 HTML 结构:
<div class="scrollable">
<table>
<thead>
<!-- headers -->
</thead>
<tbody>
<!-- contents -->
</tbody>
<tfoot>
<tr>
<!-- several `td`s -->
<td>
<custom-select
:options="options">
</custom-select>
</td>
</tr>
</tfoot>
</table>
</div>
其中,.scrollable
的作用是当表格的一行过长时,可以让其横向滚动而不影响页面的其它部分;<custom-select>
元素是一个用 ul
模拟出来的 select 效果,被包在 <tfoot>
中当作添加的新项的选项。一个可能的效果如下:
注意表格是可以左右滑动的。
因为 <custom-select>
是被包在 .scrollable
里面的,所以需要写这样一个 CSS 来确保选择框多出来的地方能够显示出来:
.scrollable {
overflow-x: auto;
overflow-y: visible;
}
这时候问题出现了。渲染之后的 overflow-y
被强行设置成了 auto!W3C 的 这个页面 中是这么写的:
The computed values of ‘overflow-x’ and ‘overflow-y’ are the same as their specified values, except that some combinations with ‘visible’ are not possible: if one is specified as ‘visible’ and the other is ‘scroll’ or ‘auto’, then ‘visible’ is set to ‘auto’.
计算所得的 'overflow-x' 和 'overflow-y' 与 CSS 中定义的相同,除了带有 'visible' 的其中一种情况:如果其中有一个是 'visible',另一个是 'scroll' 或者 'auto',那么这个 'visible' 会被设置为 'auto'。
什么鬼?!
一番谷歌之后,发现了万能的 Stack Overflow 上面有一个 看似很靠谱的答案(具体代码请看 这里),大体思想是用两个标签来限制:先把要溢出的元素包在 B 中,再把 B 包在 A 中;B 设置 overflow-x: auto
,高度必须大于算上溢出元素和滚动条之后的总高度;A 设置 overflow-y: visible
,固定高度。
这思路似乎可行,于是我改了一下 HTML:
<div class="scrollable-hack-a">
<div class="scrollable-hack-b">
<table>
<!-- original table -->
</table>
</div>
</div>
我的 <custom-select>
有一个 max-height: 400px
,由于我项目中的滚动条不占用空间,所以可以忽略滚动条的高度。那么 B 的高度应该是 之前的高度 + 400px
,可以利用 padding-bottom: 400px
来实现;A 的高度应该是 之前的高度 - 400px
,可以利用 margin-bottom: -400px
来实现。
/* outer, set overflow-y, original height */
.scrollable-hack-a {
overflow-y: visible;
margin-bottom: -400px;
}
/* inner, set overflow-x, enough height */
.scrollable-hack-b {
overflow-x: auto;
padding-bottom: 400px;
}
当然,效果就是一开始的那张截图啦!