Dark Mode & Images .svg.png: Invisible on Black Background

Howdy y’all,

Ever since the appearance of Night Mode, certain images have not displayed for me, either on the desktop version or the iOS version of Anki. For the most part these are .svg images which default to saving as .png on macOS. Examples would be images like those on the Wikipedia page for 人, like this one:

image

When I view an image like this in Anki in Night Mode, the lines remain black, but the background also becomes black, and the Anki window is black: so it becomes invisible. (Actually, on Anki desktop on macOS the window background isn’t as black as the lines, so you can still faintly see something. But on iOS, I can’t see anything at all.)

I guess one workaround would be “don’t save .svg as .png, duh!” Other images I have don’t suffer from this problem. But that would still leave me with a lot of images in cards created pre-Night Mode that would have to be replaced.

I’m using Anki desktop version ⁨2.1.42 (8eebfe18)⁩ for macOS, and 2.0.72 (20072.3) on iOS. I’m using the built-in Night Mode, not an add-on.

Is there something in the Anki settings that I’m not seeing that could make these images visible? More generally, what is it about these particular .png images that causes this behavior?

Any suggestions would be greatly appreciated.

Peace out,
t

1 Like

The png images on that page have a transparent background color rather than white, and the background color of those images are set to white with CSS. Just like the page does, you can set a background color of the images by adding something like the following to the styling section.

.nightMode img {
    background-color: white;
}

4 Likes

Thanks, @hkr ! That’s very helpful.

It seems from how you’ve done it in your screen shot that this is something I’d implement in a particular note type. So if I have this occurring in cards from different note types, I’d have to adjust the CSS in those other note types as well. Is that about right?

Is there a more global way to handle it, should I find I have a lot of those types?

Also, is there a way to restrict it to just this type of image? (It seems like the way you’ve done it would apply to any image.)

Peace out,
t

1 Like

I think that’s right.

If you only consider Anki desktop and Ankimobile, you could probably use “reviewExtra” to set global CSS, but Ankiweb and AnkiDroid don’t seem to support "reviewExtra". I think it’s better to add the CSS to each note type.

It might be technically possible, but I think it would require complex javascript. The background-color property for <img> tag has no effect unless the images have a transparent background layer, so I don’t think it’s necessary to restrict the target images.

2 Likes

Fantastic. Thanks very much for the recommendations. Incredibly helpful.

Peace out,
t

Hey thanks man, had the same problem

.night_mode img { filter:invert(1); }

What would be even better would be if I could map the “foreground” pixels to yellow, but at least this makes the image visible in night_mode without blasting the eyeballs with a big white patch.

NOTE: .nightMode seems to be an alias for .night_mode. Either works for me, but my card styling uses the latter.

I’d always pick SVG if I have the choice, because as XML docs they can be modified much more precisely than raster images.


In OP’s example, instead of downloading the .svg.png via right-click “Save As”, you can use the download button here to get the original SVG:

Method 1

You can paste the SVG code directly into the HTML editor of a field:

Then changing the fill color is as simple as this:

/* override inline styles with !important */
svg path {
  fill: yellow !important;
}

Result:

image

Method 2

Or you paste them into the rich text editor like images, which might be a preferable workflow to some:

However, for this method, you’ll need to replace the standard img tags with objects in order to expose the SVG data. I wrote a script for that:

SVG access script
<script>
   /* SVG access script by Matthias Metelka | @kleinerpirat */

   var svgImages = [...document.getElementsByTagName("IMG")].filter(img =>
      /\.svg/.test(img.src)
   );

   // Replace img with object
   // to allow access to SVG contentDocument
   svgImages.forEach(img => {
      const svgObj = document.createElement("object");
      svgObj.type = "image/svg+xml";
      svgObj.data = img.src;
      img.after(svgObj);
      img.remove();
      svgObj.addEventListener(
         "load",
         () => {
            /* you can query svgDoc for paths, shapes etc. */
            const svgDoc = svgObj.contentDocument;

            /* copy user stylesheet into SVG */
            const style = document.createElement("style");
            style.textContent = document.querySelector("#qa > style").textContent;
            const svg = svgDoc.firstChild;
            svg.insertBefore(style, svg.firstChild);
         }
      );
   });
</script>
(slightly adjusted from Diagram (maybe HTML) integration possible? - #3 by kleinerpirat)

Then you can also give the symbol any color you want. You’ll need to explicitly set a background color, otherwise it is white.

/* Container */
object {
  border-radius: 50%;
}
/* set explicitly, otherwise it will be white */
svg {
  background: linear-gradient(145deg, #fe1541, #d51237);
}
svg path {
  fill: black !important;
  /* you can also adjust stroke, stroke-width etc. */
}

Result:

image


Interactive football playbook

As another example why SVG is superior to raster images, I split static SVGs from my Hudl football playbook to multiple interactive cards. That notetype is mostly HTML+CSS and doesn’t need any JS other than for toggling extra info.

Original SVG from Hudl:

image

Front/Back for receiver Y

Extra info on click:

4 Likes