原文:http://www.smashingmagazine.com/2014/11/03/styling-and-animating-svgs-with-css/
翻译:叮当当咚当当小胖妞呀 杀手爱elva Ivan_z3 肖弦
CSS可以用来定义可缩放矢量图形的样式和动画,就像CSS定义HTML元素一样。在本文中,我会告诉大家一些用CSS定义SVG的前提条件和技术。(我最近在CSSconf EU和From the Front办了一个讲座,这篇文章是讲座的修正版)
同时我也会讲一下导出和优化SVG、嵌入SVG和每一个SVG如何影响它的样式和动画,然后我们再讨论用CSS定义SVG的样式和动画。
介绍
可缩放矢量图形(SVG)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式,它们支持交互行为和动画。换句话说,SVG是可以生成形状和图形的XML标签,这些形状和图形可以像HTML元素一样实现交互和动画。
我们可以通过CSS或者Javascript给SVG定义动画和交互行为。在本文中,我们着重讨论CSS。
SVG为什么好?为什么你应该使用它?其实答案有很多:
- SVG图形是可缩放并独立于分辨率的,无论是在高分标率的“Retina”屏还是印刷媒体,SVG看上去都很棒。
- SVG的浏览器支持率很好,对于不支持的浏览器,我们也能很容易的实施回退。稍后这篇文章中也会提到。
- 由于SVG基本上是纯文本,它们可以Gzip压缩,这样可以使文件比其他位图(JPEG或者PNG)更小。
- SVG可以通过CSS和Javascript定义交互和样式。
- SVG自带内置图形效果,如裁剪和遮罩、背景虚化模式和滤镜,基本上使用SVG就相当于在你的浏览器中拥有了Photoshop的编辑照片功能。
- SVG是可访问的。其一,SVG的DOM API使得它们成为制作信息图表和数据可视化最好的工具之一,此外,SVG相比HTML5 Canvas来说也更有优势,因为HTML5 Canvas是不可访问的。其二,你可以使用你最喜欢浏览器的开发者工具审查SVG的每一个元素,同时,如果你愿意,SVG对于屏幕阅读器也是可访问的。我们会在这篇文章的最后一个章节讨论一下可访问性。
- 我们可以使用一些工具来创建、编辑和优化SVG,还有一些其他的工具可以使我们更加便捷的操作SVG,节省了很多开发时间。下面我们也会讨论一下这些工具。
从图形编辑器导出SVG并优化
以下是三个最流行的矢量图形编辑器:
Adobe Illustrator是Adobe公司收费的应用程序,它是最受欢迎的编辑器,漂亮的UI和大量的功能使得它成为大多数设计师最喜欢的编辑器。
Inkscape是另一个免费的编辑器,虽然它的UI没有Illustrator漂亮,但是它仍然具有你所需要的所有功能。
Sketch是只能在Mac OS X上使用的app,虽然它也要收费,但是它在设计师中到处宣传并收到了欢迎,最近Sketch又推出了许多资源和工具来改善工作流程。
你可以选择任意编辑器来创建你的SVG。在选择编辑器、创建SVG之后,在把它嵌入网页之前,你需要把它从编辑器中导出并进行清理。
我会导出并优化在Illustrator中创建的SVG,除了Illustrator特定的一些选项,其余步骤跟任何编辑器都基本一致。
如果要从Illustrator中导出SVG,你需要选择“File” -> “Save as”,然后从文件扩展名下拉菜单中选择“.svg”。一旦你选择了.svg扩展名,会出现一系列导出SVG的选项面板,比如使用哪个版本的SVG、是否在图形中插入图片或者在外部保存并把它们链入SVG、如何为SVG添加样式(使用展示属性或者使用CSS的style
标签)。
下图展示了导出SVG的最佳设置:
上图中选项是最佳设置的原因可以参考Michaël Chaize的文章:使用Illustrator CC导出SVG。
无论你使用哪种图形编辑器,输出的都不会是优化的代码。SVG文件,尤其是从编辑器导出的文件,通常包含了很多多余信息,比如编辑器的meta信息、注释、空白的组、默认值、非优值等,这些信息可以被安全的移除或者转换,而不会影响SVG的生成。如果你在使用不是你自己创建的SVG文件,那么代码基本上都是非优的,所以我们推荐使用独立的优化工具优化它。
这里有些优化SVG代码的工具。Peter Collingridge的SVG编辑器是一款在线的工具,你可以直接输入SVG代码,或者上传SVG文件,然后它会提供一些优化的选项,如移除多余代码、注释、空白组、空格等等。其中有一个选项可以让你指定点坐标小数的位数。
Peter的优化工具也可以自动把inline SVG属性移动到文档头部的style
标签中去,这个工具最好的地方在于,当你点击某个选项之后,你能实时看到优化的结果,这样你就可以自主决定使用哪种方法优化。某些特定优化可能会损坏你的SVG。比如,通常一位小数 应该足够了,但是当你在使用一个路径繁多的SVG文件时,如果把小数的位数从四削减到一,你的文件会小掉一半,但是你的SVG也会损坏,所以能够预览优化也是一个很棒的加分点。
Peter的工具是在线的,如果你喜欢使用离线工具,你可以尝试SVGO(其中的“O”是“Optimizer”的缩写),这是一个基于Node.js的工具,它有一个漂亮并简易的拖放GUI。如果你不想要使用在线工具,它会是一个很好的选择。
下面的截图是用Peter的优化工具优化之前和之后的SVG代码:
我们可以看到原始文件和优化文件大小的变化,此外优化的文件更具可读性。
在优化SVG之后,可以把它嵌入web页面,之后用CSS自定义或动画。
用CSS定义SVG样式
HTML和CSS之间的界线很明确:HTML是内容和结构,CSS是样子。而SVG却模糊了这条界线。SVG 1.1不要求使用CSS定义SVG标签的样式——样式是通过“展示属性(presentation attribute)”应用到SVG元素中去的。
展示属性是在元素中设置CSS属性的简写,可以把它们看成一种特殊的样式属性。
下面的例子是使用展示属性为一个星形多边形定义边框样式(stroke
)和背景颜色(fill
):
1
2
3
|
< svg xmlns = "http://www.w3.org/2000/svg" version = "1.1" width = "300px" height = "300px" viewBox = "0 0 300 300" > < polygon fill = "#FF931E" stroke = "#ED1C24" stroke-width = "5" points = "279.1,160.8 195.2,193.3 174.4,280.8 117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 " ></ polygon > </ svg > |
fill
、stroke
和stroke-width
属性都是展示属性。
在SVG中,CSS属性的子集可能是SVG属性,反之亦然。SVG规范罗列了一些可能被设定为CSS属性的SVG属性,其中一些属性和CSS共用,如opacity
和transform
等,其他一些不是,如fill
、stroke
和stroke-width
等。
在SVG2中,这个列表包含x
、y
、width
、height
、cx
、cy
和一些其他的展示属性,这些属性不能在SVG 1.1中通过CSS设置。我们可以在SVG 2规范中找到这些新属性。
另一个设置SVG元素样式的方法是使用CSS属性。就像在HTML中一样,样式可以用inline样式属性设置到元素中去:
1
2
3
|
< svg xmlns = "http://www.w3.org/2000/svg" version = "1.1" style = "width: 300px; height: 300px;" viewBox = "0 0 300 300" > < polygon style = "fill: #FF931E; stroke: #ED1C24; stroke-width: 5;" points = "279.1,160.8 195.2,193.3 174.4,280.8 117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 " ></ polygon > </ svg > |
样式也可以使用style
标签定义,style
标签可以放在svg
标签中:
html
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="300px" viewBox="0 0 300 300">
<style type="text/css">
<![CDATA[
selector {/* styles */}
]]>
</style>
<g id=".."> … </g>
</svg>
你也可以把它放在svg
标签外:
html
<!DOCTYPE html><!-- HTML5 document -->
<html>
<head> … </head>
<body>
<style type="text/css">
/* style rules */
</style>
<!-- xmlns is optional in an HTML5 document →
<svg viewBox="0 0 300 300">
<!-- SVG content -->
</svg>
</body>
</html>
如果你想要把svg跟标签完全分开,你可以使用<?xml stylesheet>
标签链入外部样式表,代码如下:
html
<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/css" href="style.css"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=".." height=".." viewBox="..">
<!-- SVG content -->
</svg>
样式层级
我们之前提到展示属性是一种特殊的样式属性,它们是在SVG节点上设置CSS属性的简写,正由于此,SVG展示属性也是样式层级的一种。
确实,展示属性只作为低端的“作者样式表”,它会被任何其他的样式定义所覆盖,如外部样式表、文档样式表和inline样式。
下面的图表向我们展示了样式的层级,下方的样式表会覆盖上方的样式表,你可以看到,展示属性样式会被其他所有的样式覆盖,除了客户端样式。
例如,在下面的代码片段中描画了一个SVG圆形元素,圆形的填充颜色是深粉色,覆盖了展示属性中定义的蓝色:
html
<circle cx="100" cy="100" r="75" fill="blue" style="fill:deepPink;" />
选择器
大多数CSS选择器可以用来选择SVG元素,除了一般类型的选择器:样式和ID选择器之外,SVG还可以使用CSS2的动态伪类选择器(:hover
、:active
和:focus
)和伪元素(例如:first-child
、:visited
、:link
和:lang
)。剩下的CSS2伪元素,包括生成内容的选择器(例如::before
和::after
)不在SVG的定义中,因此对SVG样式无效。
下面是一个简单的动画代码,一个深粉色的圆形,在hover的时候逐渐变成绿色:
1
2
3
4
5
6
7
|
circle { fill: deepPink; transition: fill .3s ease-out; } circle:hover { fill: #009966; } |
我们还可以创造许多更震撼的效果,Iconic有一个很简单但是很棒的效果,当我们hover在的灯泡上时会点亮灯泡,我们可以看一下这个demo。
注意事项
由于展示属性是用XML属性表达的,所以它们对大小写敏感,例如,当我们要定义元素的填充颜色时,属性必须写成fill = "..."
,而不能写成Fill = "..."
。
此外,这些属性的值(例如font-style = "italic"
中的italic
)也是大小写敏感的,必须按照规范定义中的格式书写。
其他所有以CSS属性定义的样式——无论是inline样式,还是在<style>
标签中,或是在外部样式表中——都是以CSS规范的语法规则定义的,通常它们对大小写不敏感。话虽如此,SVG”样式”规范建议我们完全按照CSS规范中定义的属性名称书写,并使用同一种书写规范(通常我们使用小写字母和中划线),不要利用CSS忽略大小写的特点任意书写。
用CSS制作SVG动画
SVG可以做到像HTML元素一样,用CSS keyframe、animation属性或者CSS transition制作动画。
多数情况下,复杂的动画效果通常包含了一些变换,有translate、rotate、scale和skewing。
在大多数情况下,SVG元素和HTML元素对于transform
和transform-origin
的解读是一样的,然而还是会有一些不可避免的差异。和HTML元素不同的是,SVG元素不会被盒模型所局限,因此它就不会有margin、border、padding以及content boxes。
对于HTML元素来说,transform的原点默认是(50%,50%)
,也就是元素的中心。然而,SVG元素transform的原点默认是用户当前的坐标系统,也就是(0, 0)
,在canvas的左上角。
假设这里有一个html元素 <div>
和一个SVG元素 <rect>
:
html
<!DOCTYPE html>
…
<div style="width: 100px; height: 100px; background-color: orange"> </div>
<svg style="width: 150px; height: 150px; background-color: #eee">
<rect width="100" height="100" x="25" y="25" fill="orange" />
</svg>
如果不改变它们的transform原点,让它们都旋转45度,我们可以得到如图结果(红色的小原点就是它们transform原点所在位置):
如果想让SVG元素在旋转的时候绕着它自己的中心,而不是SVG canvas的左上角,应该怎么做呢?我们需要明确地设置transform-origin
属性来确定transform原点。
如何设置transform原点是很明确的:你设置的值与元素的border box模型相关。
在SVG中,transform原点的值可以是一个百分数或者绝对的数值(比如像素)。如果transform-origin的值是百分数,那么它的位置就和元素的边界框有关。如果它的值是一个绝对的数值,它的位置就和SVG canvas上用户的当前坐标系统有关。
我们把<div>
和<rect>
的transform origin值设为百分数,就像这样:
html
<!DOCTYPE html>
<style>
div,rect {
transform-origin: 50% 50%;
}
</style>
那么最终的变换效果是这样的:
话虽如此,在撰写本文的时候,Firefox还无法支持值为百分比的写法。这是一个大家熟知的bug,因此最好还是使用绝对数值,我们肯定能得到所期待的效果。当然你依然可以选择在WebKit浏览器上使用百分数值。
在接下来的例子中,我们会使用CSS animation来实现风车效果。为了使风车绕着自己的中心旋转,我们会用像素和百分比来设置它的transform origin。
html
<svg>
<style>
.wheel {
transform-origin: 193px 164px;
-webkit-transform-origin: 50% 50%;
-webkit-animation: rotate 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate;
animation: rotate 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate;
}
@-webkit-keyframes rotate {
50% {
-webkit-transform: rotate(360deg);
}
}
@keyframes rotate {
50% {
transform: rotate(360deg);
}
}
</style>
<!-- SVG content -->
</svg>
你可以查看Codepen上的效果。这里要注意的是,在撰写此文的时候,SVG元素上的CSS 3D transformation还 不能使用硬件加速,所以3D的效果跟2D完全一样,然而,Firefox已经 能够一定程度上提升transform的速度。
为SVG路径添加动画
现在还无法用CSS animation将SVG路径从一个形状改变成另外一个形状。如果你想要 改变路径,也就是从一个动画过渡到另一个路径,必须要用到JavaScript。如果你想要实现这样的效果,我建议你使用Dmitry Baranovskiy写的Snap.svg,他还写了SVG Library Raphaël。
Snap.svg相对于SVG的地位就好像jQuery相对HTML的地位一样,它能让我们更简单的处理SVG的一些特殊情况。
虽然不能用CSS改变形状,但是你却可以用CSS来创建一个动态的画线效果。使用animation的时候,你必须要先设定线条路径的总长度,然后用SVG的stroke-dashoffset
和stroke-dasharray
属性实现画画效果。一旦你知道路径长度,就可以通过下面的方法来实现动画了:
css
#path {
stroke-dasharray: pathLength;
stroke-dashoffset: pathLength;
/* transition stroke-dashoffset */
transition: stroke-dashoffset 2s linear;
}
svg:hover #path {
stroke-dashoffset: 0;
}
在上面的例子中,当hover SVG时,图形路径会在2秒内画好。
在接下来的演示中,我们将会用到同样的原理,再加上CSS的transition延迟,让灯泡在路径动画完成时点亮。
css
#cable {
stroke: #FFF2B1;
stroke-dasharray: 4000 4000;
stroke-dashoffset: 4000;
stroke-width: 4;
transition: stroke-dashoffset 8s linear;
}
svg:hover #cable {
stroke-dashoffset: 0;
}
/* turn lamp on */
.inner-lamp{
fill:grey;
transition: fill .5s ease-in 6s;
}
svg:hover .inner-lamp {
fill: #FBFFF8;
}
/* … */
你可以在JS Bin中查看demo,提醒大家,你同样可以写成stroke-dasharray: 4000
而不是stroke-dasharray: 4000 4000
——如果两个值相同,你可以只定义一个值。
有时候,可能你并不能知道动画路径的确切长度,这时,你可以用到JavaScript的getTotalLength()
方法来获取。
js
var path = document.querySelector('.drawing-path');
path.getTotalLength();
//set CSS properties up
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
//set transition up
path.style.transition = 'stroke-dashoffset 2s ease-in-out';
// animate
path.style.strokeDashoffset = '0';
上面这个片段是一个非常简单的例子,它用JavaScript实现了我们之前用CSS达到的效果。
Jake Archibald针对此技术写了一篇详细的文章。Jake在文章里写了一个很棒的交互演示,展现了动画到底是如何实现的,以及这两个SVG属性如何共同实现我们想要的效果。如果你对这个技术感兴趣,我建议你读一下他的文章。
SVG的嵌入
一个SVG文件可以通过六种方法嵌入到文档中,每一种都有各自的优点和缺点。
我们讨论嵌入技术的原因是,你嵌入SVG的方法会影响到一些CSS样式、动画、交互是否会实现。
以下为SVG的嵌入方法:
- 作为图片使用
<img>
标签嵌入:<img src="mySVG.svg" alt="" />
- 作为CSS中的背景图片嵌入:
.el {background-image: url(mySVG.svg);}
- 作为对象使用
<object>
标签嵌入:<object type="image/svg+xml" data="mySVG.svg"><!-- fallback here --></object>
- 作为框架使用
<iframe>
标签嵌入:<iframe src="mySVG.svg"><!-- fallback here →</iframe>
- 使用
<embed>
标签嵌入:<embed type="image/svg+xml" src="mySVG.svg" />
- 行内使用
<svg>
标签嵌入:<svg version="1.1" xmlns="http://www.w3.org/2000/svg" …>
<!-- svg content →
</svg>
从引入外部SVG文件现在大部分都使用<object>
标签,这个标签最大的好处是在SVG没有渲染的时候能够优雅降级,提供图片(或者文本)。当SVG因为某些原因没有加载时——比如提供的URI错误——浏览器就会展现<object>
起始标签和结束标签里面的内容。
html
<object type="image/svg+xml" data="mySVG.svg">
<img src="fallback-image.png" alt="…" />
</object>
如果你想实现高级的SVG特效,比如CSS或者scripting,HTML5的 <object>
标签就是你最好的选择。
因为浏览器在用它们各自的方式渲染SVG文档,所以可以用iframe来完成嵌入和展现SVG。如果你想要完全将SVG代码和脚本在主页面中分离,这会是一个很好的方法。然而,用JavaScript控制SVG图片有点困难,并且同时还会受到同源策略的限制。
<iframe>
标签就像<object>
一样,当浏览器不支持SVG或者因为某些原因无法渲染的时候会提供回退机制。
html
<iframe src="mySVG.svg">
<img src="fallback-image.png" alt="…" />
</iframe>
<embed>
标签不是HTML规范的一部分,却仍然得到了广泛的支持,它用来囊括需要外部插件才能工作的内容。Adobe公司的Flash插件就需要用到<embed>
标签,支持这个标签为唯一原因是为了使用SVG,<embed>
标签没有默认回退机制。
SVG也能使用<svg>
标签inline嵌入到文档中——作为一个”代码块”,这是当下嵌入SVG最主流的方法之一。使用inline的SVG和CSS会比较容易,因为无论样式规则放置在页面的哪个位置都可以轻松定义SVG的样式和动画。也就是说,样式不需要包含在<svg>
标签里,这对于其他技术来说这也是很必要的。
inline嵌入SVG是一个很好的选择,只要你愿意增加页面的尺寸,并且放弃它向下兼容性(因为它没有默认回退机制)。要注意的是,inline嵌入SVG不能缓存。
在定义CSS样式和动画的时候,用<img>
标签和作为CSS背景图片嵌入SVG很类似。一旦嵌入了SVG,外链的CSS资源中的样式和动画不会被保留。
下面的表格展现了用六个不同的方法嵌入SVG时,CSS动画和交互(比如hover效果)是否会被保留。最后一列是将它与 SMIL animations 比较,无论哪种情况, SVG animations (SMIL) 都支持。
CSS交互 (例如:hover) | CSS动画 | SVG动画 (SMIL) | |
---|---|---|---|
<img> |
否 | 是 只在<svg> 中 |
是 |
CSS背景图片 | 否 | 是 只在<svg> 中 |
是 |
<object> |
是 只在<svg> 中 |
是 只在<svg> 中 |
是 |
<iframe> |
是 只在<svg> 中 |
是 只在<svg> 中 |
是 |
<embed> |
是 只在<svg> 中 |
是 只在<svg> 中 |
是 |
<svg> (inline) |
是 | 是 | 是 |
表格展示了当SVG嵌入时,CSS样式、动画和交互是否会被保留
以上表格中都是标准行为的,然而,在每个浏览器中实现效果可能有差异,也可能存在bug。
这里要注意的是,即使SMIL animations会被保留,但在SVG被当做图片嵌入的时候(比如<img>
或者CSS背景图片),SMIL的交互效果也是没有的。
让SVG响应化
在嵌入SVG之后,你需要保证它是响应的。
根据你选择的嵌入技术,你需要应用一些特定的hack使得你的SVG是跨浏览器响应的,这是由于每个浏览器判定SVG的尺寸都不同,每个浏览器中SVG的实施方法也不同。因此,SVG的操作方法不尽相同,我们需要调整一些样式让SVG一直能跨浏览器响应。
我不会过多赘述浏览器矛盾,我只会简单介绍一下让SVG响应式所需的调整和hack。如果你想要了解浏览器矛盾和bug,可以看一下我在Codrops上的文章。
无论你选择什么技术,第一步要做的事情就是从<svg>
元素中删除height
和width
属性。
你需要保留viewBox
属性,并把preserveAspectRatio
属性设为xMidYMid meet
,记住如果preserveAspectRatio
的值已经默认为xMidYMid meet
的话就不需要特意设置了。
当SVG作为CSS的背景图片嵌入时,不需要额外的调整或者hack,SVG会表现的和其他位图背景图片一模一样。
在所有浏览器中,如果SVG是通过<img>
标签嵌入的话,SVG会自动拉伸到容器宽度(当然是在删除<svg>
标签上的宽度值之后),然后它会按照预期伸缩,在除了IE之外的所有浏览器中自适应。IE会把SVG的高度设为150像素妨碍正确的伸缩。为了解决这个问题,你需要把<img>
的宽度设为100%。
html
<img src="mySVG.svg" alt="SVG Description." />
img {
width: 100%;
}
这同样也适用于<object>
标签嵌入,出于同样的原因考虑,你也需要设置<object>
标签的宽度为100%:
css
object {
width: 100%;
}
即使<iframe>
跟<object>
有很多相同之处,浏览器也会分别对待。所有浏览器会默认设置CSS中替换元素的尺寸为300*150像素。
保持SVG宽高比同时让iframe响应式的唯一方法,是使用由A List Apart的Thierry Koblentz首创的“padding hack”。padding hack的思路是利用元素padding和宽度的关系,来创建一个宽高比固定的元素。
当一个元素的padding值设为百分比,这个百分比会根据元素的宽度来计算,即使你设置的是元素的padding-top
或padding-bottom
。
为了应用padding hack并使SVG响应化,SVG需要被装在一个容器中,然后你需要在容器和SVG(例如iframe)中添加样式。
html
<!-- wrap svg in a container -->
<div class="container">
<iframe src="my_SVG_file.svg">
<!-- fallback here -->
</iframe>
</div>
.container {
/* collapse the container's height */
height: 0;
/* specify any width you want (a percentage value, basically) */
width: width-value;
/* apply padding using the following formula */
/* this formula makes sure the aspect ratio of the container equals that of the SVG graphic */
padding-top: (svg-height / svg-width) * width-value;
position: relative; /* create positioning context for SVG */
}
svg-height
和svg-width
变量分别是<svg>
的高度和宽度值——就是我们之前删除的尺寸。width-value
是你想要设置的任何SVG容器宽度。
最后,SVG自身(iframe)需要在容器中绝对定位:
css
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
我们把iframe绝对定位的原因是合并容器的高度再加上padding会导致iframe超出容器边界。所以,“为了把它拉回来”,我们把它绝对定位。欲知详情,请看我Codrops上的文章。
最后,当我们把高度和宽度删除之后,<svg>
标签里的SVG会响应化,因为浏览器会假定一个100%的宽度,使得SVG按照这个宽度伸缩。然后,IE会像我们之前提到的<img>
标签一样,有一个150像素的固定高度。不幸的是,把SVG的高度设为100%对这个bug无用。
为了让SVG在IE中自适应,我们也需要添加padding hack。所以,我们在<svg>
标签外套一个容器,在容器中添加padding hack,最后让<svg>
绝对定位,这里唯一的不同是,我们不需要设定<svg>
的宽高。
css
svg {
position: absolute;
top: 0;
left: 0;
}
使用CSS媒体查询
SVG也会接受并相应CSS媒体查询。你可以使用媒体查询来告便SVG在不同viewport下的样式。
然后这里有个很重要的注意事项,SVG相应地viewport是SVG本身的viewport,不是页面的viewport!
这跟元素查询的概念很像。
当SVG插入<img>
、<object>
和<iframe>
中时,它响应的是这些元素建立起来的viewport。也就是说,这些元素的尺寸会生成描绘SVG的viewport,也会生成CSS媒体查询条件应用的viewport。
下面这个例子展示了包含媒体查询的SVG,SVG指定为<img>
标签:
html
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
<style>
@media all and (max-width: 50em) {
/* select SVG elements and style them */
}
@media all and (max-width: 30em) {
/* styles */
}
</style>
<!-- SVG elements here -->
</svg>
当<img>
的max-width
是50em
或者30em
时,SVG会应用媒体查询中的样式。
html
<img src="my-logo.svg" alt="Page Logo." />
如果你想了解更多SVG中的媒体查询,你可以看一下Dev.Opera中Andreas Bovens的文章。
最后的话
SVG是图片,就像图片有可访问性一样,SVG也有,你需要保证你的SVG具有可访问性。
我还是要再强调一遍:让你的SVG具有可访问性,你有很多种方法实现,如果你想要一个全面的概览,我推荐SitePoint上Leonie Watson的文章,她提出一些很好的方法,比如在<svg>
中使用<title>
和<desc>
标签、使用ARIA属性等。
除了可访问性,不要忘记优化你的SVG,为不支持的浏览器提供回退。我推荐Todd Parker的演讲。
最后,你可以在caniuse上查看不同SVG特性的支持情况。我希望你觉得我这篇文章对你有用的,感谢你的阅读。
本文作者:fhz 转载请注明来自:携程设计委员会