×

Web前端开发中SVG在CSS里的玩法,您学会了吗?

作者:Terry2019.11.28来源:Web前端之家浏览:13845评论:0
关键词:svgcss


500.jpg

SVG是一种轻量级的矢量图像格式,用于在Web和其他环境上显示各种图形,并支持交互性和动画。在本文中,我们将探讨将CSS与SVG结合使用的各种方法,以及将SVG包含在网页中并对其进行操作的方法。

自1999年以来,可伸缩矢量图形(SVG)格式一直是开放标准,但是自Internet Explorer 9发布以来,浏览器的使用在2011年变得可行。如今,尽管更多高级功能可能有所不同,但所有浏览器都很好地支持SVG。

SVG的好处

位图图像(例如PNG,JPG和GIF)定义了各个像素的颜色。100×100 PNG图像需要10,000像素。每个像素需要四个字节来表示红色,绿色,蓝色和透明性,因此生成的文件为40,000个字节(再加上一些元数据)。应用压缩以减小文件大小;PNG和GIF使用类似ZIP的无损压缩,而JPG有损,并删除不太明显的细节。

位图是照片和更复杂图像的理想选择,但是随着图像放大,清晰度会下降。

SVG是用XML定义的矢量图像。点,线,曲线,路径,椭圆,矩形,文本等在SVG画布上绘制。例如:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">
  <circle cx="400" cy="300" r="250" stroke-width="20" stroke="#f00" fill="#ff0" />
</svg>

所述viewBox定义的坐标空间。在此示例中,从位置0,0开始的800×600区域具有一个黄色圆圈,并在中心绘制了红色边框:

1.jpg


向量优于位图的优点:

  • 上面的SVG使用的字节数少于150个,比同等的PNG或JPG小得多

  • SVG背景默认为透明

  • 图像可以缩放到任意大小而不会降低质量

  • SVG代码/元素可以在服务器或浏览器上轻松生成和操纵

  • 就可访问性和SEO而言,文本和绘图元素是机器和人类可读的。

SVG非常适合徽标,图表,图标和更简单的图表。尽管SVG已用于延迟加载占位符,但通常仅照片是不切实际的。

SVG工具

这是了解有用的基本的SVG绘图,但你很快就想用,可以生成的代码编辑器创建更复杂的形状。选项包括:

  • Adobe Illustrator(商业)

  • Affinity Designer(商业)

  • Sketch(商业)

  • Inkscape(开源)

  • Gravit Designer(免费,在线)

  • Vectr(免费,在线)

  • SVG-Edit(开源,在线)

  • Boxy SVG(免费,应用程序,在线,但仅Blink浏览器)

  • Vecteezy –(免费,在线,但仅Blink浏览器)

  • SVG图表库 -通常使用传递给JavaScript函数的数据来创建SVG图表。

每个都有不同的优势,对于看似相同的图像,您将获得不同的结果。通常,更复杂的图像需要更复杂的软件。

通常,可以使用SVGO(大多数构建工具都提供插件)来简化和最小化结果代码,或者使用Jake Archibold的SVGOMG交互式工具。

SVG作为静态图像

在HTML <img>标签或CSS中使用时background-url,SVG的作用与位图相同:

<!-- HTML image -->
<img src="myimage.svg" alt="a vector graphic" />


/* CSS background */.myelement {
  background-image: url('mybackground.svg');}

浏览器将禁用SVG文件中嵌入的所有脚本,链接和其他交互功能。您可以使用CSS来操作SVG,其方式与使用transformfilters等的其他图像相同。使用CSS与SVG的结果通常优于位图,因为SVG可以无限缩放。

CSS内联SVG背景

SVG可以直接嵌入CSS代码中作为背景图像。这对于较小的可重复使用的图标非常理想,并且避免了其他HTTP请求。例如:

.mysvgbackground {
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600"><circle cx="400" cy="300" r="50" stroke-width="5" stroke="#f00" fill="#ff0" /></svg>') center center no-repeat;
}

可以使用标准UTF-8编码(而不是base64),因此如有必要,可以轻松地编辑SVG图像。

带有SVG的CSS:响应式SVG图像

创建响应式网站时,通常通常会省略<img> widthheight赋予属性,并通过CSS将图片调整为最大宽度:

img {
  display: block;
  max-width: 100%;
}

但是,用作图像的SVG没有隐式尺寸。您可能会发现的max-width计算为零,并且图像完全消失了。要解决此问题,请确保使用默认值,widthheight<svg>标记中进行了定义:

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300">

注意:尺寸不应添加到内联SVG中,因为我们将在下一部分中发现……

HTML内嵌的SVG图片

SVG可以直接放入HTML中。完成此操作后,它们将成为DOM的一部分,并且可以使用CSS和JavaScript进行操作:

<p>SVG is inlined directly into the HTML:</p>

<svg id="invader" xmlns="http://www.w3.org/2000/svg" viewBox="35.4 35.4 195.8 141.8">
  <path d="M70.9 35.4v17.8h17.7V35.4H70.9zm17.7 17.8v17.7H70.9v17.7H53.2V53.2H35.4V124h17.8v17.7h17.7v17.7h17.7v-17.7h88.6v17.7h17.7v-17.7h17.7V124h17.7V53.2h-17.7v35.4h-17.7V70.9h-17.7V53.2h-17.8v17.7H106.3V53.2H88.6zm88.6 0h17.7V35.4h-17.7v17.8zm17.7 106.2v17.8h17.7v-17.8h-17.7zm-124 0H53.2v17.8h17.7v-17.8zm17.7-70.8h17.7v17.7H88.6V88.6zm70.8 0h17.8v17.7h-17.8V88.6z"/>
  <path d="M319 35.4v17.8h17.6V35.4H319zm17.6 17.8v17.7H319v17.7h-17.7v17.7h-17.7V159.4h17.7V124h17.7v35.4h17.7v-17.7H425.2v17.7h17.7V124h17.7v35.4h17.7V106.3h-17.7V88.6H443V70.9h-17.7V53.2h-17.7v17.7h-53.2V53.2h-17.7zm88.6 0h17.7V35.4h-17.7v17.8zm0 106.2h-35.5v17.8h35.5v-17.8zm-88.6 0v17.8h35.5v-17.8h-35.5zm0-70.8h17.7v17.7h-17.7V88.6zm70.9 0h17.7v17.7h-17.7V88.6z"/>
</svg>

<p>The SVG is now part of the DOM.</p>

没有widthheight属性的SVG定义的,所以它可以大小包含元素或使用CSS被直接尺寸,看个DEMO:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body {
        font-family: sans-serif;
        }

        #invader {
        display: block;
        width: 200px;
        margin: 3em auto;
        animation: move 2s ease-in-out 0s infinite alternate;
        }

        #invader path {
        stroke-width: 0;
        fill: #080;
        animation: flash 1s linear 0s infinite alternate;
        }

        #invader path:hover {
        fill: #c00;
        }

        @keyframes move {
        0% { transform: translate(-200px); }
        50% { transform: scale(1.2); }
        100% { transform: translateX(200px); }
        }

        @keyframes flash {
        0% { opacity: 1; }
        0% { opacity: 0.4; }
        }

    </style>
</head>
<body>
    <p>SVG is inlined directly into the HTML:</p>
    <svg id="invader" xmlns="http://www.w3.org/2000/svg" viewBox="35.4 35.4 195.8 141.8">
    <path d="M70.9 35.4v17.8h17.7V35.4H70.9zm17.7 17.8v17.7H70.9v17.7H53.2V53.2H35.4V124h17.8v17.7h17.7v17.7h17.7v-17.7h88.6v17.7h17.7v-17.7h17.7V124h17.7V53.2h-17.7v35.4h-17.7V70.9h-17.7V53.2h-17.8v17.7H106.3V53.2H88.6zm88.6 0h17.7V35.4h-17.7v17.8zm17.7 106.2v17.8h17.7v-17.8h-17.7zm-124 0H53.2v17.8h17.7v-17.8zm17.7-70.8h17.7v17.7H88.6V88.6zm70.8 0h17.8v17.7h-17.8V88.6z"/>
    <path d="M319 35.4v17.8h17.6V35.4H319zm17.6 17.8v17.7H319v17.7h-17.7v17.7h-17.7V159.4h17.7V124h17.7v35.4h17.7v-17.7H425.2v17.7h17.7V124h17.7v35.4h17.7V106.3h-17.7V88.6H443V70.9h-17.7V53.2h-17.7v17.7h-53.2V53.2h-17.7zm88.6 0h17.7V35.4h-17.7v17.8zm0 106.2h-35.5v17.8h35.5v-17.8zm-88.6 0v17.8h35.5v-17.8h-35.5zm0-70.8h17.7v17.7h-17.7V88.6zm70.9 0h17.7v17.7h-17.7V88.6z"/>
    </svg>

    <p>The SVG is now part of the DOM and can be manipulated in CSS and JavaScript.</p>
    <script>
        const
        viewX = [35.4, 283.6],
        animationDelay = 400,
        invader = document.getElementById('invader');

        let frame = 0;

        setInterval(() => {
        frame = ++frame % 2;
        invader.viewBox.baseVal.x = viewX[frame];
        }, animationDelay);
    </script>
</body>
</html>

SVG元素(例如路径,圆形,矩形等)可以被CSS选择器作为目标,并使用标准SVG属性作为CSS属性来修改样式。例如:

/* CSS styling for all SVG circles */
circle {
  stroke-width: 20;
  stroke: #f00;
  fill: #ff0;
}

这会覆盖SVG中定义的所有属性,因为CSS具有更高的特异性。SVG CSS样式具有以下优点:

  • 可以从SVG中完全删除基于属性的样式,以减少页面权重

  • CSS样式可以在任意数量的页面上的任意数量的SVG中重复使用

  • 全SVG或图像的各个元素可具有CSS效果应用于使用:hovertransitionanimation等。

SVG精灵

单个SVG文件可以包含任意数量的单独图像。例如,此folders.svg文件包含IcoMoon生成的文件夹图标。每个都包含在一个单独的<symbol>容器中,该容器具有可以定位的ID:

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <symbol id="icon-folder" viewBox="0 0 32 32">
      <title>folder</title>
      <path d="M14 4l4 4h14v22h-32v-26z"></path>
    </symbol>
    <symbol id="icon-folder-open" viewBox="0 0 32 32">
      <title>open</title>
      <path d="M26 30l6-16h-26l-6 16zM4 12l-4 18v-26h9l4 4h13v4z"></path>
    </symbol>
    <symbol id="icon-folder-plus" viewBox="0 0 32 32">
      <title>plus</title>
      <path d="M18 8l-4-4h-14v26h32v-22h-14zM22 22h-4v4h-4v-4h-4v-4h4v-4h4v4h4v4z"></path>
    </symbol>
    <symbol id="icon-folder-minus" viewBox="0 0 32 32">
      <title>minus</title>
      <path d="M18 8l-4-4h-14v26h32v-22h-14zM22 22h-12v-4h12v4z"></path>
    </symbol>
    <symbol id="icon-folder-download" viewBox="0 0 32 32">
      <title>download</title>
      <path d="M18 8l-4-4h-14v26h32v-22h-14zM16 27l-7-7h5v-8h4v8h5l-7 7z"></path>
    </symbol>
    <symbol id="icon-folder-upload" viewBox="0 0 32 32">
      <title>upload</title>
      <path d="M18 8l-4-4h-14v26h32v-22h-14zM16 15l7 7h-5v8h-4v-8h-5l7-7z"></path>
    </symbol>
  </defs>
</svg>

可以将SVG文件引用为HTML页面中的外部缓存资源。例如,要显示文件夹图标#icon-folder

<svg class="folder" viewBox="0 0 100 100">
  <use xlink:href="folders.svg#icon-folder"></use>
</svg>

并使用CSS设置样式:

svg.folder { fill: #f7d674; }

该方法有两个缺点:

  1. 在IE9 +中失败。

  2. CSS样式仅适用于<svg>包含的元素<use>。在fill这里,使图标的每个元素相同的颜色。

为了解决这些问题,可以将SVG精灵嵌入页面HTML中,然后使用display: none或类似技术将其隐藏。可以通过引用ID来放置单个图标:

<svg><use xlink:href="#icon-folder"></use></svg>

看个DEMO:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body {
        font-family: sans-serif;
        font-size: 100%;
        }

        .icons {
        display: flex;
        justify-content: space-between;
        margin: 0;
        padding: 0;
        list-style-type: none;
        }

        .icons li {
        margin: 3px;
        }

        .icons svg {
        display: block;
        width: 100%;
        fill: #f7d674;
        }


    </style>
</head>
<body>
        <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;">
            <defs>
            <symbol id="icon-folder" viewBox="0 0 32 32">
            <title>folder</title>
            <path d="M14 4l4 4h14v22h-32v-26z"></path>
            </symbol>
            <symbol id="icon-folder-open" viewBox="0 0 32 32">
            <title>open</title>
            <path d="M26 30l6-16h-26l-6 16zM4 12l-4 18v-26h9l4 4h13v4z"></path>
            </symbol>
            <symbol id="icon-folder-plus" viewBox="0 0 32 32">
            <title>add</title>
            <path d="M18 8l-4-4h-14v26h32v-22h-14zM22 22h-4v4h-4v-4h-4v-4h4v-4h4v4h4v4z"></path>
            </symbol>
            <symbol id="icon-folder-minus" viewBox="0 0 32 32">
            <title>remove</title>
            <path d="M18 8l-4-4h-14v26h32v-22h-14zM22 22h-12v-4h12v4z"></path>
            </symbol>
            <symbol id="icon-folder-download" viewBox="0 0 32 32">
            <title>download</title>
            <path d="M18 8l-4-4h-14v26h32v-22h-14zM16 27l-7-7h5v-8h4v8h5l-7 7z"></path>
            </symbol>
            <symbol id="icon-folder-upload" viewBox="0 0 32 32">
            <title>upload</title>
            <path d="M18 8l-4-4h-14v26h32v-22h-14zM16 15l7 7h-5v8h-4v-8h-5l7-7z"></path>
            </symbol>
            </defs>
            </svg>
            
            
            <h1>Folder icons</h1>
            
            <ul class="icons">
              <li><svg><use xlink:href="#icon-folder"></use></svg></li>
              <li><svg><use xlink:href="#icon-folder-open"></use></svg></li>
              <li><svg><use xlink:href="#icon-folder-plus"></use></svg></li>
              <li><svg><use xlink:href="#icon-folder-minus"></use></svg></li>
              <li><svg><use xlink:href="#icon-folder-download"></use></svg></li>
              <li><svg><use xlink:href="#icon-folder-upload"></use></svg></li>
            </ul>
            
    <script>
    </script>
</body>
</html>

这适用于IE9 +的所有现代浏览器,并且可以使用CSS在每个图标中设置单个元素的样式。

不幸的是,SVG集不再被缓存,并且必须在需要图标的每个页面上复制。解决方案(针对此解决方案!)是使用Ajax加载SVG(然后将其缓存),然后将其注入页面中。该IcoMoon下载提供了一个JavaScript库。

SVG对HTML内容的影响

SVG长期以来一直支持:

  • masks: 更改元素各部分的可见性

  • clipping: 删除元素的分段,以便标准的常规框变为任何其他形状

  • filters: 图形效果,例如模糊,亮度,阴影等。

这些影响已经被移植到CSS maskclip-path以及filter性能。但是,仍然可以定位SVG选择器:

/* CSS */
.myelement {
  clip-path: url(#clip);
}

这引用了嵌入HTML的SVG中的效果:

<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;">
  <defs>
    <clipPath id="clip">
      <text x="0" y="200" font-family="Arial" font-size="10em" font-weight="800">Text Clip</text>
    </clipPath>
  </defs>
</svg>

产生效果,例如带有图像或渐变背景的剪切文本,来个DEMO看下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .area {
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            background: radial-gradient(circle, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(252,176,69,1) 100%);
            clip-path: url(#clip);
        }


    </style>
</head>
<body>
        <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;">
            <defs>
              <clipPath id="clip">
                <text x="0" y="200" font-family="Arial" font-size="10em" font-weight="800">Web前端之家</text>
              </clipPath>
            </defs>
          </svg>
          
          <div class="area"></div>
            
    <script>
    </script>
</body>
</html>

便携式SVG

最后,独立的SVG可以包含CSS,JavaScript和base64编码的字体或位图图像!XML范围以外的任何内容都应包含在<![CDATA[… ]]>部分中。

考虑以下invader.svg文件。它使用悬浮效果和修改viewBox状态的JavaScript动画定义CSS样式:

<svg id="invader" xmlns="http://www.w3.org/2000/svg" viewBox="35.4 35.4 195.8 141.8">
  <!-- invader images: https://github.com/rohieb/space-invaders !-->
  <style>/* <![CDATA[ */
    path {
      stroke-width: 0;
      fill: #080;
    }

    path:hover {
      fill: #c00;
    }
  /* ]]> */</style>
  <path d="M70.9 35.4v17.8h17.7V35.4H70.9zm17.7 17.8v17.7H70.9v17.7H53.2V53.2H35.4V124h17.8v17.7h17.7v17.7h17.7v-17.7h88.6v17.7h17.7v-17.7h17.7V124h17.7V53.2h-17.7v35.4h-17.7V70.9h-17.7V53.2h-17.8v17.7H106.3V53.2H88.6zm88.6 0h17.7V35.4h-17.7v17.8zm17.7 106.2v17.8h17.7v-17.8h-17.7zm-124 0H53.2v17.8h17.7v-17.8zm17.7-70.8h17.7v17.7H88.6V88.6zm70.8 0h17.8v17.7h-17.8V88.6z"/>
  <path d="M319 35.4v17.8h17.6V35.4H319zm17.6 17.8v17.7H319v17.7h-17.7v17.7h-17.7V159.4h17.7V124h17.7v35.4h17.7v-17.7H425.2v17.7h17.7V124h17.7v35.4h17.7V106.3h-17.7V88.6H443V70.9h-17.7V53.2h-17.7v17.7h-53.2V53.2h-17.7zm88.6 0h17.7V35.4h-17.7v17.8zm0 106.2h-35.5v17.8h35.5v-17.8zm-88.6 0v17.8h35.5v-17.8h-35.5zm0-70.8h17.7v17.7h-17.7V88.6zm70.9 0h17.7v17.7h-17.7V88.6z"/>
  <script>/* <![CDATA[ */
    const
      viewX = [35.4, 283.6],
      animationDelay = 500,
      invader = document.getElementById('invader');

    let frame = 0;

    setInterval(() => {
      frame = ++frame % 2;
      invader.viewBox.baseVal.x = viewX[frame];
    }, animationDelay);

  /* ]]> */</script>
</svg>

在HTML <img>或CSS背景中引用时,SVG成为初始状态(本质上是第一个动画帧)的静态图像:

1.jpg


但是,在其自己的浏览器选项卡中打开图像,所有效果都会返回。

这对于分发需要一定程度的嵌入式交互性的图像,演示或小型文档可能很有用。

复杂的SVG

SVG在网页内外都提供了广泛的技术可能性。将CSS与SVG结合使用时,可以以有趣的方式对整个图像或单个元素进行样式设置和动画处理。

本文介绍了处理SVG图像的方法,但是它们通常用于较小的视觉增强,例如:

  • 表单重点摘要和验证

  • 将汉堡菜单变成X关闭图标

  • 产生类似熔岩灯的变形。

Web开发人员在探索通过将CSS与SVG结合使用来转换无聊的基于块的页面的方法,从而产生微妙的效果。如果您创建任何有趣的示例,都可以加群分享或者留言。

您的支持是我们创作的动力!
温馨提示:本文作者系Terry ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/svg8230948203984.html

网友评论文明上网理性发言 已有0人参与

发表评论: