如何强制 SVG 水平填充其容器?

How do I force an SVG to fill its container horizontally?

我们正在为需要使用 SVG 模拟图片和视频周围设备的 top/bottom 的客户开发一个站点。我 运行 遇到了一个问题(几乎只在 iPad 上发生,但有时在其他浏览器上确实会在某种程度上发生),SVG 无法正确填充 space。当浏览器缩放时,SVG 也会缩放,但它会在各种尺寸下留下小间隙。我无法让 SVG 可靠地边到边填充它的容器。

我试过通过图像标签、对象标签添加 SVG,并且我试过将 SVG 数据硬编码到页面中。我还尝试了几种不同的方法来强制 SVG 填充 space,并且我尝试过的每个版本都获得了相同的结果。

这是说明问题的屏幕截图:

这是上面的代码: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 作用于默认值为 "xMidYMid meet" 的属性 preserveAspectRatio。掩饰这到底意味着什么,它相当于 CSS "contain" 值。

缩放图像时,将高度值向下舍入 的行为很容易导致宽度在精确计算时缺少超过 1 像素。这是一个示例:让可用宽度为 982px。保留纵横比的计算高度为 78 / 2160 * 982 = 35.4611px。现在,如果浏览器向下舍入,精确的宽度将是 2160 / 78 * 35 = 969.231px。这将显示为 ca 的差距。每边 6.6px。

解决这个问题的明显方法是将属性设置为 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>