book icon indicating copy to clipboard operation
book copied to clipboard

Images have a white background even with dark themes

Open steveklabnik opened this issue 9 years ago • 13 comments

/cc @Mark-Simulacrum

We might be able to just make the background transparent, but then the black text would be tough.

@azerupi is there even a way to switch images based on theme? That's another solution.

steveklabnik avatar Feb 15 '16 16:02 steveklabnik

is there even a way to switch images based on theme?

It is feasible, but the real questions are: "is it worth it?" and "is it desirable?"

It would require a JavaScript code to run when the theme changes, scanning for images with a specific name pattern and replacing them. I guess it would add a little latency and be a pain on first load, but I don't think it's hard / complex to implement.

This would also require the writer to maintain an image for every theme.

azerupi avatar Feb 16 '16 08:02 azerupi

I agree and share both concerns.

steveklabnik avatar Feb 16 '16 16:02 steveklabnik

Something to consider is using SVG instead, since we could then change the styles via CSS instead of swapping images on theme change.

However, it would require redoing the current images in SVG, so that is an initial pain point.

I'm also unsure as to what browsers we are aiming to support, this site says that SVG is supported pretty much everywhere post IE 9.

Mark-Simulacrum avatar Feb 16 '16 19:02 Mark-Simulacrum

Something to consider is using SVG instead, since we could then change the styles via CSS instead of swapping images on theme change.

That's interesting! But how complex would this become with images containing 3+ colors? Also, I guess this would require different CSS for every image?

azerupi avatar Feb 16 '16 19:02 azerupi

The complexity factor wouldn't be too significant, but it would probably require copying a good portion of the styles for each theme/variant.

If we decide to try SVG, I can attempt to create alternatives to the current diagrams, but I have little to no experience with using it.

If we can come up with a few common elements, then we'd only need separate CSS for images that are composed not of those elements. Another thing to consider is that we can probably just do two variants of each image (light and dark) and classify the themes as such, so we wouldn't need separate styles for each theme.

Mark-Simulacrum avatar Feb 16 '16 19:02 Mark-Simulacrum

I'm currently generating images with graphviz, which should be able to output SVG.

The sources are in a directory at the top-level if you want to try.

steveklabnik avatar Feb 16 '16 19:02 steveklabnik

Opened #77 with the SVG output.

Mark-Simulacrum avatar Feb 17 '16 00:02 Mark-Simulacrum

Ok so we have SVGs now, the next step is figuring out how to get them into the HTML in such a way as to style them with CSS and then actually style them.

From #77:

The current state is as such: In order to get the graphs looking good in both light and dark themes, I need to insert the SVG directly into the generated (HTML) file, whether by way of script or manually.

Ideally, we'd just include the generated SVG with some form of HTML or tag. However, this isn't possible because the color of the text inside of the included SVG cannot be changed based on the current theme: the then-included SVG is rendered within its own document tree (not sure if this is the proper terminology, but the result is similar to that of an iframe).

carols10cents avatar Sep 14 '16 12:09 carols10cents

Hey I stumbled upon this issue and would like to work on it a bit.

One problem with styling SVG images with CSS is the fact that styles don't persist across document boundaries. Therefore it is close to impossible to style these from outside. Currently I can think of three possibilities.

  1. Remove the background and just invert the image if a dark theme is selected. This would be easy for the graphviz images, but a bit more complicated if we would also want to style the screenshots from chapter 14 and 20. A more primitive solution would be to just invert the image without further modification but I would rather have a few pretty inverted image than all inverted badly.

  2. Create multiple different version for each image and include the matching one using CSS or JS. This would add the burden of maintaining multiple different versions of each image and probably increase load time.

  3. Embed the svg files as objects and dynamically style them. This is probably the most powerful but would require tweaks to the markdown parser etc.

Personally I would prefer the first approach as it is the easiest to maintain/implement and yields good results...

septatrix avatar Jan 16 '20 13:01 septatrix

I think the third approach, but with JavaScript, would be better until there is a new web standard to allow styling/tweaking SVG from <img> tags.

  • Performance impact only on users using the dark theme
  • Fallback to the original SVG
  • Single hack blob that can break without causing readability issues

serverwentdown avatar Aug 15 '21 08:08 serverwentdown

Experiments with the approach I suggested above: https://github.com/rust-lang/book/compare/d34ea0538f9eeb7457f480fa432ff91075e0b8cf...serverwentdown:experimental-svg-inliner

serverwentdown avatar Aug 15 '21 10:08 serverwentdown

I've been collaborating on a short introduction to Rust, also using mdBook, and we've reached the same issue, which I have addressed.

  • As stated here, formatting SVGs with CSS cannot cross document borders.
  • As with https://github.com/rust-lang/mdBook/issues/773 , #include-ing SVGs is a bit problematic if there are blank lines or comments. This can be addressed by removing both of these from the SVG source.
  • Once the SVGs can be included in the resulting HTML, it is just a matter of styling them.
  • mdBook themes happily enough provide a --bg and --fg CSS variables to match the background and foreground (text) colours
  • So by replacing black and white with --fg and --bg, the SVGs can adapt to the theme.

This method requires no JS, but inlining the SVGs will lengthen initial page loading fractionally. I'm going to create a PR to this effect shortly.

ericthelemur avatar Jul 24 '22 21:07 ericthelemur

I have found a very compact solution to enable SVG images to be rendered nicely with a dark theme that doesn't rely on #include or preprocessors: a small extra CSS file that sets img { color-scheme: light | dark; } appropriately, with one rule per theme, and a small modification to the SVG files that looks like this (the exact rules depend on the SVG file contents but can usually be discovered easily):

  <defs>
    <style>
      :root { color: #1e1e1e; }
      @media (prefers-color-scheme: dark) {
        :root { color: #d3d3d3; }
      }
    </style>
  </defs>

While decidedly not perfect, it's flexible and leaves the <img> tags in the source Markdown so that they can be rendered by GitHub. (And yes, the GitHub Markdown preview is legible too!)

You can see it in action in https://github.com/amaranth-lang/rfcs/commit/43f8f04e2a563381573c9e6cc9b12a67ac8f71fb.

whitequark avatar Mar 19 '24 16:03 whitequark