7

Using the brightness() CSS Filter to generically highlight Content

 3 years ago
source link: https://weblog.west-wind.com/posts/2020/Jul/28/Using-the-brightness-CSS-Filter-to-generically-highlight-Content
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

On this page:

INVBJ3e.gif

So it seems I have to pay better attention to CSS standards as I just realized that you can quite easily use CSS Filters to apply useful effects for generic control behaviors. Sure, I remember filter merely from the old, evil IE6 days to handle things like shadows and opacity, but it looks like the filter properties have migrated into the CSS mainstream with two now widely used and accepted filter operations that have quite a few useful filters available.

The two filter properties are:

There are a number of filter functions available:

  • blur()
  • brightness()
  • contrast()
  • drop-shadow()
  • grayscale()
  • hue-rotate()
  • invert()
  • opacity()
  • saturate()
  • sepia()

A few of these are very useful as generic tools - especially brightness() and grayscale() .

Filter and Brightness

I recently ran discovered the brightness() filter, which I didn't realize existed, but which is very, very useful for a number of generic operations.

It's so useful because it allows you to generically change the color value of an element, without having to specify a specific color value . Instead you can vary the brightness (or perhaps also the hue or saturation if you want to get more fancy) and basically affect he behavior of the element. That makes it quite useful for generic things like a 'button' control or other highlightable element.

brightness() Filter for Generic Highlighting

I can't tell you how many times over the years I've implemented a custom 'button' like CSS implementation. Over the years I've used images, backgrounds, gradients and opacity to effectively 'highlight' a control. All that works of course, but the problem with most of these approaches is that one way or the other you're hard coding a color value, image or gradient. Which means every type of button needs it's own highlight configuration and if you're doing any sort of theming the buttons need to be overridden for each theme to work typically.

The brightness() filter offers a potentially simpler alternative by simply boosting the color brightness of either or both foreground and background colors . Because brightness() works off the existing base color values, using a modifier style like :hover , you don't have to explicitly provide a new color, but rather just provide a generic brightness adjustment value.

What this means is that you can apply the button behavior to just about any content, regardless of what color it is which is great.

For example, this is what I use for turning FontAwesome icons into using button-like behavior:

<style>
  .toolbar { 
      padding: 5px;
      background: #f5f5f5;
  }
  .fa-button {
      padding: 0.5em 0.5em;
      background: #e0e0e0;  
      border-radius: 3px;                    
  }           
  .fa-button.dark {
      background: #555;                      
  }
  .fa-button:hover {
      cursor: pointer;
      border-radius: 3px;                    
      filter: brightness(120%);                    
  }            
  .fa-button.disabled {
      filter: grayscale(100%);
  }
</style>

<div style="padding: 5px; background: #eee;" class="mt-3">
  <a href="#"><i class="fas fa-plus-circle fa-button text-success"></i></a>
  <a href="#"><i class="fas fa-minus-circle fa-button text-warning"></i></a>
  <a href="#"><i class="fas fa-times-circle fa-button text-danger"></i></a>

  <a href="#"class="ml-1"><i class="fas fa-plus-circle fa-button  dark text-success"></i></a>
  <a href="#"><i class="fas fa-minus-circle fa-button dark text-warning"></i></a>
  <a href="#"><i class="fas fa-times-circle fa-button dark text-danger"></i></a> 
  
                  
  <a href="#" class="ml-1" title="this button is disabled (b&w filter)"><i class="fas fa-plus-circle fa-button text-danger disabled"></i></a>
<a href="#" title="this button is disabled (b&w filter)"><i class="fas fa-times-circle fa-button  text-danger disabled"></i></a>
<a href="#" title="this button is disabled (b&w filter)"><i class="fas fa-minus-circle fa-button text-danger disabled"></i></a>
</div>

Here's what that looks like:

INVBJ3e.gifsample on CodePen

No matter which color is applied to the icon - the highlighting just works !

If you've been paying attention to CSS standards this is probably not news to you, but I didn't know that this was something you could do. In fact I didn't realize that there are so many useful filters available including filters to blur, gray scale and a few other things that are useful for things like disabling buttons.

Background Filters

Another very useful thing and again new to me is the ability to apply a backdrop-filter . A backdrop filter lets you apply a filter to the content that the affected elements sits on top of in HTML compositional layout.

Effectively - with a little extra effort - you can apply many of these filters to the background only which was previously very difficult to do unless you used absolute positioning and z-index!

This makes it much easier to highlight content that sits on top of background images for example.

<style>
    .image-background-text {                    
        background: url(./images/Icon.png);
        background-repeat: no-repeat;                    
        border: 1px solid #eee;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 256px;
        width: 256px;
    }
    .text-overlay {
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);

        height: 256px;
        width: 256px;
        text-align: center;
          
        background: transparent;
        font-size: 70pt;
        font-weight: bold; 
        color: firebrick;
    }
</style>

<div class="image-background-text mt-4">
    <h3 class="text-overlay">Icon</h3>
</div>

which produces this:

NFvi2i.jpg!websample on CodePen

What makes this work is the backdrop-filter which lets you apply a filter to anything that sits behind the filtered element . This was notoriously difficult to do otherwise, because without the backdrop-filter applying a filter or opacity to a background element would also apply to any child content contained within a parent element.

Note that using backdrop-filter is different than setting filter on the background element , because filter also applies to all contained elements .

If you do this, which seems very similar:

.image-background-text {     
   ...
   filter: blur(10px);
}
.text-overlay {
    /*backdrop-filter: blur(2px);*/
    ...

You get this unsatisfying result:

3UNbM3Q.png!websample on CodePen

Using backdrop-filter on the top level elements instead of blur on the bottom element, makes that actually work as it applies the filter to any content behind the top element.

It's still not exactly easy to do these kind of layouts, because you still have to make sure that the content on top completely covers the bottom container in order to ensure a full fill. But it still considerably easier than having to explicitly mess around with relative and absolute positioning layout in the middle of your document.

Backdrop Filter Caveats

To be clear: The backdrop-filter does not apply to the affected element background properties like background , background-image , gradients and so on. Rather it's applied to any content that sits behind the current element. Only the area that is 'covered' by the element with the backdrop-filter gets the filter applied.

As useful as I think that backdrop-filter is, the bad news is that it takes a very recent browser to work. It requires Chromium 76 or later, and I couldn't get it to work in FireFox (even with the supposedly supported layout.css.backdrop-filter.enabled = true flag).

As of today, the compatibility for backdrop-filter (not for filter which works in all browsers) looks like:

RVjMf2j.png!web

It works in current Chromium browsers. FireFox even with the Compat flag isn't working, and it looks like iOS still requires -webkit-backdrop-filter (apparently not required in IOS 13). So this feature is just making it into evergreen browsers, but it looks like it will eventually be supported by all browsers.

Summary

Filters have been around for a while, but some of the functionality is new to me. Filters are surprisingly useful especially for generic styling of elements for dynamic hover behaviors which I've been using filter for a lot lately to reduce a bunch of redundant hard coded style rules.

backdrop-filter is still a little too bleeding edge in terms of browser support to be used, unless you know your browser targeting supports it or you can live with content not applying the filter. Nevertheless, backdrop-filter is useful for some cool effects that otherwise are a pain in the ass to achieve via layered content.

Resources


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK