C次元

Dimension C

[转]【译】用css定义svg的样式和动画

【译】用css定义svg的样式和动画

fhz发表于 2015-03-04
类别:
前端开发

原文:http://www.smashingmagazine.com/2014/11/03/styling-and-animating-svgs-with-css/
翻译:叮当当咚当当小胖妞呀 杀手爱elva Ivan_z3 肖弦

CSS可以用来定义可缩放矢量图形的样式和动画,就像CSS定义HTML元素一样。在本文中,我会告诉大家一些用CSS定义SVG的前提条件和技术。(我最近在CSSconf EUFrom 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并优化

以下是三个最流行的矢量图形编辑器:

  1. Adobe Illustrator,
  2. Inkscape,
  3. Sketch

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的最佳设置:

导出SVG的最佳设置

上图中选项是最佳设置的原因可以参考Michaël Chaize的文章:使用Illustrator CC导出SVG

无论你使用哪种图形编辑器,输出的都不会是优化的代码。SVG文件,尤其是从编辑器导出的文件,通常包含了很多多余信息,比如编辑器的meta信息、注释、空白的组、默认值、非优值等,这些信息可以被安全的移除或者转换,而不会影响SVG的生成。如果你在使用不是你自己创建的SVG文件,那么代码基本上都是非优的,所以我们推荐使用独立的优化工具优化它。

这里有些优化SVG代码的工具。Peter Collingridge的SVG编辑器是一款在线的工具,你可以直接输入SVG代码,或者上传SVG文件,然后它会提供一些优化的选项,如移除多余代码、注释、空白组、空格等等。其中有一个选项可以让你指定点坐标小数的位数。

SVG编辑器

Peter的优化工具也可以自动把inline SVG属性移动到文档头部的style标签中去,这个工具最好的地方在于,当你点击某个选项之后,你能实时看到优化的结果,这样你就可以自主决定使用哪种方法优化。某些特定优化可能会损坏你的SVG。比如,通常一位小数 应该足够了,但是当你在使用一个路径繁多的SVG文件时,如果把小数的位数从四削减到一,你的文件会小掉一半,但是你的SVG也会损坏,所以能够预览优化也是一个很棒的加分点。

Peter的工具是在线的,如果你喜欢使用离线工具,你可以尝试SVGO(其中的“O”是“Optimizer”的缩写),这是一个基于Node.js的工具,它有一个漂亮并简易的拖放GUI。如果你不想要使用在线工具,它会是一个很好的选择。

下面的截图是用Peter的优化工具优化之前和之后的SVG代码:

优化之前和之后的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>

fillstrokestroke-width属性都是展示属性。

在SVG中,CSS属性的子集可能是SVG属性,反之亦然。SVG规范罗列了一些可能被设定为CSS属性的SVG属性,其中一些属性和CSS共用,如opacitytransform等,其他一些不是,如fillstrokestroke-width等。

在SVG2中,这个列表包含xywidthheightcxcy和一些其他的展示属性,这些属性不能在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元素对于transformtransform-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原点所在位置):

transform-origin

如果想让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>

那么最终的变换效果是这样的:

transform-origin

话虽如此,在撰写本文的时候,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-dashoffsetstroke-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的嵌入方法:

  1. 作为图片使用<img>标签嵌入:<img src="mySVG.svg" alt="" />
  2. 作为CSS中的背景图片嵌入:.el {background-image: url(mySVG.svg);}
  3. 作为对象使用<object>标签嵌入:<object type="image/svg+xml" data="mySVG.svg"><!-- fallback here --></object>
  4. 作为框架使用<iframe>标签嵌入:<iframe src="mySVG.svg"><!-- fallback here →</iframe>
  5. 使用<embed>标签嵌入:<embed type="image/svg+xml" src="mySVG.svg" />
  6. 行内使用<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>元素中删除heightwidth属性。

你需要保留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-toppadding-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-heightsvg-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-width50em或者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 转载请注明来自:携程设计委员会

本文章由经典老宋创作,转载请注明来源:C次元

© 2024 C次元 — Powered by WordPress

Theme by Anders NorenUp ↑

%d 博主赞过: