6 min read

The problem

When you are working on a webpage and you are given company logos of sponsors, customers, or whatever, you use SVG logos, right? I have had marketing people give me undersized GIF or PNG logos. I always go look for SVG versions. I also sometimes find that they have given me an obsolete version of the logo.

Once you have your SVG logos, you put them on the page and test it:

Our sponsors

Red HatIBM Research

It looks great. Well, not quite, the logos should be sized differently (I have an idea on what we can do about that for a future post.) But otherwise, they look fine. Your site has a dark color scheme option, so you test that:

Our sponsors

Red HatIBM Research

Oh no! That does not work at all.

The solution

What can we do about that? There are several options:

  1. Have a light and dark version of each logo. Display one and hide the other. That would require you to put up two versions of each logo. More work and if marketing people are doing this in a CMS, they will never get it right. (I am not coming down on marketing people, I have worked with them for over 25 years. Their job is marketing, not web development. That’s my job.)

  2. Use one version of the logo and set the colors via CSS. That is doable but it can get complicated. You might have to add custom CSS for each logo. Or maybe require that the logos use common class names. Meh.

  3. Use currentColor in the logo. Yes, this does require some editing, but it is not that difficult. SVGs are text files, bring up the logo in your favorite text editor (you know, vi or emacs) and modify the colors.

I prefer the last option (and if you read the title of this post, you already knew that). But first, what is currentColor? According to MDN:

currentColor is a CSS keyword that acts as a variable representing the calculated value of an element’s color property.

How does that help us? When a site supports light and dark color schemes, the text color can switch between light and dark. That means that currentColor has the value of whatever the text color is. It is also great for setting border colors that follow the color scheme, such as:

.box {
  color: darkblue;
  border: 1px solid oklch(from currentColor l c h / 0.25);
}

The border will be a semi-transparent dark blue. If you change the text color, the border color follows automatically. Set it and forget it.

For logos, edit the SVG and find the primary color. Change it to currentColor. For the Red Hat logo, for example, we want the text to be currentColor but the hat and the hatband should stay the same. The IBM Research logo is simple, just one color.

Now let’s test it:

Our sponsors

Red HatIBM Research

Our sponsors

Red HatIBM Research

Wonderful! It works.

If you have an unusual text color (such as hot pink), you probably do not want to use that for the logo container’s color. Companies can get very persnickety about their intellectual property. Most allow you to use black or white for the logo when you are not using their brand color, but they do not like the unusual.

Remember: you do not have to use currentColor. If a particular logo works in both light and dark modes, don’t worry about. Look at the Hugo logo in the footer. It works with either color scheme.

The “gotcha”

If you have gotten this far and are testing out your logo with currentColor, you may find that it doesn’t work. What is going on?

Well, how did you insert the logo? Did you do the usual way of using an img element? For example:

<img src="redhat-logo.svg" alt="Red Hat">

There is your problem. The img element is replaced content. This means that its content is outside the scope of the document’s CSS. Nothing crosses that boundary.

You need to inline the SVG. If you can easily do that with your CMS or site builder, do it. If you don’t have an easy way to inline the SVG, all hope is not lost. You can use a script to do that for you at runtime. Here is one such script:

;(() => {
  function convertLinkedSvgsToInline() {
    const images = document.querySelectorAll('img[src$=".svg"]:not(.no-inline)')

    images.forEach((image) => {
      fetch(image.src)
        .then((response) => response.text())
        .then((svgData) => {
          const parser = new DOMParser()
          const svgElement = parser.parseFromString(svgData, 'image/svg+xml').querySelector('svg')

          if (svgElement) {
            // Copy attributes from the image to the SVG
            Array.from(image.attributes).forEach((attr) => {
              svgElement.setAttribute(attr.name, attr.value)
            })

            // Replace the image with the inline SVG
            image.replaceWith(svgElement)
          }
        })
        .catch((error) => console.error('Error fetching SVG:', error))
    })
  }

  convertLinkedSvgsToInline()
})()

This script looks for any img elements that link to SVGs. It then replaces the img element with the SVG. Sometimes you do not want or need to inline an SVG. In that case, use the class no-inline. The script will ignore those.

This script should probably be rewritten as a module instead of an IIFE, but not today. Tomorrow. Always tomorrow.

The second “gotcha”

This one is a possibility. Once you inline your SVGs, any CSS they contain becomes global to the page. Not every SVG uses CSS to set colors. But if they do, there is a possibility of cross contamination.

I have seen this happen. A logo uses a class, such as, st1 to set a color. Another logo that loads after it, uses the same class. Its color takes precedence since it appears later.

Why is this logo red? It should be blue.

Oops. A later logo overrode the blue. If that happens, edit one of the logos and change the class names. I usually just add a prefix to all of the class names. In our example, I would add “ibm-” to each class name in that logo.

On a page with thirty logos, this might happen to a couple of them.

Summary

The color currentColor is your friend when you need elements to change color based on the color scheme or theme color.

Just remember that SVGs must be inline for any of the document CSS to apply.

Bonus

When I went to Netlify to get their logo, I noticed that they do something different. Besides having the text switch between light and dark, they change the shade of the green “spark” (as they call it) based on the color scheme. They were doing the color switch with external CSS. I moved it into the SVG’s styles.

How did I do it? Using the CSS light-dark() function. I added this to the SVG:

<style>
  .netlify-spark { fill: light-dark(#05BDBA, #32E6E2) }
</style>

Thus, in light mode, the spark is #05BDBA while in dark mode it is #32E6E2.

If the logo is being used on a background that does not match the light/dark mode (such as in a dark nav bar in light mode), then light-dark() will select the wrong color. In this case, external CSS (as Netlify is doing) is the way to go.

A way around this issue is to make sure to set the nav bar’s style to color-scheme: dark so that light-dark() would make the correct choice.

If you examine the SVG, you will see that the spark elements have class="netlify-spark" while the text parts have fill="currentColor".

Netlify
Netlify

This post should provide enough food for thought to allow you to improve the responsiveness of your SVGs. Happy coding.

Tags

Related content