Scalable Vector Graphics (SVG) is a web standard that allows you to define two-dimensional vector graphics using an XML-based markup language. Using SVG images, especially for web development, has a ton of benefits. Luckily, Lightning Web Components (LWC) provide full built-in support for using them. In this post, we’ll cover different options when using SVGs in LWC.
Pixel vs. vector-based graphics
Pixel-based images (also known as raster or bitmap images) are created by defining a color for each individual pixel of the image. This gives an exact representation of a picture for its given size. But they’re difficult to scale or change. Some examples of pixel-based image formats are JPEG, GIF, PNG, TIF, BMP or PSD.
Vector-based graphics, in contrast, are made up by defining lines, curves, basic shapes, and text. These kind of images don’t lose quality when you scale them, can be easily created and modified, and they don’t require too much space on disk. Some vector-based image formats include AI, CDR or SVG.
Scalable Vector Graphics (SVG)
Here is the Salesforce logo in SVG format:
If you’re not familiar with XML, you may be wondering what the meaning of the
xmlns attribute is on the
svg tag. This is the way we tell the user agent which namespace, or XML specification, the
svg element and all its child element names (
path in this case) belong to. Concretely, the SVG namespace is called
Styling SVGs with CSS is a common thing. For example, we could change the CSS
fill attribute of our Salesforce logo background on hover state to reflect a different color:
Let’s explain what that CSS selector does. First,
:hover selects the
svg element when you mouse over it. In that case, we’ll select the first
path child element found thanks to
If you take a look at the Salesforce logo XML, you’ll see a
fill attribute on each of the
paths defined. This is a presentation attribute. Presentation attributes are equivalent to CSS properties applied through stylesheets or inline. However, CSS properties always override presentation attributes. This is exactly what is happening here. The CSS property provided in the stylesheets (
fill:yellow) is overriding the
fill attribute on hover.
Ways to use SVGs in Lightning Web Components
Let’s explore the different ways in which you can use an SVG in Lightning Web Components. To exemplify the different alternatives, we’ll create a component that is an invitation to our fictitious annual Salesforce Awards event. The component will include the Salesforce logo SVG.
You will be able to check the complete code examples in this github repo afterwards.
Use the SVG inside an HTML template
This approach is as simple as it sounds. You can directly copy the SVG XML code into the HTML template of your component, and it will render as the image that you expect. Something like:
Although this option will have great performance — as no extra-network request is needed — it has poor reusability.
Create a dedicated component for loading your SVGs
An interesting option is to create a dedicated component to serve different SVGs. Each SVG can be stored in an independent template, and the component can be configured to serve the correct template depending on an
For this, we’ve created a component called
logo and included two templates in it. One includes the SVG code for the Salesforce logo, and another one for the Google logo:
Now, we’ve implemented the logic to serve one template or the other based on an
@api property called
name. We’ll use the Salesforce logo as the default template.
Finally, we can reference the
logo component into our invitation, and configure it to return one of the templates:
This option needs to do an extra server trip to retrieve the component, but the component will serve all our SVGs, so it’s a good compromise between performance and reusability.
Store the SVG in a static resource
SVGs can be uploaded as static resources. Salesforce acts as a content distribution network (CDN) for static resources, handling automatic caching and distribution. Additionally, if you’re using SVGs to create an icon system, you can improve performance even more by combining the different icons into a single SVG sprite. This removes the need to do multiple round-trips to retrieve different icons.
Let’s take a look at two options to include an SVG static resource in your component.
Include the static resource SVG with
If you need to configure the CSS of the SVG, as we did above, pick this solution. To follow this approach, you must add an
id to the
svg tag in your SVG file. This step is important, as without the
id, the SVG won’t be loaded correctly:
Next, you’ll have to import the static resource in your component, in the same way as with other static resources. Note that you’ll have to concatenate the resource URL with the
id that you set in the
svg tag, as follows:
Having done that, you can reference the SVG passing the static resource computed URL (
svgURL) to the
href attribute of the
use element. The
use element clones the referenced node and its children into the place where it’s used, in this case the component markup. The
href element needs to include the node
id, this is the reason why we added an
id to the static resource.
If we take a look at the nodes that are generated by the
use element, we’ll see that the SVG nodes have been copied as part of the invitation component DOM, but they are enclosed in a shadow DOM:
Note: you need to activate “Show user agent shadow DOM” in Chrome Developer Tools settings to be able to see Shadow DOM contents.
Shadow DOM elements cannot be accessed using regular CSS selectors. If we try to style the image in the same way that we did at the beginning of the blog post, it won’t work. However, we can set the
fill attribute as
inherit in the SVG path and control it from the parent.
Note that we are not using the
path element in CSS anymore. We cannot use it, because of Shadow DOM. But luckily, there is something we can leverage to overcome this. By definition, the styles you apply to
use will be inherited by all its descendants. This works the same for other SVG tags that allow grouping, as
symbol. Therefore, we can style the
use element, and the inner
path elements will inherit that value.
Reference the static resource SVG with the
This approach won’t copy the SVG nodes, but instead include them as an
image. It’s a simpler approach, but it won’t allow you to modify the SVG CSS as we did above. In this case, you can upload it in a static resource as is. You don’t need to specify an
Next, you’ll have to import the static resource in your component, same as in the previous case, but this time no
id reference will be needed.
Finally, you’ll be able to reference the SVG passing the static resource computed URL (
svgURL) to the
src attribute of the
Take a look at the nodes that are generated by using the
image element. We can’t see the included SVG nodes anymore:
Use an SVG as a custom icon in Lightning App Builder or Community Builder
Another possible usage of SVGs in a Lightning Web Component is to use it to define an icon that will be visible in Lightning App Builder and Community Builder. This is done in the same way in Aura components and Lightning Web Components. For that, simply include an
.svg file in the component folder and include the SVG code. The name of the
.svg file must match the component name. Bear in mind, the component metadata file must be correctly configured so that the component is available for the different builders.
When you take a look at the component in the builders, it will look like the following:
Restrictions and compatibility
There are some things that you should keep in mind when working with SVGs in LWC:
- Not all the existing SVG tags are supported by LWC. You can check the list of supported tags here.
As you’ve seen, SVG is a great image format to be used in web development, as SVGs can be scaled without loss of quality, and can be easily modified and animated with code. Lightning Web Components provides built-in support for them, and we’ve seen the different ways in which you can use an SVG in LWC. Remember to check this github repo to see the code for all examples shown.