html - 如何强制 SVG 水平填充其容器?
问题描述
我们正在为需要使用 SVG 来模拟图片和视频周围设备的顶部/底部的客户开发一个站点。我遇到了一个问题(几乎只在 iPad 上,但有时在其他浏览器上确实会在某种程度上发生)SVG 无法正确填充空间。当浏览器缩放时,SVG 也会缩放,但会在各种尺寸下留下小间隙。我无法让 SVG 可靠地边对边地填充其容器。
我尝试通过图像标签、对象标签添加 SVG,并且尝试将 SVG 数据硬编码到页面中。我还尝试了几种不同的方法来强制 SVG 填充该空间,并且我尝试过的每个版本都获得了相同的结果。
这是说明问题的屏幕截图:
这是上面的代码:https ://codepen.io/the_pm/pen/dypVMMB - 我添加了一个带有硬编码 SVG 的版本。硬编码的 SVG 在比版本更多的浏览器中工作(请注意,SVG 没有应用任何样式)。但是它们仍然在 iPad/Safari 上显示间隙,我认为绝对定位会解决这个问题,但事实并非如此。
如前所述,我已尝试链接 SVG,并且已尝试将 SVG 代码直接添加到页面中,在显示上没有任何差异。这是我用来强制执行所需行为的几个 CSS 方法。
方法一:
.topper {
font-size:0 ; /* prevents gapping due to font descenders */
height:auto ;
padding-bottom:3.62% ; /* height/width of image */
position:relative ;
width:100%
}
.topper img {
height:100% ;
left:0 ;
position:absolute ;
top:0 ;
width:100%
/* also tried bottom:0 and right:0 instead of height:100% and width:100% - no luck */
}
方法二:
.topper {
background:url('path/to/image.svg') center top no-repeat ;
background-size:100% 100% ;
font-size:0 ;
height:auto ;
padding-bottom:3.62% ;
width:100%
}
我已经尝试了上述代码的至少十几种变体,但结果与您在 codepen 中看到的相同。
任何帮助将不胜感激!
解决方案
您遇到了无法真正控制的舍入问题。每个规范的浏览器都是如何处理这些的。您正在使用比高宽得多的 SVG。这具有数学结果,当缩放它时,将其大小四舍五入到全像素将导致纵横比发生显着变化。
现在 SVG 对纵横比变化的反应与其他图像不同。浏览器总是重新计算光栅图像,因此它们将填充所有像素,甚至会以稍微扭曲它们的代价。SVG 作用于默认为 value的属性preserveAspectRatio"xMidYMid meet"
。忽略这究竟意味着什么,它相当于 CSS"contain"
值。
缩放图像时,将高度值向下舍入很容易导致宽度在精确计算时缺少超过 1 像素。下面是一个例子:让可用宽度为 982px。保留纵横比的计算高度将为 78 / 2160 * 982 = 35.4611px。现在,如果浏览器向下取整,确切的宽度将是 2160 / 78 * 35 = 969.231px。这将显示为 ca 的间隙。每边 6.6 像素。
解决此问题的明显方法是将属性设置为preserveAspectRatio="none"
. (我冒昧地重写了您的 SVG,简化了它并提高了可读性。)
svg {
display: block;
width: 982px;
height: 35px;
background: green;
margin: 20px 0;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2160 78">
<rect x="1" y="1" width="2158" height="120" rx="30" style="fill:none;stroke:#000;stroke-width:2" />
<circle r="9" cx="62" cy="40" />
<circle r="9" cx="97" cy="40" />
<circle r="9" cx="132" cy="40" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2160 78" preserveAspectRatio="none">
<rect x="1" y="1" width="2158" height="120" rx="30" style="fill:none;stroke:#000;stroke-width:2" />
<circle r="9" cx="62" cy="40" />
<circle r="9" cx="97" cy="40" />
<circle r="9" cx="132" cy="40" />
</svg>
推荐阅读
- python - 如何在特定字符之前测量字符串的长度
- kotlin - 纽贝印刷类型
- javascript - 如何删除由模板引用创建的组件?
- python - HDF5数据可以在Python中实时读取为字节流吗?
- c# - 我正在尝试对 ASP.NET 网络表单中的一系列控件进行分组,并使用 c# 对所有控件执行计算
- reactjs - 未捕获的 ReferenceError: _JSXStyle 未定义
- c - 记录 v4 CTree 数据库的内部结构.. 解析二进制文件?
- c# - 使用 Linq 获取列表的最大值?
- javascript - JS 范围滑块不适用于 JS 画布
- python - 为什么迭代器没有从初始位置开始