如何使SVG随其父容器缩放?

397

我想让内联SVG元素的内容在大小非本机时自动缩放。当然,我也可以将其作为单独的文件并按照那样进行缩放。

index.html:

<img src="foo.svg" style="width: 100%;" />

foo.svg:

<svg width="123" height="456"></svg>

然而,我想通过CSS为SVG添加额外的样式,因此链接外部样式表不是一个选择。我该如何使内联SVG缩放?


3
尝试在SVG宽度和高度中使用百分比。 - Sina R.
1
@ncm 用 JavaScript 怎么实现呢? - Mawg says reinstate Monica
1
在JS中设置它:yoursvgelem.setAttribute("width", "100%");yoursvgelem.setAttribute("height", "100%"); @MawgsaysreinstateMonica - Viktor Borítás
9个回答

706

为了在SVG图像中独立于图像的缩放大小指定坐标,请使用viewBox属性定义图像在图像坐标系统中的边界框,并使用widthheight属性定义宽度或高度与包含页面的相关性。

例如,这将呈现为一个10px乘20px的三角形:

svg {
  border: 1px solid blue;
}
<svg>
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

如果只设置宽度和高度,那将会改变SVG元素的大小,但不会对三角形进行缩放:

svg {
  border: 1px solid blue;
}
<svg width=100 height=50>
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

如果您设置了视图框(view box),那么它会使图像进行转换,使得给定的框(在图像的坐标系中)被缩放以适合给定的宽度和高度(在页面的坐标系中)。例如,将三角形缩放为100px x 50px:

如果您设置了视图框(view box),那么它会使图像进行转换,使得给定的框(在图像的坐标系中)被缩放以适合给定的宽度和高度(在页面的坐标系中)。例如,将三角形缩放为100px x 50px:

svg {
  border: 1px solid blue;
}
<svg width=100 height=50 viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

如果您想将其扩展到HTML视口的宽度:

svg {
  border: 1px solid blue;
}
<svg width="100%" viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

请注意,默认情况下,宽高比会被保留。因此,如果您指定元素的宽度为100%,但高度为50px,则实际上只会缩放到50px的高度(除非您有一个非常窄的窗口):

svg {
  border: 1px solid blue;
}
<svg width="100%" height="50px" viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
           points="0,10 20,10 10,0" />
</svg>

如果您确实希望它在水平方向上拉伸,请使用preserveAspectRatio = none禁用宽高比保持:

svg {
  border: 1px solid blue;
}
<svg width="100%" height="50px" viewBox="0 0 20 10" preserveAspectRatio="none">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>


3
这对我很有效。我首先在SVG元素上创建了一个viewBox属性,并将值设置为“0 0 [原始SVG宽度] [原始SVG高度]”。接下来,我将SVG元素的宽度属性更改为“auto”,高度属性更改为“100%”。容器还必须有一个定义好的高度。这将把矢量缩放到容器高度的100%,使宽度浮动。最后,将SVG的CSS max-width设置为100%,以防止超出容器。 - Ryan Griggs
不理解这个答案。问题是关于带有SVG源的IMG标签,而不是SVG内联图片。 - serge
@serge,SVG 图像只是包含标记的文本文件。这里的解决方案将根据需要应用于图像文件。 - isherwood
@serge,SVG图像只是包含标记的文本文件。这里的解决方案将根据需要应用于图像文件。 - undefined
出于更好的兼容性考虑,有没有一种方法可以不使用<polygon>标签(或其他可比较的标签,例如<path>)来实现?我想要像这样做<svg width="100%" height="50px" viewBox="0 0 20 10" preserveAspectRatio="none" url="/mySvg.svg"></svg>,但它不起作用。 - Normajean

76

我最终采用以下方法来实现等比例缩放:

注意:此示例使用React编写。如果您没有使用React,请将驼峰命名法更改为连字符(例如将backgroundColor更改为background-color,并将样式Object更改回String)。

<div
  style={{
    backgroundColor: 'lightpink',
    resize: 'horizontal',
    overflow: 'hidden',
    width: '1000px',
    height: 'auto',
  }}
>
  <svg
    width="100%"
    viewBox="113 128 972 600"
    preserveAspectRatio="xMidYMid meet"
  >
    <g> ... </g>
  </svg>
</div>

以下是上面示例代码中发生的情况:

VIEWBOX

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox

min-x、min-y、width 和 height

例如:viewbox="0 0 1000 1000"

视口盒(Viewbox)是一个重要的属性,它基本上告诉 SVG 绘制的大小和位置。如果你使用 CSS 使 SVG 变为 1000x1000 像素但视口盒为 2000x2000,则你会看到你的 SVG 的左上角一部分。

前两个数字 min-x 和 min-y 决定了 SVG 是否在视口盒内偏移。

我的 SVG 需要向上/向下或向左/向右移动

查看此代码:viewbox="50 50 450 450"

前两个数字将把你的 SVG 左移 50px,上移 50px,后两个数字是视口盒大小:450x450 像素。如果你的 SVG 是 500x500 但有一些额外的填充,则可以操纵这些数字以在“视口盒”内移动它。

你此时的目标是更改其中一个数字并查看发生了什么。

你也可以完全省略视口盒,但这样做会因为其他设置而有所不同。根据我的经验,你将遇到保持纵横比的问题,因为视口盒有助于定义它。

PRESERVE ASPECT RATIO

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio

根据我的研究,有很多不同的纵横比设置,但默认的称为 xMidYMid meet。我将其放在我的代码上以明确提醒自己。 xMidYMid meet 使其基于中点 X 和 Y 比例缩放。这意味着它在视口盒中保持居中。

WIDTH

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/width

查看我上面的示例代码。注意我只设置了宽度,没有高度。我将其设置为 100%,以使其填充其所在的容器。这可能是回答此 Stack Overflow 问题的最大贡献。

你可以将其更改为任何像素值,但我建议像我一样使用 100% 来将其放大到最大尺寸,然后通过父容器控制它的大小。我建议这样做是因为你会得到“正确”的控制。你可以使用媒体查询,而且你可以在没有疯狂 JavaScript 的情况下控制其大小。

SCALING WITH CSS

再次查看我上面的示例代码。注意我具有以下属性:

resize: 'horizontal', // you can safely omit this
overflow: 'hidden',   // if you use resize, use this to fix weird scrollbar appearance
width: '1000px',
height: 'auto',

这是额外信息,但它展示了如何允许用户在保持正确的宽高比的同时调整SVG的大小。因为SVG维护自己的宽高比,你只需要使父容器的宽度可调整大小,它就会按需求进行调整。

我们不需要改变高度或将其设置为自动,而是用宽度来控制调整大小。我选择宽度,因为在响应式设计中通常更有意义。

这里是使用这些设置的图片:

enter image description here

如果您阅读了此问题中的所有解决方案仍然感到困惑或没有看到所需内容,请查看这个链接。我发现它非常有帮助:

https://css-tricks.com/scale-svg/

这是一篇很长的文章,但它几乎涵盖了操纵SVG的每种可能方式,无论是否使用CSS。我建议边喝咖啡或你选择的选择性液体边阅读它。


1
这似乎不适用于任何SVG - 如果您无法控制SVG源,则当SVG具有固定宽度时,此方法会失败。 - user48956
1
是的 - 你总是可以用编程来探索各种文件格式的内部结构,但你希望有一种适用于所有类型资源(例如PNG)且不需要JavaScript编程的方法。 - user48956
如果您只有一个SGV文件而不是SVG内联对象会怎么样? - serge
@serge 将其作为 <img><object><embed> 标记添加到您的 HTML 文档中,其中 src 是 SVG 文件。 这样,您就无法通过 CSS 修改它,但是仍然可以使用 JavaScript 修改其属性。 但是,如果可能,最好的做法是在 SVG 中使用内联方式。 - Viktor Borítás
我的朋友,你太棒了!谢谢。 - boardkeystown
显示剩余2条评论

28
你需要进行以下转换:
使用JavaScript:
document.getElementById(yourtarget).setAttribute("transform", "scale(2.0)");

CSS样式:

#yourtarget {
  transform:scale(2.0);
  -webkit-transform:scale(2.0);
}

将您的SVG页面包装在一个组标签中,如下所示,并将其定位为操作整个页面的目标:

<svg>
  <g id="yourtarget">
    your svg page
  </g>
</svg>

注意:比例尺1.0表示100%


9
好的。我不想用JS来实现这个功能。有没有办法让它自动适应父元素大小? - bjb568
1
@bj setAttribute和<tag attribute="value">是相同的东西。 - john k
如果一个转换属性已经存在会发生什么?它会被覆盖吗?! - qräbnö

23

无意中发现这个 CSS 似乎可以在 Chrome 浏览器中将 SVG 包含,直到容器大于图像的大小为止:

div.inserted-svg-logo svg { max-width:100%; }

看起来在Firefox和IE 11中也能正常工作。


这对我解决了问题。虽然我只在iOS上看到了溢出,但还是谢谢! - Evan Mattson
8
同时使用 max-width: 100%max-height: 100% 可以使 SVG 图像始终按比例缩放到容器内,而不会溢出或失去其纵横比。 - Gavin
3
max-height: 100%”对我无效,使用“vh”代替“%”解决了问题。 - Pavel

10
这里有一个简单的方法: 方法一:大多数SVG都有一个视口,如下所示:
<svg viewBox="0 0 24 30" ...>

而且你可以很容易地在CSS中控制它们的大小:

svg {
  height: 20px;
}

类型2:如果SVG具有宽度和高度,但没有视口,如下所示:

<svg width="810" height="540">

那么你可以手动添加一个视口(viewbox),它的宽度和高度完全相同,就像这样:

<svg width="810" height="540" viewBox="0 0 810 540">

然后你可以像类型1一样做。


类型2不起作用。添加viewBox也没有改变任何东西。 - EugZol
第一种方法对我很有效。基本上我们只需要在SVG中添加viewBox,然后通过CSS控制widthheight - undefined

7

另一种简单的方法是:

transform: scale(1.5);

3
在SVG中应该在哪里添加这个?这看起来像CSS。 - Dimitri Kopriwa
1
你可以在 transform 属性中使用 @DimitriKopriwa。例如 <g transform="scale(1.5)">...</g> 或者你可以给元素分配一个 class 并使用 CSS。 - Elias

5

对于我来说,更改SVG文件不是一个公平的解决方案,因此我使用相对CSS单位

vhvw%非常方便。我使用类似于height: 2.4vh;的CSS设置SVG图像的动态大小。


3

如果想要缩放SVG而没有preserveAspectRatio属性的话:

这种方式会使SVG始终拉伸以填充widthheight,如果必要,它将只调整widthheight的大小,我为此寻找了好几天,因此想在这里分享给其他可能需要的人。

您需要从<svg>中删除widthheight属性,并添加viewBox属性以及preserveAspectRatio="none"

例如:

<?xml version="1.0" encoding="utf-8"?>

<svg 
version="1.1" 
xmlns="http://www.w3.org/2000/svg" 
viewBox="0 0 5.8208332 15.9"
preserveAspectRatio="none">

<polygon points="480.4,200 0,200 0,0 480.4,0 599.9,100 " fill="#E1E1E1"/>
</svg>

0

调整currentScale属性在IE中有效(我已经测试过IE 11),但在Chrome中无效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接