use multiple css filters at the same time?
I am using this.
/* Multiple filters */
backdrop-filter: url(filters.svg#filter) blur(4px) saturate(150%);
I'm trying to create utility classes in vanilla CSS and this would be helpful but it looks like it can not be done this way.
<img class="brightness-20 image-grayscale-100">
.brightness-20 {
filter:brightness(20%);
}
.image-grayscale-100 {
filter: grayscale(100%);
}
I'm not sure why they didn't just create a more specific property like:
filter-brightness: 20%; filter-grayscale: 100%
After some more work I came up with this solution:
/*Initalize Variables No Adjustments*/
:root {
--blur:0px;
--contrast:100%;
--brightness:100%;
--contrast:100%;
--dropshadow:0px 0px 0px black;
--grayscale:0%;
--hue-rotate:0deg;
--invert:0%;
--opacity:100%;
--saturate:100%;
--sepia:0%;
}
/*Apply Defult Variables To Image*/
.filter {
filter: blur(var(--blur)) contrast(var(--contrast)) brightness(var(--brightness)) contrast(var(--contrast)) drop-shadow(var(--dropshadow)) grayscale(var(--grayscale)) hue-rotate(var(--hue-rotate)) invert(var(--invert)) opacity(var(--opacity)) saturate(var(--saturate)) sepia(var(--sepia));
}
/*Override Defults*/
.brightness-20 {
--brightness:20%;
}
.image-grayscale-100 {
--grayscale: 100%;
}
Because it's one property named filter
, every time you want to add a style to it you override it.
CSS version 1
Fortunately you can add multiple styles in some properties like background-image and filter! To get this working you'll have to put all the filter styles in one space separated filter property.
.grayscale.blur {
filter: blur(5px) grayscale(1);
}
CSS version 2
An alternative, flexible, solution would be to create a "div soup" on purpose and set different filters in the html stack. e.g.
<div class='demo__blurwrap' style='filter: blur(5px);'>
<div class="demo__graywrap" style='filter: grayscale(1);'>
<img src="awesome_image.jpeg" alt="">
</div>
</div>
CSS version 3
edit: just realised I just wrote this version with transforms, but the same idea applies.
Yet another solution is CSS vars. I wouldn't say it's ideal but it's a nice experiment. The major downside is that you need to declare a lot of variables, have default long rules for transform
and nested transforms will definitely break.
// Added just for fun
setInterval(() => {
yes_this_works_and_one_of_many_reasons_ids_are_bad.classList.toggle('translate');
}, 1000);
setInterval(() => {
yes_this_works_and_one_of_many_reasons_ids_are_bad.classList.toggle('scale');
}, 1500);
:root {
--scale: 1;
--translate: 0px;
}
.box {
background: blue;
width: 20px;
height: 20px;
transform:
scale(var(--scale))
translate(var(--translate), var(--translate));
transition: transform .3s;
}
.box.translate {
--translate: 20px;
}
.box.scale {
--scale: 3;
}
<div
id='yes_this_works_and_one_of_many_reasons_ids_are_bad'
class='box scale translate'
></div>
Javascript
Lastly, if you were to use JavaScript to render the styles you can read the current applied filters using getComputedStyle and add more to the mix.
- Modern browser demo setting styles nicely
- Modern browser demo setting styles without respect and fix it with observers
And a relevant article - this is more for animations and not yet supported by many browsers: Additive animations
And another relevant article on css-tricks: Houdini