如何在保持纵横比和可扩展性的同时使用 SVG Sprite Sheet 作为 CSS 背景图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10956636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use SVG Sprite Sheet as CSS background-image while maintaining aspect ratio and scalability
提问by Adrian
TL;DR: I want to use several icons tiled in an SVG sprite sheet as CSS background-images, which maintain their aspect ratio and automatically scale to fill the parent element, using nothing but SVG and CSS. No JavaScript please.
TL;DR:我想在 SVG 精灵表中使用几个平铺的图标作为 CSS 背景图像,它们保持它们的纵横比并自动缩放以填充父元素,只使用 SVG 和 CSS。请不要使用 JavaScript。
So I have a spritesheet in SVG format, which I made with a combination of SVG-Editand some hand-coding in Notepad++. Here's the source code:
所以我有一个 SVG 格式的 spritesheet,我结合了SVG-Edit和 Notepad++ 中的一些手工编码。这是源代码:
<svg version="1.1"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="600"
height="400"
viewBox="0 0 600 400">
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
<title>chosen_sprite</title>
<g>
<title>Add</title>
<rect fill="none" stroke-width="10" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" x="5" y="5" width="90" height="90" id="svg_1" stroke="#dcdcdc"/>
<line id="svg_2" y2="50" x2="70" y1="50" x1="30" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/>
<line id="svg_3" y2="30" x2="50" y1="70" x1="50" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/>
</g>
<g>
<title>Delete</title>
<rect fill="none" stroke-width="10" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" x="105" y="5" width="90" height="90" id="svg_1" stroke="#dcdcdc"/>
<line id="svg_2" y2="70" x2="170" y1="30" x1="130" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#ff0000" fill="none"/>
<line id="svg_3" y2="30" x2="170" y1="70" x1="130" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#ff0000" fill="none"/>
</g>
<g>
<title>Expand Dark</title>
<rect stroke="#505050" id="svg_1" height="90" width="90" y="5" x="205" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="10" fill="none"/>
<line fill="none" stroke="#000000" stroke-width="12" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="round" x1="250" y1="65" x2="280" y2="35" id="svg_2"/>
<line fill="none" stroke="#000000" stroke-width="12" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="round" x1="220" y1="35" x2="250" y2="65" id="svg_3"/>
</g>
<g>
<title>Collapse Dark</title>
<rect stroke="#505050" height="90" width="90" y="5" x="305" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="10" fill="none" id="svg_4"/>
<line fill="none" stroke="#000000" stroke-width="12" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="round" x1="350" y1="35" x2="380" y2="65" id="svg_5"/>
<line fill="none" stroke="#000000" stroke-width="12" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="round" x1="320" y1="65" x2="350" y2="35" id="svg_6"/>
</g>
<g>
<title>Expand Green</title>
<rect fill="none" stroke-width="10" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" x="405" y="5" width="90" height="90" id="svg_1" stroke="#dcdcdc"/>
<line id="svg_2" y2="35" x2="480" y1="65" x1="450" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/>
<line id="svg_3" y2="65" x2="450" y1="35" x1="420" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/>
</g>
<g>
<title>Collapse Green</title>
<rect fill="none" stroke-width="10" stroke-dasharray="null" stroke-linejoin="null" stroke-linecap="null" x="505" y="5" width="90" height="90" id="svg_1" stroke="#dcdcdc"/>
<line id="svg_2" y2="65" x2="580" y1="35" x1="550" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/>
<line id="svg_3" y2="35" x2="550" y1="65" x1="520" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#00a00c" fill="none"/>
</g>
<g>
<title>Search</title>
<circle id="svg_9" r="32" cy="140" cx="60" stroke-width="8" stroke="#000000" fill="none"/>
<line id="svg_11" y2="167.5" x2="32.5" y1="190" x1="10" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#000000" fill="none"/>
</g>
<g>
<title>Search 2</title>
<rect id="svg_10" stroke="#505050" height="90" width="90" y="105" x="105" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="10" fill="none"/>
<circle r="25" cy="142.5" cx="157.5" stroke-width="8" stroke="#000000" fill="none" id="svg_7"/>
<line y2="165" x2="135" y1="180" x1="120" stroke-linecap="round" stroke-linejoin="null" stroke-dasharray="null" stroke-width="12" stroke="#000000" fill="none" id="svg_8"/>
</g>
</svg>
It works fine and looks the way I want it to.
它工作正常,看起来像我想要的那样。
The problem is the CSS. Defining the cells in the spritesheet is a little bit messier than I would like it to be. Here's the page I'm displaying these icons in:
问题是CSS。在 spritesheet 中定义单元格比我希望的要麻烦一些。这是我在其中显示这些图标的页面:
<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<html>
<head>
<style>
* {padding: 0px; margin: 0px; outline: 1px solid rgba(0,0,0,0.1);}
html {width: 100%; height: 100%;}
body {width: 100%; height: 100%;}
.svgSprite {
background-image: url('./svgicons/form_icons_sprite.svg');
background-repeat: no-repeat;
background-size: 600%;
}
.svgSprite.add {
background-position: 0px 0px;
width: 12px;
height: 12px;
}
.svgSprite.delete {
background-position: -16px 0px;
width: 16px;
height: 16px;
}
.svgSprite.expandDark {
background-position: -24px 0px;
width: 12px;
height: 12px;
}
.svgSprite.collapseDark {
background-position: -36px 0px;
width: 12px;
height: 12px;
}
.svgSprite.expandGreen {
background-position: -48px 0px;
width: 12px;
height: 12px;
}
.svgSprite.collapseGreen {
background-position: -60px 0px;
width: 12px;
height: 12px;
}
.svgSprite.search {
background-position: 0px -12px;
width: 12px;
height: 12px;
}
.svgSprite.search2 {
background-position: -16px -16px;
width: 16px;
height: 16px;
}
</style>
</head>
<body>
<div class="svgSprite add"></div>
<div class="svgSprite delete"></div>
<div class="svgSprite expandDark"></div>
<div class="svgSprite collapseDark"></div>
<div class="svgSprite expandGreen"></div>
<div class="svgSprite collapseGreen"></div>
<div class="svgSprite search"></div>
<div class="svgSprite search2"></div>
</body>
</html>
Basically, I want to know if there's an easier way to define the cells in the spritesheet and simplify the CSS I use to tell each div which icon to display from the spritesheet.
基本上,我想知道是否有更简单的方法来定义 spritesheet 中的单元格并简化我用来告诉每个 div 从 spritesheet 显示哪个图标的 CSS。
I would prefer that this solution be strictly SVG and CSS; I am not interested in using JavaScript libraries. I am aiming to get it to a point where I can simply define the cells and have the particular icon I'm aiming for automatically scale to fit its container, while maintaining its aspect ratio. Currently, in order to make the icon fit its parent container, its width and height need to be explicitly defined, and match the width and height of the parent container. If I change the width and height of the parent container, I need to change the background-position sizes as well.
我更喜欢这个解决方案是严格的 SVG 和 CSS;我对使用 JavaScript 库不感兴趣。我的目标是让它达到这样的程度,我可以简单地定义单元格并让我的目标是自动缩放以适应其容器的特定图标,同时保持其纵横比。目前,为了使图标适合其父容器,需要明确定义其宽度和高度,并匹配父容器的宽度和高度。如果我改变父容器的宽度和高度,我也需要改变背景位置的大小。
Then, there's the problem of scaling. With this setup, the SVG scales to the appropriate size to be drawn on-screen, but if I decide to zoom using my browser's zoom, it pixelates. This is not how SVG is supposed to work.
然后,还有缩放问题。通过此设置,SVG 会缩放到要在屏幕上绘制的适当大小,但是如果我决定使用浏览器的缩放功能进行缩放,它会像素化。这不是 SVG 应该如何工作。
I suppose I could just put each icon in its own file, because that seems to work wonderfully, but I just really like using sprites; it not only saves me several server requests, it's just cool.
我想我可以将每个图标放在自己的文件中,因为这看起来效果很好,但我真的很喜欢使用精灵;它不仅为我节省了几个服务器请求,而且很酷。
I am aware of SVG Icon Loader. It's pretty cool, but it's one more JavaScript file that I would rather not rely on.
我知道SVG Icon Loader。这很酷,但它是另一个我不想依赖的 JavaScript 文件。
I've already read the w3 SVG docs, the MDN SVG docs, and the following threads on SO:
我已经阅读了 w3 SVG 文档、MDN SVG 文档以及关于 SO 的以下线程:
Fit <svg> to the size of <object> container
...but even after all that, I haven't managed to find a solution.
……但即便如此,我还是没能找到解决办法。
EDIT: I forgot to mention, this needs to work in IE9. That's a bit of an issue, I'm sure, but IE9's SVG support is decent, which is why I chose SVG for this project.
编辑:我忘了提到,这需要在 IE9 中工作。这有点问题,我敢肯定,但 IE9 的 SVG 支持不错,这就是我为这个项目选择 SVG 的原因。
采纳答案by b1_
Basically, I want to know if there's an easier way to define the cells in the spritesheet and simplify the CSS I use to tell each div which icon to display from the spritesheet.
基本上,我想知道是否有更简单的方法来定义 spritesheet 中的单元格并简化我用来告诉每个 div 从 spritesheet 显示哪个图标的 CSS。
No, you can't do it easier.
不,你不能更容易。
Try this article
试试这篇文章
Then, there's the problem of scaling. With this setup, the SVG scales to the appropriate size to be drawn on-screen, but if I decide to zoom using my browser's zoom, it pixelates. This is not how SVG is supposed to work.
然后,还有缩放问题。通过此设置,SVG 会缩放到要在屏幕上绘制的适当大小,但是如果我决定使用浏览器的缩放功能进行缩放,它会像素化。这不是 SVG 应该如何工作。
In Chromium 18 it looks pretty fine - no pixelations at all.
在 Chromium 18 中,它看起来很不错——根本没有像素化。
In my test browsers list (FF3.6 Opera 9.2 IE6) I didn't see what I saw in Chromium
在我的测试浏览器列表(FF3.6 Opera 9.2 IE6)中,我没有看到我在 Chromium 中看到的内容
And about IE9, maybe problem in engine
关于IE9,可能是引擎问题
回答by Alexander Shutau
If your icons have the same size you can do the following:
如果您的图标大小相同,您可以执行以下操作:
- Pack your icons into sprite horizontally (use svg-spriteif icons are in separate files).
- Set
background-size: auto 100%;
for your target selector. - Set your target elements'
width
,height
orfont-size
for scale.
- 将您的图标水平打包成精灵(如果图标位于单独的文件中,请使用svg-sprite)。
background-size: auto 100%;
为您的目标选择器设置。- 设置您的目标元素'
width
,height
或font-size
缩放。
.icon {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="16" viewBox="0 0 64 16"> <circle fill="blue" cx="8" cy="8" r="8"/> <circle fill="red" cx="24" cy="8" r="8"/> <circle fill="yellow" cx="40" cy="8" r="8"/> <circle fill="green" cx="56" cy="8" r="8"/> </svg>');
background-repeat: no-repeat;
background-size: auto 100%;
display: inline-block;
}
.icon.small {
height: 1em;
width: 1em;
}
.icon.medium {
height: 2em;
width: 2em;
}
.icon.large {
height: 4em;
width: 4em;
}
.icon_1 {
background-position: 0 0;
}
.icon_2 {
background-position: 33.33% 0;
}
.icon_3 {
background-position: 66.67% 0;
}
.icon_4 {
background-position: 100% 0;
}
<span class="icon icon_1 small"></span>
<span class="icon icon_1 medium"></span>
<span class="icon icon_2 large"></span>