Applying CSS Filters to an iframe

Slight change of topic with this post, as I'm covering a small personal victory. It's a fairly bespoke issue, but if you want to know how to embed .NET Fiddle code into a Gridsome markdown post, and/or you want to know how to apply CSS filters to an iframe to create a "dark mode" version, read on!

I've written a couple posts about C# on this site, and I intend to write many more. The problem I have however, is that it would be much nicer to be able to show the code working, rather than just write about it.

Front-end technologies (particularly everything JavaScript) already have these tools, such as CodePen, CodeSandbox, JSFiddle, and many (many) more.

For C# and .NET however, there seems to be very few. Of those, only one worked well for me - .NET Fiddle.

It's a great tool, and it was incredibly easy to embed the code into my site, simply by adding the iframe directly into the markdown page:

<iframe
    loading="lazy"
    width="100%" 
    height="475" 
    src="https://dotnetfiddle.net/Widget/6xeOaS"
    frameborder="0">
</iframe>

Let's take a look at the result:

If you hit run, the code executes. Perfect! Almost...

It's too bright!

There's one minor issue however - there's no dark mode!

It's not a deal breaker, but I much prefer to look at this site with dark mode turned on, simply to avoid eye strain.

And a large white box in the middle of an otherwise dark page can definitely strain the eyes.

Ideally, I would apply CSS to style the individual elements however I want, however that becomes difficult when embedding an iframe.

However, something I found interesting was that I could style the iframe using CSS filters. I'd previously only seen these used on an image, so it was a surprise when it worked!

To do so, let's first give the iframe a class to target:

<iframe 
    class="dotnetfiddle"    loading="lazy"
    width="100%" 
    height="475" 
    src="https://dotnetfiddle.net/Widget/6xeOaS"
    frameborder="0">
</iframe>

When the site going into dark mode, I add a data-theme attribute to the body, setting it to "dark" for dark mode.

Let's use filters when in dark mode, by targeting the data-theme attribute and the .dotnetfiddle class:

  body[data-theme="dark"] .dotnetfiddle {
      filter: invert(95%) hue-rotate(180deg);
  }

First, we're inverting the iframe by 95%. This inverts the light gray bits to dark gray, and white bits to a very dark gray.

Second, we use a hue-rotate. Inverting the iframe will invert all of the colours, but hue-rotate will only change the hue.

How does this affect the result? Well, the elements with no hue (i.e., everything that is grayscale) will not be affected.

By using a hue-rotate of 180 degrees, we get the following result:

If you're already on the light theme, please try it out by clicking "Turn off the lights" at the top of the page (or the little sun/moon in the top right on mobile view).

I admit, this is not the best solution. Using filters like this is a bit of a hack, at least for a few reasons:

  • If .NET Fiddle change their colour scheme, things might look odd (particularly if they opt out of a grayscale background).
  • If the browser doesn't support it, then nothing happens (please, update your browser).
  • The colours are not exact, and the text is less readable.

But, it works! And hopefully it's a good solution while I'm waiting for .NET Fiddle to create a dark theme. I may try to inject CSS to make it more adapted to my colour scheme later.