SVG无法在绝对定位的父级中正确调整大小 [英] SVG fails to size properly in absolutely positioned parent
问题描述
我遇到一个问题,当将内联<svg>
元素包装在绝对定位的父级中时,该元素不会按其viewBox
属性中所声明的那样扩展到其原始大小:
I am encountering an issue where an inline <svg>
element does not stretch to its native size, as declared in its viewBox
attribute, when it is wrapped in an absolutely positioned parent:
- 使用
width: 100%
似乎只能强制SVG扩展到浏览器定义的默认大小300px
.这也会导致<img>
不能调整为其原始尺寸. - 使用
width: auto
会使SVG完全折叠成0px x 0px的尺寸,但是<img>
现在已调整为其原始尺寸
- Using
width: 100%
seems to only force the SVG to stretch to the browser defined default size of300px
. This also causes<img>
to not size to its native dimensions. - Using
width: auto
causes the SVG to collapse entirely into a dimension of 0px by 0px, but<img>
is now sized to its native dimensions
有趣的是,可以通过将SVG用作<img>
元素的src
属性的data:image/svg+xml
来复制此行为,因此看来SVG不会将其原始尺寸传递"给其包含的父对象(可以是<svg>
或<img>
元素).
Interestingly, this behavior can be replicated by using the SVG as a data:image/svg+xml
for the src
attribute of an <img>
element, so it appears that SVG does not "pass on" its native dimensions to its containing parent (be it an <svg>
or an <img>
element).
所以,我的问题是CSS中是否有任何可靠的方法可以根据其viewbox属性将SVG强制调整为其原始大小.通过阅读viewBox
属性和
So, my question is that if there is any reliable way in CSS that can force an SVG to size to its native size based on its viewbox attributes. I can probably use JS to brute force my way, by reading the viewBox
attributes and use the fixed aspect ratio hack to show my SVG as a background image in a fixed aspect ratio <div>
element, but I try to refrain from that. I am perhaps misunderstanding the browser's implementation of SVG specs, but I can't seem to find a workaround for this.
我的问题可以在下面的代码片段中复制.您可以:
My issue can be reproduced in the code snippet below. You can:
- 使用页面顶部的复选框打开/关闭父级的绝对定位 在
- 选择
width
声明(自动或100%)
<img>
或<svg>
元素上- turn on/off absolute positioning of the parent using a checkbox on the top of the page
- select
width
declarations (auto or 100%) on the<img>
or<svg>
elements
// The JS logic below is only used to dynamically set styles based on checkbox/select changes, has nothing to do with SVG layout
// Change positioning strategy
document.getElementById('absPosToggle').addEventListener('change', function() {
var parents = document.querySelectorAll('.parent');
if (this.checked) {
for (var i = 0; i < parents.length; i++) {
parents[i].classList.remove('no-absolute-positioning');
}
} else {
for (var i = 0; i < parents.length; i++) {
parents[i].classList.add('no-absolute-positioning');
}
}
});
// Change width declaration of <svg>/<img> elements
document.getElementById('widthSetting').addEventListener('change', function() {
var images = document.querySelectorAll('img, svg');
var value = this.options[this.selectedIndex].value;
if (value === '100%') {
for (var i = 0; i < images.length; i++) {
images[i].classList.add('width--100');
}
} else {
for (var i = 0; i < images.length; i++) {
images[i].classList.remove('width--100');
}
}
});
body {
margin: 0;
padding: 50px 0 0 0;
}
form {
position: fixed;
top: 0;
left: 0;
right: 0;
display: block;
background-color: #fff;
z-index: 1;
padding: 5px;
}
.wrapper {
width: 100%;
height: 250px;
background-color: #eee;
margin-bottom: 10px;
position: relative;
text-align: center;
}
.parent {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.parent.no-absolute-positioning {
position: relative;
top: 0;
left: 0;
transform: none;
}
img,
svg {
display: block;
width: auto;
}
img.width--100,
svg.width--100 {
width: 100%;
}
<form>
<label><input type="checkbox" id="absPosToggle" checked />Toggle absolute positioning</label><br />
<label for="widthSetting">Set svg/img widths to:</label><select id="widthSetting">
<option value="auto">Auto</option>
<option value="100%">100%</option>
</select>
</form>
<!-- <img> -->
<div class="wrapper">
<div class="parent">
<img src="https://via.placeholder.com/500x150/173755/ffffff" />
</div>
<span>This is an <code><img></code> element</span>
</div>
<!-- Inline <svg> -->
<div class="wrapper">
<div class="parent">
<svg viewBox="0 0 500 150" xmlns="http://www.w3.org/2000/svg"><rect x="0" y="0" width="500" height="150" fill="#b13131" /><g transform="translate(250, 75)"><text fill="#ffffff" style="text-anchor: middle; font-size: 50; font-family: Arial;" dy="0.35em">500 x 150</text></g></svg>
</div>
<span>This is an inline <code><svg></code> element</span>
</div>
<!-- <img> with SVG as data:image -->
<div class="wrapper">
<div class="parent">
<img src="data:image/svg+xml;charset=utf8,%3Csvg%20viewBox=%220%200%20500%20150%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Crect%20x=%220%22%20y=%220%22%20width=%22500%22%20height=%22150%22%20fill=%22#b13131%22%20/%3E%3Cg%20transform=%22translate(250,%2075)%22%3E%3Ctext%20fill=%22#ffffff%22%20style=%22text-anchor:%20middle;%20font-size:%2050;%20font-family:%20Arial;%22%20dy=%220.35em%22%3E500%20x%20150%3C/text%3E%3C/g%3E%3C/svg%3E"
/>
</div>
<span>This is an <code><img></code> element with SVG as data:image</span>
</div>
推荐答案
我认为问题的根本原因在于,通过绝对定位,您可以使父对象的宽度计算方法变为shrink-to-fit
,并且该内容和包含以下内容的内容也没有适当的固有宽度,这有点像22,这可以解释回落到标准"的300px宽度.
I think root cause of the issue is that with absolute positioning you make the width calculation method for the parent become shrink-to-fit
, and with that and content that has no proper intrinsic width either, that's kind of a catch 22, which might explain the fall back to the "standard" 300px width.
我们发现,您已经通过 https://css-tricks.com/scale -svg/,并且似乎在SVG本身中添加width
和height
属性可能是给SVG适当的固有高度的唯一工作方式(在这种特殊情况下),因此可以依次放大"其绝对定位的父级.
As we figured out, you have been through https://css-tricks.com/scale-svg/ already, and it seems like adding width
and height
attributes to the SVG itself might be the only working way (in this particular situation) to give the SVG a proper intrinsic height, so that it can in turn "span up" its absolute positioned parent.
这篇关于SVG无法在绝对定位的父级中正确调整大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!