CSS: Change SVG Backgrounds. Styling SVG with CSS. Features and Limitations

This page shows how to use CSS with a special language for creating graphics: SVG.

You'll make a small example that can be run in any browser that supports SVG.

General information: SVG

SVG(Scalable Vector Graphics) is a subset of the XML language and is designed for creating graphics.

SVG can be used for static images, as well as for animations and creating user interfaces.

Like other XML-based languages, SVG supports the use of CSS style sheets, which allows you to decouple different visual options from the data structure.

Additionally, style sheets that you use in other document markup languages ​​may contain a reference to SVG graphics in places where an image is needed. For example, in the style sheet for your HTML document, you can specify a link (URL) to an SVG graphic in the background property.

Some details

At the time of writing (mid-2011), most modern browsers have basic SVG support, including Internet Explorer 9 and higher. Some advanced SVG features are not supported, or are only partially supported, in certain browsers. For more information on current SVG support, see SVG tables on caniuse.com, or see the SVG element reference compatibility tables for information on individual element support.

In other versions, you can add SVG support by installing an additional plugin, for example, provided by Adobe.

For more information about SVG in Mozilla, see the SVG page on this wiki.

Get to Work: SVG Demo

Create a new SVG document as a regular text file, doc8.svg. Copy and paste the contents of the block below, making sure to scroll all the way through to copy everything:

SVG demonstration Mozilla CSS Getting Started - SVG demonstration SVG demonstration Move your mouse pointer over the flower.

Create a new CSS file, style8.css. Copy and paste the contents of the block below, making sure to scroll all the way through to copy everything:

/*** SVG demonstration ***/ /* page */ svg ( background-color: beige; ) #heading ( font-size: 24px; font-weight: bold; ) #caption ( font-size: 12px; ) /* flower */ #flower:hover ( cursor: crosshair; ) /* gradient */ #fade-stop-1 ( stop-color: blue; ) #fade-stop-2 ( stop-color: white; ) /* outer petals */ #outer-petals ( opacity: .75; ) #outer-petals .segment-fill ( fill: azure; stroke: lightsteelblue; stroke-width: 1; ) #outer-petals .segment-edge ( fill: none; stroke: deepskyblue; stroke-width: 3; ) #outer-petals .segment:hover > .segment-fill ( fill: plum; stroke: none; ) #outer-petals .segment:hover > .segment-edge ( stroke: slateblue; ) /* inner petals */ #inner-petals .segment-fill ( fill: yellow; stroke: yellowgreen; stroke-width: 1; ) #inner-petals .segment-edge ( fill: none; stroke: yellowgreen; stroke-width: 9; ) #inner-petals .segment:hover > .segment-fill ( fill: darkseagreen; stroke: none; ) #inner-petals .segment:hover > .segment-edge ( stroke: green; )

Open the document in your SVG-enabled browser. Move your mouse pointer over the image.

This wiki does not support inserting SVG into pages, so we are not able to demonstrate it here. The image will look like this:

What's next?

In this demo, your SVG-enabled browser already knows how to render SVG elements. The style sheet just changes the display in some way. The same thing happens with HTML and XUL documents. However, CSS can be used for any XML document that does not have a default way to render elements. This example is shown on the following page:

CSS is becoming more powerful every day, with many new features emerging that make it much easier to create user interfaces. And that is great!

One such feature in CSS is filters. Let's try using filters to work with SVG images.

CSS filters

First, let's take a look at filters. They include the following features:

  • blur()
  • brightness()
  • contrast()
  • drop-shadow()
  • grayscale()
  • hue-rotate()
  • invert()
  • opacity()
  • saturate()
  • sepia()

CSS filters are the easiest way to implement basic transformations in a browser-efficient manner.

If you want to see how each filter works, we recommend visiting the website: cssfilters.co.

Editing SVG backgrounds

I love using SVG (scalable vector graphics) format on the web. SVG is a great image format for the web. When you add an SVG to a page, you have access to every element and property within it. This allows you to add animation, change colors, and dynamically add information. SVG is also great for icons.

SVG is often used as background images. In this case, you lose control over the elements of the image. You now cannot change colors or properties, since the SVG becomes a regular image. But with the help of CSS filters you can solve this problem.

Brightness adjustment

The first thing I encountered when working with icons was the need to darken a white icon on a light background. To avoid creating a new dark icon, I used filter: brightness().

A brightness value greater than 1 makes the element brighter, less than 1 makes the element darker.

Icons with color #000 or rbg(0, 0, 0) will not be clarified. They must be any other color.

Color adjustment

We looked at how to change the brightness of the icon. But what if we want to change the color of the icon? In this case, a filter will help us sepia, hue-rotate, brightness And saturation to create any color we want.

From white you can create, for example, blue, cyan and pink.

Colorize-pink ( filter: brightness(0.5) sepia(1) hue-rotate(-70deg) saturate(5); .colorize-navy ( filter: brightness(0.2) sepia(1) hue-rotate(180deg) saturate( 5); ) .colorize-blue ( filter: brightness(0.5) sepia(1) hue-rotate(140deg) saturate(6); )

Compatibility

At the time of writing, filters are supported by the following browsers:

Instead of a conclusion

Never forget about your users. So far, filters do not work everywhere. Therefore, do not use white filter icons on a white background, as some users simply will not see anything. Also, don’t forget about alternative text for images.


Original article: link Author of the article: Alex. Category:
Date of publication: 04/01/2018

SVG is the new standard for vector images in the browser. Vector editors such as Adobe Illustrator allow you to directly save the file in this format, and modern browsers have no problem displaying SVG correctly. Since SVG graphics are made up of markup, they can be created and modified in your favorite text editor that you use for HTML. It's even possible to style SVG using CSS, but there are a few subtleties here.

The dividing line between HTML and CSS is pretty straight. HTML is responsible for the content and structure, and CSS takes care of the appearance of the projects. In SVG this line is blurred. This is the main reason why text and shapes in SVG are typically controlled using element attributes rather than CSS:

In this example we have drawn a rectangle which is filled in using fill . The color and strength of the outer rectangle frame is determined by the attributes stroke and stroke-width.. But, the rectangle can be styled in the same way using CSS:

However, this does not work for all attributes. You won't be able to define positions and values ​​for width and height this way. We'll just stick with the y , width and height attributes.

Just like in HTML, we could work with classes and IDs on any element. So we would define the appearance of multiple elements in an SVG using a styled class.

Using Pseudo-Classes

Using pseudo-classes such as:hover is possible in SVG, even in combination with the CSS3 transition property.

By implementing this example, hover elements carrying the example class will cause the color to change from red to blue. For this to work properly, make sure the SVG is not inserted as an Img. Better choose Embed or Iframe:

Using Img will help the SVG display properly. But, hover effects and transitions will be ignored. In addition to transition, we could use transform, thereby allowing elements to be scaled or rotated.

When using CSS3, be sure to add vendor prefixes to support as many modern browsers as possible. While Chrome and Firefox have no problem rendering flawlessly, Internet Explorer will refuse to show your creations even in the latest version, while it is perfectly capable of showing these CSS3 properties when used in HTML.

Media queries and SVG

If you want to customize your SVG so that it can change sizes, then just use media queries directly in it:

This example ensures that elements of class example will not be shown as soon as the visible width drops below 800 pixels. Be aware that it is not the width of the document that determines this, but the width of the element carrying your SVG.

In this example, elements of the example class will not be shown, since the specified width is only 500 pixels. Media queries in SVG are also useful for optimizing graphics for printing.

Detailed article on styling content in an SVG element and overcoming related problems.

Graphics in the SVG format are especially often used to create icons, and one of the most common techniques for this is SVG sprites using SVG use to instantiate icons in the right place in the document.

Instantiating icons or any other SVG content into an element causes difficulties when designing individual copies. The purpose of this article is to give you an overview of some possible ways to get around the design restrictions associated with using .

But before we begin, let's quickly look at the basic structure and grouping of elements in SVG, gradually moving on to , DOM, and then back to the CSS. We will look at why the design can cause difficulties and how to overcome them.

A quick overview of SVG structure, grouping, and element referencing in SVG

SVG includes 4 basic elements to define, structure, and link to SVG content in a document. These elements allow images to be reused while keeping the code readable and maintainable. Due to the nature of SVG, some of these elements have functionality similar to the corresponding commands in graphics editors.

The 4 main grouping and linking elements of SVG are: , , and .

Element (short for “group”) is used to logically group sets of related graphic elements. In terms of graphic editors (such as Adobe Illustrator), the element Its functionality is similar to the “Group objects” function. You can also think of a group as a layer in a graphics editor.

Grouping elements is useful in cases where you want to apply a style to all elements of a group, and also when you want to animate all elements of a group while maintaining the relationship between them.

Element is used to define many things, mainly defining patterns such as gradients, which can then be used to fill other SVG elements. It can be used to define any elements that you are going to use anywhere on the canvas.

Element combines possibilities And one that is used to group elements together to create a pattern that can be referenced elsewhere in the document. Unlike , not used to set patterns; it is typically used to create symbols such as icons, which are then used throughout the document.

At the element There is another important advantage: it accepts a viewBox attribute, which allows zooming within any scope.

Element allows you to use a previously defined element anywhere in the document. It allows you to reuse elements and provides functionality similar to copy-paste in a graphics editor. It can be used either as a single element or as a group specified in , or .

To use an element you need to pass a link to this element, the identifier is the xlink:href attribute and position it by setting the x and y attributes. You can apply styles to an element and they will cascade onto the content of this element.

But what is the content? ? Where does it clone? And how does CSS cascade work with it?

Before we answer these questions, and given that we've only had a quick look at SVG structure and grouping, it's worth mentioning a couple of articles that will let you learn more about these elements, as well as the viewBox attribute on an element :

  • Structuring, Grouping and Linking in SVG - The g, use, defs and symbol elements
  • Understanding the SVG coordinate system (Part 1): Viewport, viewBox and PreserveAspectRatio

SVG and shadow DOM

When you refer to an element with , your code looks something like this:

An icon is displayed on the screen, the contents of which are defined internally , but it's actually the content of the element , which is a clone .

But the element it's just one self-closing element - there's no content between the opening and closing tags, so where does the content get cloned? ?

The answer is in shadow DOM(for some reason I always associate him with Batman, I don’t know why).

What is shadow DOM?

The shadow DOM is identical to the regular DOM, except that instead of being part of the main document tree, shadow DOM nodes refer to a fragment of the document that is parallel to the main document, but is not accessible to its scripts and styles. This gives authors the ability to create modular components by encapsulating scripts and styles. If you've ever used a video element or range input in HTML5 and didn't understand where the video player or slider controls came from, then the answer is the same - the shadow DOM.

In the case of an SVG element , the content it refers to is cloned into a document fragment “hosted” in . In this case this is a shadow host.

So the contents (clone or copy of the element it refers to) is present inside the shadow document fragment.

In other words, the content is there, but it is invisible. The same as the contents of the regular DOM, but not accessible to high-level features such as CSS and JavaScript selectors, copied into a document fragment bound to .

Now, if you're a designer, you might be thinking, "OK, I get it, but is there a way to inspect this subdocument and see its contents." The answer is yes, you can view the contents of the shadow DOM using the development tools in Chrome (this feature is not available in Firefox at the moment). But first, you need to activate the shadow DOM inspector in the General tab of the settings panel. This is described in detail.

Once you've enabled Shadow DOM Inspection in Developer Tools, you can see cloned elements in the Toolbox, just like regular DOM elements. The following image shows an example element , referencing the content of the element . Please note that “#shadow-root” and its contents are a clone of the contents .

Using the Chrome Developer Tools, you can inspect the contents of the use element inside the shadow DOM (“#shadow-root”, the line grayed out). This screenshot inspects the Codrops logo from the example we'll look at in the next section.

Looking at the inspected code, you can see that the shadow DOM is very similar to the regular DOM, except for the way it is handled by the CSS and JavaScript of the main document. There are also other differences between the two that we won't cover in this article due to length, so if you want to learn more, I recommend the following articles:

  • Shadow DOM 101 (translated by Frontender.info)
  • Introduction to Shadow DOM (Video)

Given my limited experience with the shadow DOM, I view it as a regular DOM that needs to be handled differently in terms of CSS and JavaScript access to its elements. This is what is important to us when working with SVG: how to influence the content inside the shadow DOM, because it is important for us to be able to style it. The whole point of using this is the ability to create different copies of an element and in most cases we need to be able to style each copy differently. For example, this could be a logo in two color themes or multi-color icons for different color themes. So it's important for us to be able to do this with CSS.

As stated, the contents of the shadow DOM are not accessible to CSS, unlike the regular DOM. So how do we style it? We can't use a descendant path like this:

Use path#line ( stroke: #009966; )

Because we don't have access to the shadow DOM using regular CSS selectors.

You might expect, as I do, that presentational attributes have the highest specificity of all style rules. After all, external styles are usually overwritten by internal declarations, and these, in turn, are overwritten by inline attribute styles - they have maximum specificity, and, accordingly, priority over other styles. While this expectation makes sense, the actual mechanism at work is different.

In fact, presentational attributes are treated as low-level “author style sheets” and they are overwritten by other style declarations: external, internal and inline styles. Their only strength is their priority over inherited styles. That's all.

Now that we have that cleared up, let's go back to our element and its contents.

We know that we can't set styles internally using CSS selectors.

But we also know that, as with the element , styles applied to will be inherited by all of its descendants (which are in the shadow DOM).

So, first let's try to change the fill color of the element inside by applying the selector to the element itself with the expectation that cascade and inheritance will do their job.

However, this raises a couple of questions:

  1. The fill color will be inherited all descendants element , even ones you don't want to apply styles to (but if inside If you have only one element, then this problem will not occur).
  2. If you exported the SVG from a graphics editor or are otherwise unable to modify the SVG code, then you will end up working with an SVG that already has presentation attributes applied (unless you explicitly disable this when exporting to SVG format) and the values ​​of these attributes will take precedence over those inherited from .

And even if you can edit the SVG code and can get rid of them, I strongly recommend not to do so for the following reasons:

  1. Removing attributes in order to subsequently set certain properties will reset the values ​​of these properties to the default, and this is, as a rule, a black fill and stroke (in relation to colors).
  2. By resetting values, you force yourself to style the entire set of properties.
  3. Presentation attributes, which are initially set, are a great fallback in case of problems with external styles. If the CSS doesn't load, your icons will still look nice.

So we have these attributes, but we want to style different instances of the icons differently.

This is done by forcing the presentation attributes to inherit the styles specified or finding a way around overriding these values. To do this, we will have to use the full power of CSS cascading.

Let's start with simple examples and gradually move on to complex ones.

Rewriting presentation attribute values ​​using CSS

Presentation attributes are overridden by any style declaration. We can use this to ensure that the presentation attribute receives a value inherited from the styles .

This is easy thanks to the CSS inherits keyword. Take a look at the following example - an ice cream icon drawn with a single outline, the color of which we want to change in different instances. The icon was created by Erin Agnoli from Noun Project.

The content of our ice cream icon (path) is defined inside the element , which means that it will not be displayed on the canvas by default.

We display multiple instances of an icon using .

We set the width and height of the icons using CSS. I'm using the same dimensions as the viewBox, but they don't have to be identical. However, to avoid excess white space within the SVG, make sure you maintain the aspect ratio.

Icon (width: 100px; height: 125px; )

With this code we got the following result:

Notice that thanks to the added black borders around our SVGs, you can see the borders of each one, including the first one where the content is not rendered. Remember: the SVG document in which you defined symbol will be displayed on the page, but without content. To prevent this, use the display: none property on the first SVG. If you don't hide the SVG with icon definitions, it will appear on the screen even if you don't size it - it will occupy the default 300 by 150 pixels (this is the default value for non-replaced elements in CSS) and you will end up with an empty block on the screen that you don't need .

Now let's try to change the fill color for each icon instance:

Use.ic-1 ( fill: skyblue; ) use.ic-2 ( fill: #FDC646; )

The fill color of the icons still does not change, since the inherited color is overwritten by the fill="#000" attribute in the path element. To prevent this from happening, we need to force path to inherit the color:

Svg path ( fill: inherit; )

Voila! Colors assigned to elements are now applied to the path of each of them. Check out the demo and experiment with the values ​​by creating instances and giving them different colors:

Now this technique works after we forced the content inherit styles. But in many cases this is not exactly what you need. There are other design methods, we will now move on to some of them.

Content design using the CSS all property

Some time ago, while working on an icon activated with , I needed one of the elements inside it to inherit all the styles , such as fill , stroke , stroke-width , opacity and even transform . So I needed to control all of these attributes through CSS, while keeping all the presentational attributes in the markup as a fallback.

If you encounter a similar task, you'll probably think it would take too long to do everything in CSS:

Path#myPath ( fill: inherit; stroke: inherit; stroke-width: inherit; transform: inherit; /* ... */ )

Having looked at this snippet, you will notice a pattern, which means it would make sense to combine all the specified properties into one and set it to inherit .

Luckily, the CSS all property can help us. My CSS reference book mentions using the all property to style SVG, but it's worth a refresher.

Using the all property we can do this:

Path#myPath ( all: inherit; )

This works fine in all browsers that support all , but there's one important thing to consider: this declaration tells the element to inherit literally all of the properties of its parent, including those you don't want the element to have. So unless you want all CSS properties to be styled, this won't work for you - it's a last resort and is only partially suitable when you have an unstyled element and full control over its properties in the CSS. If you use this declaration and don't define values ​​for all CSS properties, they will cascade until they find a value to inherit, in most cases the browser's default styles.

Note that this only applies to attributes that can be set using CSS, not attributes that can only be set in SVG. If the attribute can be set using CSS, it will inherit styles, otherwise not.

Ability to enable inheritance of presentation attributes for all styles , but what if you have an icon consisting of several elements and you don't want them all to inherit the same fill color? What if you want to apply many different fill colors to different children? Specifying one style in no longer suitable. We need something different to cascade the right colors to the right elements.

Using the CSS currentColor variable to style content

Using the CSS currentColor variable in combination with the technique described above allows you to define two colors for an element rather than just one. Fabrice Weinberg wrote about this a year ago.

The idea is to simultaneously apply to fill and color properties and then cascade those properties to the content , using the capabilities of the currentColor variable. Let's look at some example code to understand how it works.

Let's say we want to design this minimalistic Codrops logo using 2 colors - one for the front drop and one for the back.

First, let's start with the code for this image: we have a symbol containing a description of the icon and three instances , creating three copies of the logo.

If we set the fill color in the element for each instance, this color will be inherited by both blobs, which is not our goal.

So instead of defining the fill color and cascading it in the usual way, we'll use the currentColor variable so that the smaller blob in the foreground will be a different color and we'll set that value using the color property.

First, we need to insert currentColor where we want to apply this color - this will be the place in the markup where the icon is defined, that is, inside . Now this fragment looks like this:

Next, we need to remove the presentational fill attribute from the second droplet and let it inherit the element's fill color using inherit .

If we were to use the inherit keyword to force presentation attributes to inherit values ​​from , both parts would inherit the same value, and currentColor would have no effect. Therefore, in this technique, we need to remove the attribute that we want to set via CSS, and leave only the one in which we will use currentColor .

Now, using the fill and color properties in We will add styles to the drop from the logo:

Codrops-1 ( fill: #4BC0A5; color: #A4DFD1; ) .codrops-2 ( fill: #0099CC; color: #7FCBE5; ) .codrops-3 ( fill: #5F5EC0; color: #AEAFDD; )

Each element gets its own fill and color value. In each, the fill color is cascaded to fill the first path that does not have a fill attribute, and the color property color is used to set the fill attribute in the second path.

So what happened is that the current color value leaked into the element's content styles by using the currentColor variable. Graceful, isn't it?

Here's a demo with the code used:

This two-color technique is great for two-color logos. In his article, Fabrice created three different versions of the Sass logo, changing the color of the text relative to the background.

The currentColor keyword is the only CSS variable available at the moment. However, if we had more variables, could we use them to populate even more values ​​in the content? ? Yes, we could. Amelia Bellamy-Royds introduced the concept for this on her Codepen blog a year ago. Let's see how it works.

The Future: Content Design using CSS variables

The robot code contains all the colors that make up it:

Now, we won't be using CSS variables as fill attribute values ​​for each outline. Instead, we'll use them as fill colors using the CSS fill property, keeping all the fill attributes in place. These attributes will be used as a fallback for browsers that don't support CSS variables - the image will appear as is if the CSS variables don't work.

With the added variables the code will be as follows:

Because inline style tags override presentation attributes, browsers that support CSS variables will use these variables to set the fill color. Browsers that don't support them will use the fill attribute.

Next we need to set the values ​​for the variables in CSS. But first we instantiate the image using :

<xlink:href="#robot" id="robot-1" />

After that, we will set the values ​​of the variables for use so that they can cascade to its contents. The colors you choose will create the color scheme of the drawing. Since our robot uses three primary colors, we will call them primary, secondary and tertiary.

#robot-1 ( --primary-color: #0099CC; --secondary-color: #FFDF34; --tertiary-color: #333; )

You can still use the fill and color properties in conjunction with these variables, but you can get away with it just fine. So, with the colors specified in our variables, the robot looks like this:

You can use as many copies of the image as you like and set each of them to a set of different colors, creating different themes. This is partially useful when you want to style the logo in different ways depending on the context and other similar cases.

As mentioned, browsers that don't support CSS variables use the given presentation attributes as a fallback, and browsers that do support CSS variables use them to populate the fill property and overwrite attributes. But what happens if the browser supports CSS variables, but you forgot to set these variables in styles or set the wrong value?

For our hipster robot, we set three variables and only a few of its fragments do not depend on them - after all, it was originally developed for possible theming. So if you run this code in a browser that supports CSS variables and remove all declarations that declare those variables, you will get the following result:

If variable values ​​are not set or are not correct, the browser will use its default color, which is usually black for fill and stroke in SVG.

A workaround for this is to set a different color as a fallback for supporting browsers. The CSS variable syntax allows you to do this: Instead of passing the variable name as an argument to var(), you pass two arguments separated by a comma - the variable name and a fallback, in this case the value for the presentation attribute.

So now our robot code looks like this:

And it's all. If any variable doesn't have a value set, the browser will always have a color set as a fallback. Amazing.

Using this technique you can display this robot anywhere on the page using , assigning different colors to each instance and resulting in different color themes in the end.

You can experiment with the demo, create as many copies of the robot as you like and color it with any colors - just remember that you must use a browser that supports CSS variables to do this:

If you view this demo in a browser that supports CSS variables, you will see a blue and yellow version of the robot among others, just like we set in the CSS variables. Otherwise, you will see three identical robots with a fallback color.

Summing up

This was a great article.

Using the power of CSS cascade, content styling stored in the shadow DOM becomes less complex. And with CSS variables (currentColor or custom properties) we can reach into the shadow DOM and customize our graphics however we want, while creating a fallback in case of problems.

Personally, I really like the combination of CSS and SVG variables. I like their combined functionality, especially in terms of creating a fallback mechanism.

We may also receive other ways to style the content. in the future, as discussions continue about using CSS variables as SVG parameters - so this article does not cover everything there is to learn on this topic.

Working with reusable SVG content is one of the tricky parts of SVG, it has to do with the behavior and placement of the code being cloned. There are a lot of related issues that arise here that could become the topic of separate articles.