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

[filters] Proposal: color-filter #2875

Comments

Copy link
Contributor

color-filter is a new inherited property that modifies color values used when rendering. It's syntax is similar to the filter property, and defines a transform function that is applied to a color.

Example:

.foo {
  color: blue;
  color-filter: invert();
}

This would apply a channel invert to all the colors in properties matching .foo. In this case the text color would render as an orangey-yellow.

The set of filters available are the same as the current filter property, with the exclusion of those that move pixels (i.e. drop-shadow and blur).

Notes:

  • Efficient because it only applies to color values at rendering time.
  • Very convenient way to do a "dark mode" version of your site.
  • Applies to color values, including those in gradients.
  • Leaves images and emoji untouched.
  • No nasty side effects of filter
    • No new stacking context
    • Because it is inherited, descendants can change the value
@AmeliaBR
Copy link
Contributor

AmeliaBR commented Jul 3, 2018

all the colors in properties

This seems like a dangerously vague generalization.

Also, is there any use-case other than invert where you'd want to apply the same filter to all CSS painting, but not to embedded media?

@tabatkins
Copy link
Member

This seems like a dangerously vague generalization.

Eh, I suspect it's okay to just literally state that every single <color> in properties on the element gets the filter applied.

Also, is there any use-case other than invert where you'd want to apply the same filter to all CSS painting, but not to embedded media?

Yeah, this is my question too. A few other filters could make sense here, like sepia(), but I'm not sure you'd want to sepia the <color>s but not the images and emoji on the element.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Jul 3, 2018

One option might be to make sure that the color filters are available as modifiers within the color modification functions, whenever they are spec'd again.

An author could then integrate that with variables, for something like:

main {
  color: filter-color(var(--text-color), var(--global-color-filter));
  background: filter-color(var(--bg-color), var(--global-color-filter));
}

:root.dark {
  --global-color-filter: invert(100%);
}

Much more verbose, but also much more flexible, so the effect can be targetted exactly as the author intends.

@tabatkins
Copy link
Member

While I agree that filtering colors is probably something we want to do when we re-introduce the color modifier function, I think Dean's suggestion of something that can invert all the colors on an element is probably worthwhile to have on its own.

@w3c w3c deleted a comment from css-meeting-bot Jul 4, 2018
@css-meeting-bot
Copy link
Member

The Working Group just discussed color-filter.

The full IRC log of that discussion <fantasai> Topic: color-filter
<fantasai> github: https://github.com//issues/2875
<shane> Restaurant tonight is Long Chim
<fantasai> dino: Some background...
<fantasai> ScribeNick: fantasai
<shane> address for Long Chim: Corner of Pitt Street &, Angel Pl, Sydney NSW 2000
<fantasai> dino: Same way that Windows has done for decades, Apple's latest OS has a “dark theme”
<fantasai> dino: Where user has a checkbox where they can choose between light or dark mode
<fantasai> dino: You can see my browser is in dark mode atm
<fantasai> dino: System apps have implemented this
<fantasai> dino: Seems pretty popular
<fantasai> dino: This is about how you can apply something like that to the Web
<fantasai> dino: Particularly relevant to us for mail messages
<fantasai> dino: which are web pages
<fantasai> dino: What we wnated to do was automatically ocnvert a page to dark mode
<fantasai> dino: To do that, you want white to go to black, but you want hues to stay the same
<fantasai> dino: e.g. blue shouldn't become orange
<fantasai> dino: We had the idea to use color-filter
<fantasai> dino: This takes filters just like 'filter'
<fantasai> dino: But doesn't have ability to omove pixels
<fantasai> dino: It's a paint-time effect
<fantasai> chris: Is this a straight 255 minus effect?
<fantasai> dino: Yes
<fantasai> dino shows off invert()
<fantasai> dino: It's not like a regular filter. No stacking context. Just applies to colors
<fantasai> dino: colors of gradients, anywhere a <color> appears
<fantasai> dino: DOesn't affect images
<fantasai> dino: Because when you switch to dark theme, you don't want to have images invert
<fantasai> dino: or emoji colors to invert
<fantasai> etc.
<fantasai> dino: We don't actually wantto just invert the colors
<fantasai> dino: Here's an example - invert(0.83) hue-rotate(180deg) saturate(3)
<fantasai> dino: white goes to dark gray, bump saturation to compensate for grayishness, and then hue-rotate gets our colors back to what they would be without inversion
<fantasai> dino: Works nicely. Better on my laptop than on the projector here.
<fantasai> dino: This other column does some additional tweaks using JS, to look a little better.
<fantasai> dino: Anyway, this is what we're using to display mail messages now
<fantasai> dino: We have heuristics, if a marketing mail sets bgcolor, we won't do it
<fantasai> dino: but for plaintext or simple HTML messages, we'll apply the filter
<fantasai> dino: What we've got here is not Web-exposed, just in Mail
<fantasai> dino: We can talk more later about Media Queries and how to interact with the Web
<fantasai> dino: But a Web page could e.g. change colors manually in response to a media query, or they could use color-filter
<fantasai> dino: It's just maths on red/green/blue channels of the colors
<fantasai> dino: images are untouched
<fantasai> dino: No stacking context
<fantasai> dino: It's inherited, so you can undo it in a subtree
<fantasai> chris: Initial value?
<fantasai> dino: none
<fantasai> chris: You say not images, but some parts of CSS are <image>s...
<fantasai> dino: Gradients is a good example. If your bgimage is a gradient, you apply it to the coors in the image
<fantasai> leaverou: What about color variables?
<fantasai> fantasai: Gets applied when you apply the color
<fantasai> TabAtkins: But you don't want to double-apply for typed variables
<fantasai> ...
<leaverou> s/What about color variables?/What about custom properties that have been defined to accept <color>?/
<fantasai> xidorn: Is it applied during cascading or what?
<fantasai> emilio: Computed value is not affected
<fantasai> fantasai: used-value time operation
<fantasai> astearns: currentColor
<fantasai> fantasai: probalby fine
<fantasai> heycam: <canvas> ?
<fantasai> dino: Woudln't apply to canvas
<fantasai> dino: Currently implemented not for Web, in apps ike Mail etc.
<fantasai> dino: We think it makes sense for the Web
<fantasai> dino: as a way to help authors adjust page
<fantasai> leaverou: What about color modification functions?
<fantasai> TabAtkins: Amelia asked that already in the issue. I think having both is useful
<fantasai> leaverou: Are there uses other than dark themes?
<fantasai> dino, chris: high-contrast
<fantasai> dino: One of the greatest benefits we've found, before this people with vision issue sthat didn't like bright content would be constantly swapping between inverted/non-inverted mode
<fantasai> dino: And that's a screen-time effect
<fantasai> dino: And then we had to uninvert the images to make that useful for them
<fantasai> dino: And then also create all these stackign contexts, which aaffects the page
<fantasai> dino: So this is pretty nice.
<fantasai> dino: So this might be a nice forced option
<fantasai> dino: That the user could apply, e.g. "I want to see this web site dark"
<fantasai> leaverou: Does it also apply to colors in inline SVG?
<fantasai> dino: Yes
<dbaron> This seems like a reasonable feature, although I'm skeptical about the readability of the mail in the use case Dean described given the massive differences in perceived luminance between the R, G, and B channels. (e.g., blue on black is hard to read, as is green on white)
<fantasai> leaverou: Woudn't this be ...
<fantasai> leaverou: You can have bitmaps inside an SVG
<fantasai> leaverou: Seems like it would interact badly
<fantasai> dino: Could have a UA rule that sets it back to none
<fantasai> dino: We've mostly experimented with Mail. Haven't tried to apply to the Web yet
<fantasai> heycam: What if page wants to try handling it themselves?
<fantasai> dino: This is a complicated topic, wanted to deal later, but let's talk about it now
<fantasai> dino: If the browser is being told to apply dark mode automatically, what should we do?
<fantasai> dino: If there's a media query that allows the page to detect if the user wants dark mod
<fantasai> dino: Should the browser automatically flip th epage or not?
<fantasai> dino: It would be very odd for MQ to trigger behavior change
<fantasai> fantasai: We do have precedence
<fantasai> frremy: On Windows 8, if you resize an application to be in phone mode, we would scale the website down, except if it used @Viewport
<fantasai> florian: That's not a media query. @Viewport is *supposed* to have an effect on the page
<fantasai> florian: Opera did that for projection media type.
<tantek> similarly with full screen
<fantasai> dbaron: Been done before, but not a good idea. Poor API
<fantasai> dino: API I think that would provide it is also bad
<fantasai> dino: it's <meta viewport>
<fantasai> ...
<fantasai> florian: MS has an alternative to that, it's a property
<fantasai> florian: can say "for this subtree, I've done it"
<fantasai> emilio: Could say color-filter: noe
<fantasai> florian: *If* the browser is doing this with color-filter and not some other mechanism
<fantasai> dino: So you'd set that property on the body
<fantasai> fantasai: Can we use html , not body?
<fantasai> heycam: Is this about high-contrast?
<fantasai> Rossen: yes
<fantasai> dino: The only thing I dn't like about that is it forces you to resolve style before you decide whta you've got to do
<fantasai> dino: meta tag doesn't have that problem
<fantasai> dino: but then can't exclude part of the page
<fantasai> Rossen: In practice, ppl tend to opt out of things like menus and ...
<fantasai> dino: So that's actually main reason we don't want to do it automatically
<tantek> what about where web devs have matched color related values with colors in images?
<fantasai> dino: form-controls look weird
<fantasai> s/form/built-in form/
<fantasai> dino: but ppl don't use built-in form controls that much, they use boostrap etc.
<tantek> Tab: WAT
<fantasai> TabAtkins: Uhhh,, no???
<fantasai> TabAtkins: The whole point is that built-in form controls work properly on.e.g. apple watch
<fantasai> florian: We've discussed similar model for auto-adjustment of colors for printing
<fantasai> florian: Where authro might want the browser to not make changes to the colors, because they already turned on colors and stuff
<fantasai> florian: “Browser has magic adjustments. I want to opt out on this part of the page.”
<fantasai> dino: It worries me a bit that including any style sheet could override this
<fantasai> florian: meta tag seems the wrong layer to do it
<fantasai> fantasai: That's true of viewport meta in general. SHould be in style sheet
<fantasai> dino: Suppose you include your favorite UI library. It supports dark mode.
<fantasai> dino: Should it put "I support dark mode" property on the html?
<fantasai> frremy: No, you set the property on the elements in your framework. Not on the whole page
<fantasai> dino: So bounding to a tree
<fantasai> florian: It's just a property. You *can* use it on <html>, but could apply only to components.
<fantasai> tantek: Did you talk about use case of matching colors in a JPEG?
<fantasai> dino: Could just set the filter to none
<fantasai> florian: Could use property to express two different things
<fantasai> florian: “Dear Browser, don't do it, because I've done it myself.” vs “Dear Browser, don't do it, because here it's not appropriate”
<fantasai> dino: So property is nice there, can say "Don't use on this color of red, because it has to match the red of these shoes" but rest of page is fine
<fantasai> heycam: Are we considering possibility of meechanisms other than color-filter() being set to handle these cases?
<fantasai> heycam: Because if not, then maybe we don't need a separate filter
<fantasai> dino: So far color-filter has been enough for us, but we've only been looking at mail
<fantasai> dino: Haven't tried browsing the web to see what happens on random content
<fantasai> astearns: It's the exceptions I'm worried about
<fantasai> astearns: In mail, generally the bg is set on the canvas
<fantasai> astearns: but on web pages could be arbitrary div
<fantasai> dino: We found a lot of messages that don't set a bgcolor
<astearns> s/canvas/body/
<fantasai> dino: but content sets bg the white
<fantasai> dino: that's why we couldn't layer mail over a gray application background
<fantasai> dino: had to put some smarts into analyzing the page
<fantasai> dino: If we can detect that the page wants a white background, because it's set some things to white...
<fantasai> dino: But so far color-filter has been enough
<fantasai> dino: Good news is implementation is quite easy
<fantasai> dino: Just at the point of where you're asking for the color value
<fantasai> dino: It's great, makes it easy to be a render-time effect
<fantasai> dino: math is pretty easy
<fantasai> dino: can also cache the values
<fantasai> heycam: Some properties to control the color space that we interpolate in
<fantasai> heycam: for animations and gradients
<fantasai> heycam: That would happen with origianl color values before transofrming them?
<fantasai> dino: Don't think there's case wher eyou d'want to change colors *and* change interpolation space
<fantasai> dino: No idea why red-blue gradient, why if you invert it you'd want it to be in linear-rg
<fantasai> rgb
<fantasai> dino: If you ask for gradient colors, you get filtered colors, and then interpolate like gradient said to
<astearns> s/wher eyou d'want/where you'd want/
<fantasai> dino: Of course could put property with a media query if you wanted
<fantasai> chris: So this modification happens last, just before rendering
<fantasai> dino: Right.
<fantasai> dino: Computed style is still the original color
<fantasai> dino: While we're talkign about this, maybe talk about MQ
<fantasai> dino: Our current one that we use internally, is prefers-dark-interface
<fantasai> dino: Think it's more prefers-dark-content
<fantasai> TabAtkins: prefers-dark
<fantasai> dino: Lines up with prefers-*
<fantasai> dino: User is requesting that they prefer this type of content
<fantasai> florian: I'm supportive of prefers-type MQs,
<fantasai> florian: Question is what is the other options?
<fantasai> florian: Can you express no preference in addition to expressing preference for light?
<fantasai> ...
<fantasai> dino: prefers-dark: light seems weird
<TabAtkins> `color-pref: goth | prep;`
<fantasai> fantasai: Just rename it to something else, e.g. prefers-colors: light | dark | any
<fantasai> ...
<fantasai> heycam: Say you have a site which is already dark, like DaringFireball, and you turn on the browser option "Please automatically make this dark for me"?
<fantasai> heycam: Are there options to keep it dark?
<fantasai> dino: I think we need to be careful to say that "Please make this dark for me" can't be a universial hammer
<fantasai> dino: It's hard to tell
<fantasai> dino: E.g. we try with scrollbarls, to try to guess whether page is light or dark and make scrollbars match
<fantasai> dino: Because DaringFireball sets bgcolor which is neither white nor back
<fantasai> dino: we probably wouldn't change anything
<fantasai> heycam: Is that a case where the author should indicate they already support dark?
<fantasai> dino: Question is, does anyone want to force bright?
<fantasai> dino: If you set bgcolor to hot pink, might say that you support dark and they'll get hot pink anyway
<fantasai> dino: Also for mail you'd get hot pink
<fantasai> dino: ...
<fantasai> florian: Do ppl anticipate forced-darkening of pages?
<fantasai> dino: There are a lot of users who seem to want that
<fantasai> dino: They've set up shortcuts to invert the page
<fantasai> dino: They toggle this on and off as they browse different pages
<fantasai> florian: If you have prefers-dark and forced-dark on at the same time, what does that mean?
<fantasai> dino: ...
<fantasai> dino: If the page says 'I did dark mode' then we wouldn't force it
<fantasai> dbaron: Did some experiments with this sort of color inversion maybe 8-10 yrs ago
<fantasai> dbaron: One problem I ran into in the end, and dino's example with mail was showing it, is that you can't actually do a good job of preserving both satuaration and lightness contrast at the same time
<fantasai> dbaron: because the contributions of red green and blue channels to luminance is very very different
<fantasai> dbaron: In the difference of white vs black, the luminance perception of that is 70% green 23% red and 7% blue or something like that
<fantasai> dbaron: which means that fully saturated blue is quite readable against white, but unreadable against black
<fantasai> dbaron: and fullysaturated green is quite readable against black and unreadable against white
<fantasai> dino: Which is why my third column was there, it bumped dark blues to lighter blues... blends a light-ish blue over every color ...
<fantasai> astearns: I expect as your designer looks at more and more pages, they would find additional tweaks they'd want to make to the filter
<fantasai> astearns: I can see the usefulness for this feature for browser UI
<fantasai> astearns: as something you can toggle, and you can flip it back if it isn't working
<fantasai> astearns: from a design perspective
<fantasai> astearns: I can't imagine someone wanting to tweak their colors with such a blunt hammer
<chris> for sTGB it is 21.26% red 71.52% green 7.22% blue
<fantasai> astearns: Create a light them and a dark theme as a designer, never going to be a filter that'll get you from one to the other
<chris> s/sTGB/sRGB/
<fantasai> astearns: So from UA perspective I see the usefulness
<fantasai> astearns: But from author perspective I can't see the use case
<chris> zakim, this meeting spans midnight
<Zakim> I don't understand 'this meeting spans midnight', chris
<chris> rrsagent, this meeting spans midnight
<RRSAgent> ok, chris; I will not start a new log at midnight
<astearns> s/see the use case/see the use case for the color-filter property/
<fantasai> Rossen: Thank you for demos and explanations, and that's a wrap for this issue.

@Wes0617
Copy link
Contributor

Wes0617 commented Jul 4, 2018

(a bit off topic) maybe alongside a feature like this, css could introduce an alternative syntax to chain/nest "function" calls

background-color: saturation(hue(brightness(red, 1.2), 12deg) 0.3); /* current */

background-color: red -> brightness(1.2) -> hue(+12deg) -> saturation(+0.3); /* oop */
background-color: brightness(red, 1.2) |> hue(_, +12deg) |> saturation(_, +0.3); /* pipe */

@dirkschulze
Copy link
Contributor

@Netmosfera Please open a separate issue for the syntax discussion. Let's keep the current discussion specific to the color-filter proposal.

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

No branches or pull requests

7 participants