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 CSS filter support #3923

Merged
merged 17 commits into from
Apr 4, 2021
Merged

Add CSS filter support #3923

merged 17 commits into from
Apr 4, 2021

Conversation

adamwathan
Copy link
Member

@adamwathan adamwathan commented Apr 3, 2021

This PR adds support for CSS filters (for both filter and backdrop-filter) using a composable syntax that is very similar to how transforms work, for example:

<div class="filter grayscale drop-shadow-lg">

The filter class "enables" filters, and the individual filters can be stacked on top.

The class names match the filter functions, like blur-{x}, brightness-{x}, contrast-{x}, drop-shadow-{x}, grayscale-{x}, hue-rotate-{x}, invert-{x}, saturate-{x}, and sepia-{x}.

The grayscale, invert, and sepia filter functions include a suffixless version by default that just sets them to 100%, so to make something fully grayscale for example you just need to write:

<div class="filter grayscale">

Each value can be defined as an array, which will add multiple of those filter functions. So for example if you want a drop-shadow that actually adds two drop shadows, that's totally possible just using an array syntax in your config:

    dropShadow: {
      lg: ['0 10px 15px rgba(0, 0, 0, 0.1)', '0 4px 6px rgba(0, 0, 0, 0.05)'],
    },

This will ultimately spit out what is effectively this after variables are resolved:

.drop-shadow-lg {
  filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.1)) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.05))
}

Backdrop filter utilities are the same as regular filter utilities but are prefixed with backdrop:

<div class="backdrop-filter backdrop-grayscale backdrop-blur-lg">

Differences between filter and backdrop-filter support

The only differences between regular filters and backdrop-filters are:

  1. We don't support opacity for regular filters, but we do for backdrop-filters. This is because the regular opacity utilities in Tailwind accomplish the same thing as the opacity function for regular filters.
  2. We don't support drop-shadow for backdrop-filters, because it behaves inconsistently across browsers and is generally useless.

Default values

The default values have been chosen to be as minimal as I felt was reasonable while still being useful. For example, grayscale only supports two values (100% and 0%), as does sepia, and invert. Users can add more if they need them or rely on arbitrary value support if using JIT mode.

The drop shadow values are based on our regular box shadows, but because drop shadows don't support spread and because the blur is calculated differently for drop-shadows than it is for regular box shadows, I approximated them by eye to look as similar as possible.

Only responsive variants are enabled by default for these utilities due to file size considerations in non-JIT builds. Users can of course enable extra variants if needed.

@jshimkoski
Copy link

These are a couple filter related items I’ve used a bunch:

Lighten and darken:

https://github.com/jshimkoski/simple-design-system/blob/master/simple-design-system/tailwindcss/plugins/tailwindcss-lightness.js

and

background glass (apple glass effect):

https://github.com/jshimkoski/simple-design-system/blob/master/simple-design-system/tailwindcss/plugins/tailwindcss-bg-glass.js

Not sure if they would amount to some sort of default for this but hopefully this new functionality will allow us to do this sort of thing without plugins.

@neupauer
Copy link
Contributor

neupauer commented Apr 4, 2021

Hi, I am glad this utility is coming to tailwind's core.

In TODO I see the planned support for backdrop-filter, so I want to add a little ( maybe useful :) ) advice here. When I was building a similar plugin for myself, I noticed that when drop-shadow function is not at the last position in the list, it will not render correctly in Safari. The whole backdrop-filter rule will be ignored.

backdrop-filter: ... drop-shadow saturate blur
backdrop-filter: ... saturate blur drop-shadow

POC Example (open in Safari):
https://play.tailwindcss.com/8gDdLOUZFk?file=css

Links:
neupauer/tailwindcss-plugin-filter@f0b192b
https://github.com/neupauer/tailwindcss-plugin-filter

@adamwathan
Copy link
Member Author

@neupauer Ah that's a good tip on the drop-shadow thing, weird bug. Hadn't seen your plugin before, looks really close to what I was planning here! I noticed you are reusing the same filter function classes for both filter and backdrop-filter — what was your motivation for this, just fewer classes? I worry if someone ever needed both filter and backdrop-filter at the same time on an element that they would collide, even though that sounds extremely rare to me.

Think it's worth it for the reduction in classes/less verbose class names like blur instead of backdrop-blur?

@neupauer
Copy link
Contributor

neupauer commented Apr 4, 2021

 @adamwathan Hi, my motivation was to introduce a clean and reusable API for both filters. I built it primarily for myself, and I did not need to use them both, so I came up with this solution.

I am not sure if someone will ever need to use both filters on the same element. Maybe you can ask on twitter if someone uses it that way.

I am sorry but I can't help you with this decision.

@neupauer
Copy link
Contributor

neupauer commented Apr 4, 2021

Just got an idea, maybe it will confuse someone, but what about CSS variable default value:

backdrop-filter: blur(var(--tw-backdrop-filter-blur, var(--tw-filter-blur));

If --tw-backdrop-filter-blur will not be present on element (e.g. .backdrop-blur-*) then --tw-filter-blur (.blur-*) will be used.

So this will cover edge cases if someone needs to use both filters and the API stays clean.

<div class="filter blur-1"></div>

<div class="backdrop blur-1"></div>

<!-- edge case  -->
<div class="filter backdrop blur-1 backdrop-blur-2"></div>

@adamwathan adamwathan changed the title [WIP] Add CSS filter support Add CSS filter support Apr 4, 2021
@adamwathan
Copy link
Member Author

@neupauer Thanks so much for the input! I definitely agree that's a cool idea 👍 I've decided to keep it really simple and non-clever though just to make sure I don't find myself in a situation I regret, so every backdrop-filter utility is just prefixed with backdrop. Boring but guaranteed to not bite us at least. Thanks again!

neupauer added a commit to neupauer/tailwindcss-plugin-filter that referenced this pull request Apr 10, 2021
adamwathan added a commit that referenced this pull request May 7, 2021
* Implement `filter` helper classes with all methods

* Rename filter plugins/utilities, drop filter opacity, add drop shadow

* Remove non-final default filter values

* Working on default filter values, add basic JIT support

* Working on blur values

* New blur values (these are ~okay)

* Match drop-shadow values to box-shadows by eye as best as possible

* Update tests

* Fix kitchen sink test

* Add filter variants configuration

* Move drop-shadow to end of filters list

Co-Authored-By: Peter Neupauer <[email protected]>

* Add invert variants configuration

* Add backdrop-filter utilities

* Update tests

* Transition filters by default

* Alphabetize new config keys

* Optimize filter plugins for JIT + add arbitrary value support

Except for drop-shadow, will add that once we can think it through a bit.

Co-authored-by: Nick Schmidt <[email protected]>
Co-authored-by: Peter Neupauer <[email protected]>
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

Successfully merging this pull request may close these issues.

3 participants