Use SVG in conjunction with media queries

Original link: www.sitepoint.com/using-svg-w…

In HTML documents, we can show, hide, or rearrange parts of the page based on viewport conditions. For example, if the browser window is 480 pixels wide, we might move the navigation from horizontal navigation to a vertical foldable list. We can do something similar when we use SVG with media queries.

This article is adapted from Tiffany’s book CSS Master, 3rd edition. If you want to master other advanced CSS3 features such as Flexbox and Grid, check it out!


In addition to using CSS with HTML, we can also use CSS with SVG or Scalable Vector Graphics. SVG is a markup format for describing flat, two-dimensional images. Because it is a markup language, it has a document object model and can be used with CSS.

By using CSS with SVG, we can change the appearance of SVG based on user interaction. Or we can use the same SVG document in multiple places and show or hide parts of it depending on the width of the viewport.

All the major browser engines support the SVG 1.1 specification, and they have done so for years. Support for features in SVG 2, on the other hand, is still a work in progress. At the time of writing, some of the things we’ll discuss here have limited browser support. By the time you read this article, that may have changed. Keep an eye on Chromium meta-issues – implement SVG2 functionality – to track progress on chromium-based browsers. Watch support SVG 2 feature meta-issues to follow up on the Firefox implementation, and WebKit implementation SVG 2 meta-issues for Safari. Problem tracker navigation can be unpleasant, but for now, they are the best way to track SVG 2 support.

However, before we go any further, let’s talk about what SVG is and why you should use it.

Vector image and raster image

Most of the images used on the network today are raster images, also known as bitmap images. Raster images consist of pixels on a fixed grid, with a certain number of pixels per inch. JPEG, WebP, GIF, and PNG are examples of raster image formats.

Raster images are related to resolution. 144 PPI (pixels per inch) PNG images look great on devices with 144 PPI display resolution. However, the same image may look blurry when viewed on a higher-resolution 400 PPI monitor. Raster images also have fixed sizes and look best in their original size. Scaling a 150 x 150 pixel image to 300 x 300 pixels will distort it.

The vector image format does not use pixels on a grid, but rather describes the original shapes (circles, rectangles, lines, or paths) that make up the image and their positions in the document coordinate system. Therefore, vector images are resolution independent and can maintain their quality regardless of display resolution or display size.

Resolution independence is the biggest advantage of SVG. We can zoom in and out of the image without losing quality. The same image looks great on both high and low PPI devices. That said, SVG is not well suited to the amount of color data required for photos. Best for drawing and shape. Use it instead of PNG and GIF images and as a more flexible alternative to icon fonts.

Another advantage of SVG is that it is intended for use with other Web languages. SVG images can be created, modified, and manipulated using JavaScript. Or, as we’ll see below, we can use CSS to style and animate SVG.

Associate CSS with an SVG document

Using CSS with SVG is very similar to using it with HTML. We can use CSS to apply attributes of styleSVG elements, use

usestyleattribute

Here is a simple SVG document where the code creates a black circle:

< SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" viewBox = "0 0 200 200" ➥ enable - background = "new 0 0 200 200" > < SVG > </ SVG >Copy the code

The following diagram shows how this code is rendered in the browser.

Let’s use CSS and the style property:

< SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" viewBox = "0 0 200 200" ➥ enable - background = "new 0 0 200 200" > Cx = "circle" 101.3 "cy =" 96.8 "r =" 79.6 "style =" the fill: # f9f "/ > < / SVG >Copy the code

The effect is shown below.

This is one difference between using CSS in HTML and CSS in SVG: attribute names. Many OF the CSS properties we use in HTML documents are not compatible with SVG and vice versa. We will return to this point later in this chapter.

Using the style property is certainly not the best way to use CSS. Doing so limits the ability to reuse these styles across multiple elements or documents. Instead, use inline or linked CSS.

Embed CSS in an SVG document

Instead of using the style attribute, we can use the

< SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" viewBox = "0 0 ➥ 200 200" enable - background = "new 0 0 200 200" > <style type="text/ CSS "> Cx =} < / style > < circle "101.3" cy = "96.8" r = "79.6" / > < / SVG >Copy the code

Embedding CSS in SVG documents allows us to reuse these styles for multiple elements in the same document, but it prevents CSS from being shared across multiple documents. This is great for logos and ICONS. However, if you are creating something like a chart style library, it is best to use external CSS files.

Using a standard text editor, you can also add CSS to SVG images created using software such as Sketch, Inkscape, or Illustrator. Doing so does not affect your ability to edit images using a drawing application, but if you use graphics software to edit files, the application may rewrite or delete your CSS.

Link from SVG to external CSS files

As with HTML, links to external CSS files can share styles across multiple SVG documents. To link to an external CSS file, add
to the beginning of the SVG file:

<? The XML version = "1.0" encoding = "utf-8"? > <? xml-stylesheet href="style.css" type="text/css"? > < SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" viewBox = "0 0 ➥ 200 200" enable - background = "new 0 0 200 200" > < SVG > </ SVG >Copy the code

use<link>The element

Alternatively, use an HTML element. If you do use this method, you need to include the XMLNS namespace attribute, as shown below:

< link href = "style.css. CSS" type = "text/CSS" rel = "stylesheet" ➥ XMLNS = "http://www.w3.org/1999/xhtml" / >Copy the code

Note: Some older browsers require it<link>Enveloped elements<defs>or<g>The label.

This element is not an SVG element. It belongs to HTML and XHTML. XHTML is an HTML variant parsed according to XML markup rules. According to the rules of XML, we can borrow elements and their behavior from other XML dialects, such as XHTML. To do this, however, we need to tell the browser which namespace the element belongs to, using the XMLNS attribute.

use@import

We can also use the

tags linked to the external stylesheet @import:

<style type="text/css"> 
@import('style.css'); 
</style> 
Copy the code

The function of this method is similar to the method.

SVG and<img>Elements: Constraints

Linking from SVG files to external resources, including CSS files, does not work with elements. This is a security limit for embedded browser elements.

If you want to use linked CSS for SVG images, you need to do one of two things:

  • use<style>Elements in an SVG document to place CSS inline
  • use<iframe>or<object>Element (see comments below)

Note: Craig Buckler’s tutorialHow to add scalable vector graphics to your web page”Discusses the use<iframe>and<object>In more detail.

In general, you should use

Inline SVG with external resources

When SVG is added to HTML, the browser does not load external resources referenced by an SVG document. However, we can link from an SVG document to CSS our HTML document:

⋮ <link href="svg.css" type="text/ CSS "rel="stylesheet" /> </ header >Copy the code

SVG elements in HTML documents also become part of the HTML document tree. If you are using inline SVG, it is good to combine HTML-related CSS and SVG-related CSS in the same stylesheet.

Differences between SVG and HTML

Although SVG and HTML are both markup languages, there are two significant differences between them that affect how they use CSS:

  • SVG does not follow the CSS box model
  • SVG lacks a positioning scheme

SVG does not follow the CSS box model

When used with HTML, CSS layouts follow the rules of the CSS box model. SVG, on the other hand, uses coordinates for layout. It follows what is best understood as a “shape model.”

SVG shapes are not limited to rectangular boxes. Therefore, most attributes associated with the box model do not apply to SVG elements. For example, you cannot change the padding or marginSVG elements. You also can’t use box-sizing, box-shadow, outline, or border-* features. Grid layouts, floats, and Flexbox don’t work either.

However, you can use CSS to set or change a number of SVG properties and property values. An overview of the complete list in the SVG 2 specification, although most browser support is incomplete. Some CSS attributes, such as filter, can be used with SVG or HTML. In this chapter, we will discuss some of these in the context of specific technologies.

SVG lacks a positioning scheme

When CSS is used with HTML, element boxes can:

  • Exists in normal flow
  • Deleted from normal trafficfloatproperty
  • Deleted from normal trafficpositionproperty

The CSS specification calls these positioning schemes. There is no positioning scheme in SVG. The position attribute has no effect on the SVG element. There are also no attributes like top, left, and bottom, depending on the element being located. You also cannot float elements in an SVG document.

Instead, SVG uses coordinate systems to place elements. To create a

, for example, you need to use the Cx and cy attributes and use the R attribute. A polygon consists of a series of point coordinates and a line segment drawn between them. In other words, you can define where to draw elements to an SVG canvas, but you cannot “locate” them in the sense of CSS words.

Related to positioning schemes, SVG also lacks z-index and stack contexts.

Note:SVG 2 The specification is indeedz-indexAnd stack context in SVG documents, but most browsers do not yet support it.

SVG elements are stacked according to their source order. Those that appear later in the document are at the top of the stack. If you want to change the stacking order of SVG elements, you need to move them around in the source or reorder them in the DOM tree using JavaScript.

In fact, most CSS 2.1 attributes do not apply to SVG documents. Exceptions include animations and transforms, display, overflow, visibility, filter, and some font – and text-related properties. Instead, you must assign svG-specific style attributes to be used with an SVG document. Most of these attributes can also be represented as SVG element attributes.

Style SVG elements

This is a simple example of how to style an SVG element using CSS. The first is our SVG document, which is a separate file:

<? The XML version = "1.0" encoding = "utf-8"? > <? xml-stylesheet href="styles.css" type="text/css" ? > < SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" XMLNS: xlink ➥ = "http://www.w3.org/1999/xlink" x = "0 px" y = 0 px "" ViewBox ="0 0 497 ➥ 184" enable-background="new 0 0 497 184" XML :space="preserve"> <polygon id="star" points="77,23.7 98.2,66.6 145.5,66.5 111.2, ➥106.9,119.3,154 77,131.8 34.7,154 42.8,106.9 8.5,67.5 55.8, ➥ 66.6 "/ > < circle id =" circle "cx =" 245 "cy =" 88.9 "r =" 67.5 "/ > < / SVG >Copy the code

This tag creates the image shown below.

Although we cannot use most CSS attributes for SVG documents, we can use CSS to change the colors of elements. Let’s turn the stars yellow:

# star {fill: HSL (44, 100%, 50%); }Copy the code

You’ll often see fill as an attribute used with SVG tags — for example,

— but it’s also an attribute that can be used with CSS.

We can also use CSS to adjust the element’s stroke, which is the outline of the SVG shape. The stroke of the shape exists even if no stroke property is set. Let’s give our circle a dark blue dotted border ten pixels wide. We will also set it’s fill property to CornflowerBlue:

Circle {filler: cornflower blue; Stroke: dark blue; Stroke width: 10; Stroke - Dasharray: 10, 15; Stroke line cap: round; }Copy the code

This gives us the following result.

Use SVG properties as CSS properties

We can also use CSS to set coordinate values for some shape elements:

,

, and

. Typically, we use SVG attributes for these elements:


<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg"> <rect x="20" y="200" width="300" height="300" fill="#f60"  /> </svg>Copy the code

However, SVG 2 redefines some SVG attributes as geometric attributes. This means we can use CSS to set their values:

< SVG viewBox = "0 0 400 400" XMLNS = "http://www.w3.org/2000/svg" > < style type = "text/CSS" > rectangular {x: 20 px; Y: 50 px; Width: 300px; Height: 300px; Fill: #f60; } </style> <rect /> </svg>Copy the code

Coordinate properties (x and y), center properties (cx and cy), and radius properties (rx, RY, and R) can be set using CSS. So it can be width and height. Units are optional for SVG attributes. CSS values, on the other hand, require units. Both length and percentage are valid for the attributes mentioned here, but note that length works slightly differently in SVG documents. Remember that the S in SVG stands for extensible. The calculated size of an SVG element also depends on:

  • Calculation of thewidthandheightRoot SVG element
  • The value of the root elementviewBoxattribute
  • Any scaling transformations applied to the element or its ancestors

In other words, our corner

elements are (20, 50), (20, 320), (350, 320), and (20, 350) in the SVG coordinate system. However, the actual size may be larger or smaller, depending on the factors mentioned above.

Not every SVG attribute is available via CSS — at least not in every browser. For example, Chrome and Edge support using the CSS path() function to set path data, or the D property:

Path {d: path ("M 454.45223, 559.21474-304.96705,163.45948 417.4767, -296.33928z "); }Copy the code

At the time of this writing, they are the only browsers that can do this. Work on adding support in Firefox and WebKit has not yet begun.

For other shape elements, the SVG 2 specification is completely inconsistent. So far, you have to use element attributes to set , , and elements.

That is, we are not limited to using type (or element) selectors to set attributes. For example, we can use class selectors to define small, medium, and large circles:

< SVG viewBox = "0 0 400 400" XMLNS = "http://www.w3.org/2000/svg" > < style type = "text/CSS" >. Small {cx: 20px; Cy: 20 px; r: 20px; Fill: #0c0; }. Medium {cx: 80px; Cy: 80 px; r: 60px; Filling: # fc0; }. Large {cx: 220px; cy: 220px; r: 120px; Fill: #00f; } </style> <circle class="small" /> <circle class="medium" />Copy the code

Regardless of the selector, using CSS syntax to specify properties also makes it easy to animate them. We’ll learn how to do this in the next section.

Animate and convert SVG CSS properties

Using CSS with SVG becomes even more interesting when we add transitions and animations to the mix. This process is similar to setting up animations for HTML elements using CSS, but with SVG-specific attributes. Let’s create a twinkling star effect using the following SVG document:

< SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" x = "0 px" ➥ y = "0 px" viewBox = "0 0 497 184" XML: space = "preserve" > > < definition < link href = "twinkle. CSS" type = "text/CSS" rel = "stylesheet" ➥ XMLNS = "http://www.w3.org/1999/xhtml" / > < / definition > < polygon Class ="star" points="77,23.7 98.2,66.6 145.5,66.5 111.2 ➥,106.9 119.3,154 77,131.8 34.7,154 42.8,106.9 8.5,67.5 ➥ /> <polygon class="star twinkle" points="77,23.7 98.2,66.6 145.5 ", ➥ 66.5 111.2, 106.9, 119.3, 34.7, 154, 77131.8 154, 42.8, 106.9 ➥ 8.5, 67.5, 55.8, 66.6, "/ > < / SVG >Copy the code

Our document contains two star-shaped polygon elements, each with a class name of star. To create the flicker effect, we will animate the first one. Here is our CSS:

@keyframe flicker {from {fill opacity:.4; } to {fill opacity: 0; Transformation: ratio (2); }} instead! Star {fill: RGB (255,195,0); Transform origin: 50% 50%; }. Blink {animation: blink for 1.5 seconds infinitely slow forward; }Copy the code

Here we use the svG-specific property fan-opacity. As with CSS, if we can insert the value of an SVG style attribute, we can animate or transition it. You can see two differences in the animation below.

Let’s look at another example. This time we will create the stroke-Dasharray property by transitioning the drawing effect. Here is our SVG document:

< SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" ➥ XMLNS: xlink = "http://www.w3.org/1999/xlink" x = "0 px" y = 0 px "" ViewBox ="0 0 200 200" enable-background="new 00 200 200"> <circle fill="transparent" stroke-width="16" cx="101.3" ➥ Cy = "96.8" r = "79.6" / > < / SVG >Copy the code

This stroke-Dasharray property accepts a comma-separated list of length or percentage values to create a dashed pattern. Odd values determine the length of the line. Even values determine the length of the gap. A stroke-dasharray value of 5, 10 means the stroke will be 5px long with a gap of 10px between each dash. A value of 5, 5, 10 replaces the difference between the 5px and 10px dash lengths.

We can use stroke-da harray to create a drawing effect by starting with a zero dashed length and a large gap and ending with a large dashed length and a zero dashed gap. And then we’ll transition between the two. Here’s what our CSS looks like:

Circle {transition: stroke-Dasharray 1s buffer; Fill: transparent; Stroke - Dasharray: 0, 500; }. Animate {stroke -dasharray: 500, 0; }Copy the code

At the beginning of the transition, our stroke is not visible, because the dashed line length is 0 and our gap is 500. But when we added the animate class to our circle, we moved the dash length to 500 and eliminated the gap. The effect is a bit like drawing a circle with a compass. Why 500? This is the minimum to create this special effect.

Animation path future

Remember the example of defining paths through CSS from the previous section? Someday, we might be able to animate paths using CSS in every browser:

Path {d: path (" M357.5451L506.889 192.25h208.111l357.5451z "); Transition: D 1s slow in and slow out; }. Straighten {d: path (" m357.58871L406-10113.75h208.111L357.5351z "); }Copy the code

However, until now, only Chromium-based browsers (such as Google Chrome and Microsoft Edge) have supported animating path definitions in this way. To make it work in other browsers, use JavaScript libraries such as GreenSock and its MorphSVGPlugin. In addition to cross-browser compatibility, GreenSock and MorphSVGPlugin make it easier to morph between two shapes regardless of the number of points in each shape.

For HTML documents, we might show, hide, or rearrange parts of the page based on viewport conditions. For example, if the browser window is 480 pixels wide, we might move the navigation from horizontal navigation to a vertical foldable list. We can do similar things with media queries and SVG documents. Consider a logo, such as the fictional Hexagon Web Design & Development logo shown below.

If there is no media query, the SVG flag is simply stretched or contracted to fit the viewport or its container. But with media inquiries, we can do smarter things.

Let’s distinguish between HTML document viewports and SVG document viewports. When SVG is inlined, an HTML viewport and an SVG viewport are the same thing. SVG documents behave like any other HTML element. On the other hand, when an SVG document is linked — like the

Media queries work in both cases, but when an SVG document is linked, its viewport is independent of its HTML document. In this case, the size of the browser window does not determine the size of the SVG viewport. Instead, viewport sizes are defined by ,

< SVG version = "1.1" id = "HexagonLogo" XMLNS = "http://www.w3.org/2000/ ➥ SVG" XMLNS: xlink = "http://www.w3.org/1999/xlink" X ="0px" y="0px" ➥ viewBox="0 0 555 174" XML :space="preserve"> < definition > <style type="text/ CSS "> /* CSS is here */ </style> </ definition > <g id=" hexadecimal "> <polygon id="hexagonbg" points="55.2,162 10,86.5 55.2,11 ➥ 145.5,11 190.7,86.5 145.5,162"/> <path Id ="letterH" fill="#FFFFFF" d="M58, 35.5h33v35.2h18.➥ 4v35.5H33.2v103.4h-33.2V-38.3h91v38.3h58v35.5z m75.5126.5v87. V39 ➥ 3 h45. 6. 2 h4v47. 9 h - 4 v35. 6 h77. 5 v47. 9 h - 4 v78. 6 h77. 5 z "/ > < / g > < g id =" word - mark "> id =" hexagon - the word "> < g... </g> <g id="web-design-and-dev"> ... </g> </g> </svg>Copy the code

Note: A full demonstration of this technique is provided, including the full source of this SVG documentCode in the code archive.

In the smaller viewport, let’s display H only in the hexagon symbol:

@media (Max width: 320px) {[id=word-mark] {Display: none; }}Copy the code

Now, whenever our SVG container is less than or equal to 20em, only the symbolic part of our logo is visible.

To trigger this view from an HTML document, set the width of the SVG container:

<iframe src="hexlogo.svg" style="width: 320px; border:0"></iframe> 
Copy the code

As you may have noticed when looking at the image above, our SVG image retains its intrinsic size, even if parts of it are hidden. Unfortunately, this is a limitation of SVG. To fix it, we need to change the properties of the viewBoxSVG document, but only if the viewport is smaller than a certain size. This is a good use case for matchMedia (discussed in Chapter 10, “Applying CSS conditionally”).

This viewBox property, as the name implies, determines the viewable area of an SVG element. By tuning it, we can determine which part of the SVG image fills the viewport. Here is an example using matchMedia and a media query to update viewBox properties:

<script type="text/javascript"> const svg = document.querySelector('svg'); /* Store the original value ina variable */ const originalViewBox = svg.getAttribute('viewBox'); /* Define our media query and media query object */ const mq = matchMedia('(Max width: 320px)'); /* Define handler */ const updateViewBox = () => {if (mq.matches) {/* Change viewBox size to display hexagon */ svg.setattribute ('viewBox', '0 0, 200, 174'); } other {svg.setattribute ('viewBox', originalViewBox); } } svg.addEventListener('SVGLoad', updateViewBox); /* Trigger if the media condition changes */ mq.addEventListener('change', updateViewBox); < / script >Copy the code

Now, whenever the SVG container is less than or equal to 320 pixels, the viewBox will be “0 0 200 174”. When you exceed 320 pixels, the viewBox returns to its initial value.

Since this technique uses the onload event attribute or SVGLoad event, embedding our CSS and JavaScript in SVG files is a good idea. When CSS is external, the SVGLoad event may fire before its associated CSS has finished loading.

Using media querybackground-size

SVG documents and media queries are not limited to foreground images. We can also use CSS to resize the BACKground-size property of the SVG viewport.

We’ll start with this SVG document:

<? The XML version = "1.0" encoding = "utf-8"? > < SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" ➥ XMLNS: xlink = "http://www.w3.org/1999/xlink" x = "0 px" y = "0 px" ➥ ViewBox =" -20-20 250 250" XML :space="preserve"> <style type="text/ CSS "> Stroke width: 30; Fill: #009688; } @media (width: 100px) {circle {fill: #673ab7; }} @media (width: 300px) {circle {fill: #ffc107; }} < / style > < / definition > < circle cx = "100" cy = "100" r = "100" / > < circle cx = "100" cy = "100" r = "50" / > < / SVG >Copy the code

This is a simple case. Our

element gets the color of the new fill specific viewport width. When the viewport is 20 pixels wide, the fill value is turquoise. When it’s 300 pixels wide, it’s yellow.

To do this, we must use our SVG image as the background image and set the background-size property of the selector. In this case, we will use our image as the background element and for the

  • element:
  • Body, li {background: url (circles.svg); } Body {background color: # 9c27B0; Background size: 300px automatic; } li {background position: left center; 2. Not to repeat; Background size: 1EM automatic; padding-left: 40px; Font size: 24px; Margin: 1rem 0; }Copy the code

    The result is shown below.

    conclusion

    Using SVG in conjunction with CSS gives us the possibility of more flexible and adaptive documents. You should now know how to:

    • Style SVG elements using CSS

    • Animate SVG properties

    • Apis for displaying and hiding parts of SVG documents using CSS media queries and matchMedia