Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an invert filter that preserves colors #133

Open
adil192 opened this issue Dec 29, 2023 · 1 comment
Open

Add an invert filter that preserves colors #133

adil192 opened this issue Dec 29, 2023 · 1 comment

Comments

@adil192
Copy link

adil192 commented Dec 29, 2023

Introduction

Describe the challenge or problem on the web you are proposing we address.

Images are often designed to be used in light mode (which use dark elements that would be hard to see against a dark background). A similar scenario is described in #50 but with SVGs specifically.

As an example, take this PWA icon which also provides an inverse variant:
The letters PWA in dark grey, purple, and dark grey respectively vs The letters PWA in white, purple, and white respectively

As another example, many learning resources are intended to be printed out onto white paper. This worksheet from Wikimedia Commons is an example of this:
A worksheet with instructions: Use the words in the table below to correctly label the picture of the flower that follows.

Sometimes the images I use have dark-mode variants available, but most of the time they don't (or I'm creating them myself).
There are also plenty of reasons not to use two separate variant images for light and dark mode:

  • More files = slightly harder to organize a project
  • If the user switches from light to dark mode, they have to redownload a whole new set of images.
  • <img> tags have to be replaced with e.g. <picture> tags to support automatically switching between variants, which can mess up assumptions made in stylesheets/scripts.
  • File name confusion: if you're looking at someone else's project, does image-light.png mean that the image should be used in light-mode, or that it contains light elements that should be used in dark mode?

The current filter: invert(1) does not preserve colors and so turns the originally purple logo green. We can combat this by using a hue-rotate (filter: invert(1) hue-rotate(166deg);) but we need to find this through trial and error for every image:
The letters PWA in dark grey, purple, and dark grey respectively vs Incorrectly inverted letters that are white and green vs Hue-rotated inverted image with white and purple letters

Use Cases (Recommended)

Clearly define one (or, ideally, more) ways in which this challenge or problem is blocking real-world applications. Please be as specific as you can.

My notes app Saber is written in Flutter not CSS, and needed to invert any media supplied by the user while preserving the original colours.

The way I found to do this was to write a small custom shader that converts each pixel to HSL format, inverts the lightness only, then converts it back to RGB and returns it.

This wouldn't currently be possible in CSS since we can't use custom shaders (and the old experimental -webkit-filter: custom(...) didn't allow sampling individual pixels for security reasons).

A new filter built into browsers (like filter: hsl-invert(1)) would make this possible.

This is how Saber deals with the examples in this issue. Notice how the inverted "PWA" logo keeps its vibrancy and looks like the actual inverted logo from the repo.
vs

Goals (Optional)

A list of what this proposal must do in order to be considered successful.

Add a new CSS filter that inverts each pixel while maintaining its hue. Potential names could be any of the following or something else:

filter: hsl-invert(1);

filter: hue-invert(1);
filter: invert-lightness(1);
filter: invert-shades(1);

/* Or even replace the existing invert filter */
filter: invert(1);

Non-goals (Optional)

A list of aspects of this challenge/problem or related challenges/problems that this proposal does not need to address.

The aforementioned #50 issue revolves around passing information to an svg that's inside an <img> tag.
This issue can be applied to any element, not just SVGs, by applying a filter over each pixel.

Proposed Solution

Without being too prescriptive, articulate a specific way (procedurally, algorithmically, declaratively) that a new or current web technology solves an existing problem or challenge.

The CSS filter property already uses a collection of browser-provided shaders. We just need another shader like the one used in Saber.

Examples (Recommended)

Share one or more examples of how your proposal would be used by developers.

<style>
@media (prefers-color-scheme: dark) {
    .invert-me {
        filter: hue-invert(1);
    }
}
</style>

<img src="pwa-logo.svg" class="invert-me">

<img src="worksheet.png" class="invert-me">

<div id="someComplicatedDom" class="invert-me">
</div>

Alternate Approaches (Optional)

Could this challenge be addressed another way? Including other options you considered can help others understand the limitations or adverse side effects of other approaches.

Privacy & Security Considerations

Perform a self-review. You may think of additional privacy/security considerations other than the ideas listed. If you find no considerations after careful review: "No considerable privacy or security concerns are expected, but we welcome community feedback."

No considerable privacy or security concerns are expected, but we welcome community feedback.

Let’s Discuss (Optional)

This is a great place to list out questions you'd like others to weigh in on or areas you need feedback on.

@Crissov
Copy link

Crissov commented Dec 29, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants