首页 > 解决方案 > 如何强制 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 中看到的相同。

任何帮助将不胜感激!

标签: htmlcsssvgfill

解决方案


您遇到了无法真正控制的舍入问题。每个规范的浏览器都是如何处理这些的。您正在使用比高宽得多的 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>


推荐阅读