Css svg fill on hover. Styling SVG with CSS: Features and Limitations
SVG is new standard vector images in the browser. Vector editors, such as Adobe Illustrator, allow you to directly save graphics in this format, and modern browsers display SVG without problems.
Because the SVG images consist of markup and can be created and maintained using your favorite text editor, just as you would with HTML. Moreover, you can even style SVG with using CSS, although you will need to become familiar with the differences between SVG and HTML styling.
SVG attributes and CSS properties
The line between HTML and CSS is clear. HTML is responsible for content and structure, CSS for display. In SVG this line is blurred, to say the least. This main reason that text boxes and shapes are usually controlled using element attributes rather than CSS:
In this example, we draw a rectangle that is filled using the fill attribute. The color and width of the rectangle's outer border are specified by the stroke and stroke-width attributes. But you can also style the rectangle like this using CSS:
We simply used attributes as CSS properties. Although, this does not work for all attributes. You cannot set the position and width and height values this way. We'll just use the y attribute, as well as width and height.
Just like in HTML, we can work with classes or identifiers of any element. So we would define a representation for a set of SVG elements through a styled class.
Because SVG does not differentiate between the head and body regions, style sheets and the content itself share the SVG element, which is comparable to the HTML element.
Using Pseudo-Classes
SVG allows the use of pseudo-classes such as:hover , even in conjunction with the CSS3 transition property.
Having implemented this example, we will see that when we hover over an element with the example class set for it, the fill color will change from red to blue. For this to work properly, don't embed the SVG using img tag. Better use embed or iframe:
When using the img tag, the SVG itself will display correctly. But hover effects and transitions will be ignored. In addition to the transition property, we can also use transform . In this case, the elements will be scaled or rotated.
When using CSS3, be sure to add vendor prefixes to ensure support for as many as possible modern browsers. While Chrome and Firefox handle rendering flawlessly, Internet Explorer refuses to show your creation, although it is perfectly capable of showing these CSS3 properties if you apply them to HTML.
Media queries and SVG
If you want to customize your SVG to adapt to specific resolutions, just use media queries right inside it:
In this example, elements that have the example class specified will not be shown as soon as the visible screen width becomes less than 800 pixels. Be careful, this is not about the width of the document, but about the width of the SVG carrier element.
SVG is the new standard for vector images in the browser. Vector editors such as Adobe Illustrator allow you to directly save the file to 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, which you are using 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 ask appearance multiple elements in 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 display the SVG 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 most 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.
Today, there is more than one way to create SVG animation. This can be done using a tag that is inserted directly into the SVG code. There are special libraries such as Snap.svg or SVG.js.
We'll take a slightly different approach: using inline SVG (SVG code directly in the HTML) and animating individual parts directly through CSS.
I recently experimented with this method, in a project for my alma mater Wufoo, as a bit of a refresher on the topic we'll be covering here.
I haven't used SVG much in my recent projects, so I think this article is a great opportunity to give it more attention.
The final animation look is very simple. Here's what it looks like:
View on CodePen
Let's look at how this is done.
1. Make a list of elements that we will use
It may seem that there is a lot of work here in the manner of how to draw an owl, but this article is about animation, so let's deal with graphics as quickly as possible.
My plan was to make a super simple Wufoo ad using their classic logo, colors and corporate identity. And then add a little creativity:
- Create the effect that the letters are running off the page. Wufoo is a fun word, let the letters be fun too;
- The day before, we designed a T-shirt with a dinosaur on the front and the words on the back: “ Fast. Smart. Grozny" These are traits that both dinosaurs and Wufoo share. Not to mention the fact that we played on the word “FORMidble” (formidable). So I wanted to make these words appear and disappear in the animation block;
- To connect these words with a dinosaur, we will have the T-Rex's head appear and then quickly disappear. This will display the word “Fast”, which will be another interesting link for the elements.
- I loaded all these elements into Illustrator:
Notice how the logo and slogan texts are outlined. This means that they are simply vector shapes, and effects can be easily applied to them, both in SVG and in
The text you see is “Fast. ” remains in Illustrator in text format.
When I save the file in Illustrator, the lettering will remain an element.
2. Save in SVG format
Illustrator supports saving as SVG:
You can open this SVG file in a code editor and see the SVG code in it:
3. Clean up the SVG and set classes for the shapes
You can run the code through SVGO to optimize it and remove unnecessary elements like DOCTYPE and the like.
But now it’s more important for us to ask different names classes for shapes, so we can select them in CSS and do different things!
4. Insert SVG
You can copy this SVG code and paste it directly into the HTML where you want the block to appear. But this is just a primitive template.
You can do something like this:
5. Animation!
Now all these shapes are captured in the DOM, and we can position them and style them just like any other HTML element. Let's do that.
Let's say we want to use a 10 second timeline:
First words fall out and disappear
The first thing we want to do is print the words " Fast. Smart. Grozny.» Each word will be displayed for one second.
This is how we create an animation in which each word takes 10% of the time:
@keyframes hideshow ( 0% ( opacity: 1; ) 10% ( opacity: 1; ) 15% ( opacity: 0; ) 100% ( opacity: 0; ) )
Then we specify the first word and the duration of the entire animation at 10 seconds (10% of which is 1 second):
Text-1 ( animation: hideshow 10s ease infinite; )
The next two words will be hidden first (opacity: 0; ), and then we will use the same animation, only with a time delay, so that the next words will appear a little later:
Text-2 ( opacity: 0; animation: hideshow 10s 1.5s ease infinite; ) .text-3 ( opacity: 0; animation: hideshow 10s 3s ease infinite; )
An additional 0.5 seconds is needed to set the interval between the output of each next word.
Jumping letters
Once we have set the animation for this element, we proceed to the effects for the letters in the word Wufoo, which should jump to the side like this:
The trick here is that we create an animation effect that only lasts 5 seconds, but we run it forward once and then backward.
So it will correspond to our 10 second chart, and will be located in the middle of the timeline. All we have to do is set the parameters for scrolling the animation effect in one direction, because when reverse scroll it will simply return to its original position.
The effects for each letter have a slight time delay, so they do not all move at the same time, but one after the other:
Wufoo-letter ( animation: kaboom 5s ease alternate infinite; &:nth-child(2) ( animation-delay: 0.1s; ) &:nth-child(3) ( animation-delay: 0.2s; ) &:nth- child(4) ( animation-delay: 0.3s; ) &:nth-child(5) ( animation-delay: 0.4s; ) ) @keyframes kaboom ( 90% ( transform: scale(1.0); ) 100% ( transform : scale(1.1); ) )
The SCSS code above is just a short version, it does not include prefixes (which you will need in practice).
I think animation-delay is a property that would be useful to take from original CSS. It would look neater when the letters move with a slight delay.
And finally, the dinosaur
After these inscriptions flash across the block, a dinosaur’s head emerges from below. Despite the fact that the dinosaur figure consists of large quantity elements, we can position them all together using a positioning tag (group), which contains all these elements.
Since it's more efficient to use transforms to position the animation, we'll do this using keyframes :
@keyframes popup ( 0% ( transform: translateY(150px); ) 34% ( transform: translateY(20px); ) 37% ( transform: translateY(150px); ) 100% ( transform: translateY(150px); ) )
We want this animation to be displayed in the "last" approximately 3 seconds. This cycle actually works for the entire 10 seconds, but you will see the actual visible effects during the last 3 seconds.
When translateY(150px) is applied in the effect, the dinosaur moves so far down outside the box that you can't see it.
But for 37% of the time of this animation (about 3 seconds) you see him slowly moving up and then quickly moving back down.
When we apply this animation we will make sure that:
- The dinosaur is hidden at first;
- The output of this animation fragment is delayed in time, so it begins immediately after the letters in the logo word have finished their dance (they have shifted to the side and returned to their place).
Trex ( transform: translateY(150px); animation: popup 10s 6.5s ease infinite; )
The dinosaur falls down just at the last second so that immediately afterwards the word “Fast” appears in the block again (the animation playback interval is set to infinite so that it runs in a circle over and over again). It adds some fun synergy.
6. Making the block a clickable/interactive ad
One of useful features SVG is the ability to scale objects to any size without losing quality.
To create an inline SVG box while maintaining the original quality of the images, we can use the ol' padded box technique.
.wufoo-ad-wrap ( height: 0; padding-top: 100%; position: relative; ) .wufoo-ad ( position: absolute; top: 0; left: 0; width: 100%; height: 100%; )The idea is that the “wrapper” will always take the shape of a square, based on its width. Then we ask absolute values SVG positions inside this perfect square, the dimensions of which are adjusted based on the width.
Since this is an ad (which, of course, needs to be clickable), then as the containing container, instead of
Detailed article on styling content in an SVG element
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
But before we begin, let's quickly look at the basic structure and grouping of elements in SVG, gradually moving on to
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:
Element
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
Element
At the element
Element
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
But what is the content?
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
An icon is displayed on the screen, the contents of which are defined internally
But the element
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
So the contents
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 (in Firefox on this moment this function is not available). 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
Using Chrome Developer Tools, you can inspect the contents of the use element inside the shadow DOM (“#shadow-root”, line highlighted gray). 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
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
We know that we can't set styles internally
But we also know that, as with the element
So, first let's try to change the fill color of the element inside
However, this raises a couple of questions:
- 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). - If you exported SVG from graphic editor or are otherwise unable to modify the SVG code, then you will end up working with SVG that already has presentational attributes applied to it (unless you explicitly override this when exporting to SVG format) and the values of those attributes will take precedence over 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:
- 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).
- By resetting values, you force yourself to style the entire set of properties.
- Presentation attributes, which are initially set, are an excellent 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
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 next example- an ice cream icon drawn with one 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
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 empty space inside 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
Now this technique works after we forced the content
Content design using the CSS all property
Some time ago, while working on an icon activated with
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 .
Fortunately, it will help us CSS property all. 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 be aware of the following: important point: 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 if you don't want all CSS properties to be styled, this won't work for you - it's last resort and it's only partially suitable when you have an unstyled element and full control above its properties in 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
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
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
If we set the fill color in the element
So instead of defining a fill color and cascading it in the usual way, we will use the currentColor variable so that the smaller blob in the foreground will be a different color and we will set this 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
Next, we need to remove the presentational fill attribute from the second droplet and let it inherit the element's fill color
If we were to use the inherit keyword to force presentation attributes to inherit values from
Now, using the fill and color properties in
Codrops-1 ( fill: #4BC0A5; color: #A4DFD1; ) .codrops-2 ( fill: #0099CC; color: #7FCBE5; ) .codrops-3 ( fill: #5F5EC0; color: #AEAFDD; )
Each element
So what happened is that the current color value leaked into the element's content styles
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.
Keyword currentColor 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?
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:
Since inline style tags rewrite 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
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 color scheme 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 design a logo different ways depending on the context and in other similar cases.
As mentioned, browsers that do not support CSS variables use specified presentation attributes as a fallback, while 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
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
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.
Working with reusable SVG content is one of the complex issues SVG, this has to do with the behavior and location of the code being cloned. There are a lot of related issues that arise here that could become the topic of separate articles.
Continuation of the previous article “Styling SVG with CSS - Part 1”, dedicated to the format vector graphics SVG.
Styling with CSS
There is a clear and distinct relationship between the HTML and CSS languages: HTML language created for content structuring On the page; task CSS language- external design of this content. SVG format blurs clear boundaries this relationship. For example, format version SVG1.1 does not need CSS for styling individual elements SVG objects - for this purpose there are so-called presentation attributes.
Presentation attributes are shorthand for CSS properties for SVG elements. You can think of these attributes as CSS properties for SVG with a special syntax. Style cascading applies to these properties, but in this article we'll do it in a more concise way.
The example shown below is code that uses presentation attributes to style the border
polygon in the form of a five-pointed star:In this example the attributes
1 | fill |
The SVG2 format has several presentation attributes, such as
1 | x |
1 | y |
1 | width |
1 | height |
1 | cx |
1 | cy |
Another way to style SVG elements is to use CSS properties for this purpose. Just like with HTML elements, CSS properties can be set using an inline style:
SVG Style Cascades
As stated earlier, presentation attributes are a special type of property and that they are simply shorthand for CSS properties that apply to SVG elements. Based on the above, it is logical to assume that the concept of presentational SVG attributes, just like CSS properties, is applicable cascade of styles.
Presentation attributes are positioned as “author style rules” and can be overridden by any other definitions: external style sheets, internal style sheets or inline styles.
The diagram below shows the order of styles in a style cascade. The lower the styles are in this table, the more styles above them they can be overwritten. In our case, presentation styles can be overridden by almost all other styles, except user agent styles:
For example, the code sample below is a circle written in SVG. Circle fill color as an attribute
using the rule , , and .Notes
Since presentation attributes have XML syntax, they case sensitive. For example, when setting the fill color of an SVG element, the attribute should be written as
V ,1 |