Safari浏览器column-count属性下自定义复选框显示异常问题
我最近碰到了一个一模一样的棘手兼容性bug:用column-count:3给自定义复选框列表做三列布局时,除了OSX High Sierra和Catalina的Safari,其他所有浏览器(包括Mojave版本的Safari)都能正常显示,但这两个旧版Safari里,只有第一列的复选框能看见,剩下列的复选框明明DOM结构完整、位置也正确,就是死活不渲染。移除column-count属性后,所有复选框又都正常显示了。
先贴一下当时的原代码:
原CSS代码
.container { background-color: black; color: goldenrod; display: block; padding: 60px; } .facet-values { box-sizing: border-box; column-count: 3; font-size: 18px; list-style: none; margin: 5px 0; } .facet-value { > * { vertical-align: middle; } } /* 注意这是SCSS语法,实际使用需转成标准CSS */ .label { cursor: pointer; display: block; overflow: hidden; white-space: nowrap; } .wrapper { overflow: hidden; position: relative; } input[type="checkbox"] { display: none; padding: 0; } input[type="checkbox"]:checked + .checkbox > span { opacity: 1; } .checkbox { background-color: white; border: 1px solid goldenrod; border-radius: 3px; display: inline-block; height: 20px; margin: 3px 12px 3px 3px; position: relative; vertical-align: top; width: 20px; } .checkbox > span { border: 3px solid goldenrod; border-right: none; border-top: none; height: 5px; left: 3px; margin: 2px; opacity: 0; position: absolute; top: 3px; transform: rotate(-45deg); width: 9px; } .caption { display: inline-block; line-height: 1.28; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; white-space: nowrap; }
原HTML代码
<div class="container"> <ul class="facet-values"> <li class="facet-value"> <label class="label"> <div class="wrapper"> <input type="checkbox" /> <div class="checkbox"> <span></span> </div> <span class="caption">Filter 1</span> </div> </label> </li> <li class="facet-value"> <label class="label"> <div class="wrapper"> <input type="checkbox" /> <div class="checkbox"> <span></span> </div> <span class="caption">Filter 2</span> </div> </label> </li> <li class="facet-value"> <label class="label"> <div class="wrapper"> <input type="checkbox" /> <div class="checkbox"> <span></span> </div> <span class="caption">Filter 3</span> </div> </label> </li> <li class="facet-value"> <label class="label"> <div class="wrapper"> <input type="checkbox" /> <div class="checkbox"> <span></span> </div> <span class="caption">Filter 4</span> </div> </label> </li> <li class="facet-value"> <label class="label"> <div class="wrapper"> <input type="checkbox" /> <div class="checkbox"> <span></span> </div> <span class="caption">Filter 5</span> </div> </label> </li> <li class="facet-value"> <label class="label"> <div class="wrapper"> <input type="checkbox" /> <div class="checkbox"> <span></span> </div> <span class="caption">Filter 6</span> </div> </label> </li> </ul> </div>
问题根源
反复测试后发现,这个bug是旧版Safari对多列布局中position:relative元素的渲染异常导致的——你的.wrapper设置了position:relative,但这个相对定位完全没有必要(复选框的勾选标记是相对于.checkbox定位的,而.checkbox本身已经设置了position:relative),旧Safari在处理多列布局时,会错误地隐藏非第一列中带有相对定位的容器内的元素。
修复方案
我测试了三个可行的修复方法,优先推荐第一种,最简单有效:
方案1:移除.wrapper的position:relative
既然.wrapper的相对定位没有实际作用,直接删掉就能解决问题。修改后的.wrapper样式如下:
.wrapper { overflow: hidden; /* 删掉position:relative */ }
另外注意原CSS里的SCSS语法要转成标准CSS:
.facet-value > * { vertical-align: middle; }
方案2:触发硬件加速强制渲染
如果必须保留.wrapper的position:relative,可以给.facet-values添加transform: translateZ(0)触发硬件加速,强制Safari正确渲染所有列的元素:
.facet-values { box-sizing: border-box; column-count: 3; font-size: 18px; list-style: none; margin: 5px 0; transform: translateZ(0); /* 添加这行 */ }
方案3:改用Flexbox替代column-count
如果不想再和旧Safari的多列布局bug纠缠,可以改用Flexbox实现三列布局,兼容性更好,彻底避免这个问题。修改.facet-values和.facet-value的样式:
.facet-values { box-sizing: border-box; display: flex; flex-wrap: wrap; gap: 8px; /* 可选,控制列表项间距 */ font-size: 18px; list-style: none; margin: 5px 0; } .facet-value { flex: 0 0 calc(33.333% - 8px); /* 三列布局,减去gap宽度 */ }
我当时用方案1就完美解决了问题,所有列的复选框在目标Safari版本里都正常显示了。
内容的提问来源于stack exchange,提问作者Jeroen

