Distorted Button Effects with SVG Filters

A set of inspirational, highly experimental distortion effects for buttons using SVG filters.

Following our latest web experiment by Lucas Bebber where we created realistic heat and water distortion on images and text, we’d like to share some inspiration for these kind of effects on buttons. Applying SVG filters on HTML elements give us some great opportunity to get creative with click interactions, and that’s exactly what we are going to explore today.

The main idea is to apply distortion or blob filters to buttons and explore some creative possibilities.

If you remember the “Gooey effect” that Lucas also introduced last year, you might recall that this technique is using the CSS filter() function mixed with an SVG <filter>. This is now supported by modern browsers, which is really great because lots of other filter effects still aren’t, so let’s dig a bit more into it and see what we can do on buttons with this.

Attention: This is still a highly experimental technique which currently works best in Google Chrome and Firefox.

Let’s have a closer look at the technique used.

Setting up the Button

To begin, let’s create a simple button element:

<button class="button">Click me</button>

With some basic styling, our button looks like this:
bt

Then, we define the filter inside an SVG object which we will place in our HTML:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="svg-filters">
  <defs>
    <filter id="filter">
      <feTurbulence type="fractalNoise" baseFrequency="0 0.15" numOctaves="1" result="warp" />
      <feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="30" in="SourceGraphic" in2="warp" />
    </filter>
  </defs>
</svg>

Now we apply the filter we just created to the button in the following way:

.button {
  /* other styles */
  -webkit-filter: url("#filter");
  filter: url("/#filter");
}

The slash in the second declaration is important, if you want to have the filter properly applied in Firefox.

How the filter works

SVG filters offer an extensive list of primitives. Check out Lucas’ article to get a bit of background on them.

One of the primitives is particularly interesting for our example which is the <fedisplacementmap>.
The displacement map effect moves the pixels of the element you apply it to, based on the pixel values of an input of your choice.

<fedisplacementmap> can be applied on any DOM element based on different sources such as an image, a gradient or another SVG filter element. For the button we are building, we use the SVG’s <feTurbulence> element.

<feTurbulence> is a primitive that generates “noise” (based on the Perlin noise algorithm).

See what happens when we apply this alone to our button:

bt noise filter

The <baseFrequency> property is the important one here. It will define how the noise will be generated. It accepts two numbers as parameters that correspond to the effect on the x and y coordinates.

Play with the properties to understand how it works:

Now, let’s apply our <fedisplacementmap> filter and see what happen:

bt displacement map

The important property here is the scale: it defines the strength of the effect.

We also need to determine the sources of our filter: every filters accept two input sources with the properties in and in2. We define our first source as SourceGraphic (this is the HTML element we apply the filter to) and the second source as our first filter <feTurbulence> (we give it the name noise).

Now our displacement map knows that it must move the pixels of the SourceGraphic based on the noise generated with <feTurbulence>.

The xChannelSelector and yChannelSelector properties tells it which color (R, G or B) to use to define the pixel displacement on each axis.

Now we just have to animate these properties using JavaScript to have the achieve the effect (we use the Greensock animation library here):

You can adventure yourself and apply this to any HTML element. See the result on a textarea for example:

Some interesting possibilities here πŸ™‚

SVG filters let us apply advanced algorithm like displacement maps really easily on web elements. All the complicated work is handled by the SVG filter element itself, all we are doing here is applying and animating some parameters.

And that’s it! Most of the effects in the demo are using the principle described.

Check out more ideas in the demo. Keep in mind that SVG filters can be applied to any HTML element so there is tons of other possibilities. Your imagination is the limit, but keep in mind to use these kind of effects wisely as filters can be quite resource intensive; refrain from applying them to large areas.

Note that support for CSS filters varies across browsers and the effects can also look slightly different. Make sure to always include a fallback.

Browser Support:
  • ChromeSupported
  • FirefoxSupported
  • Internet ExplorerNot supported
  • SafariNot supported
  • OperaNot supported

We hope you enjoyed these effects and find them inspirational!

Tagged with:

Adrien Denat

Adrien is a frontend developer at NEVERBLAND in London. Check out his work on Codepen.

Stay up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 35

Comments are closed.
  1. Number 4 is just ADORABLE!!!
    I also love no 8 and 9, the water effect is really pretty cool.

    Thanks for the experiment πŸ™‚ I have the feeling that also site visitors love this sort of playfulness.

  2. Great article and lovely demos!

    GSAP recently added the ability to animate numbers in complex strings so you could literally animate

    “weight 100 and height 20” to
    “salmon loves 3 and 300”

    GSAP would intelligently animate 100 (first number in first string) to 3 (first number in second string) and 20 (second number in first string) to 300 (second number in second string).

    Yes that is a totally silly example but this is very good news for things like SVG filter values!
    Instead of tweening a proxy object and then building a string using onUpdate you can tween the filter attributes directly.

    For instance in your demo 6 you can now use:

    btTl.to(turb, 0.2, {attr:{baseFrequency: “0.00001 0.6”}});
    btTl.to(turb, 0.2, {attr:{baseFrequency: “0.00001 0.0001”}});

    Here is a CodePen demo: http://codepen.io/GreenSock/pen/MyxzYo?editors=1010

    Just be sure to use GSAP 1.14.0 or higher.

    Keep up the great work. Very impressive.

    Carl from GreenSock

  3. Again, Such a wonderful button concepts. You guys rock.

    Thank you.

  4. great tutorial thanks for sharing,
    just a weird thing happens with me, i’m trying to only use the section number eight, when i delete all the other sections, the effect doesn’t work !

    any help will be appreciated, thanks

    • I found the solution, it was my miss-understanding anyone having this problem i can discuss..
      Thanks again

    • Great tuto !
      I’m trying just the same but don’t understand why i cant remove others button without breaking the one i want to isolate.. maybe a reference to nth child or something like that .. im looking further but if you have a hint it would be appreciated πŸ™‚ Thanks !

  5. It works on opera as well for me. But there’s one issue. View demo works perfectly on mozilla but when download files the buttons there don’t show up at all in mozilla. Is there a way to fix it?

  6. Hello everyone! I needed a little help! I am not a front end developer professionally but I was trying to use these buttons for my personal blog at http://cachezine.tumblr.com/

    My first button has effect#7 applied on it and is working perfectly on it’s own. But the moment I add the second button and put a different effect on it the first one stops working. I’m guessing it’s a problem with the javascript because if I remove the javascript code for the second button the first one start working again.

    I could really use a little help here

    Thanks a lot

  7. Hello! I make pogfish.ru on CMS ‘Opencart 2.0’ and want to use this svg filter on button ‘addtocart’, and I run into a trouble. Svg filters don’t work in smarty tpl files. I spent a lot of time, but didn’t have any solutions. But when I put this code to another site to php file, this work done. Here my code:
    Thanks!

    .wave { -webkit-filter: url(“#filter”); filter: url(“../#filter”);}
    .svg-filters { position: absolute; visibility: hidden; width: 1px; height: 1px;}

    Some text for the example

    var bt = document.querySelectorAll(‘.wave’)[0];
    var turbVal = { val: 0.000001 };
    var turb = document.querySelectorAll(‘#filter feTurbulence’)[0];
    var btTl = new TimelineLite({ paused: true, onUpdate: function() {
    turb.setAttribute(‘baseFrequency’, ‘0 ‘ + turbVal.val);
    } });

    btTl.to(turbVal, 0.2, { val: 0.3 });
    btTl.to(turbVal, 0.2, { val: 0.000001 });

    bt.addEventListener(‘click’, function() {
    btTl.restart();
    });

  8. Hi, looks really cool, but some makes my i7 fan spinning on single button. Is it worth it? Doesnt look like effective class for buttons.

  9. This is amazing work! I’m trying to figure out how to make the button link out to another page. I wrapped a href around the button and it doesn’t seem to work. Any suggestions?

    Thanks!

    • Nesting a button within a link is not valid code and will not work. I suspect that all you want is for an element to 1) work like a link, 2) look like a button, and 3) accept the filters described above. The harder way would be to overwrite the behavior of the button with JS and force it to work like a link. The easier way is to use CSS to style a link to look like a button and simply use the same filters in the CSS, but applied to the link.

      David Walsh went into more detail on the subject of buttons, links (anchors), and inputs a couple of years ago. https://davidwalsh.name/html5-buttons

  10. Wow !! It’s really awesome , its working 100% for me, i am web designer , i love to learn more creative animations, thanks for sharing wonderful animated effect.

  11. I don’t know why I can’t remove one without breaking the other one. Please help me…. Thanks in advance

  12. Hey Adrien!!

    Thanks very much for so nice buttons collection!! I loved them! =)

    Look… is there any shorter way to use the buttons more than 1 time? I’m creating a page where I will need to use the button more than one time. I got how to put it to work, and everything, but, I need to create a JS class for each button, and this is not so fast, to develop nor to load. Is there any “faster” way to achieve this?

    Cheers =)

  13. Are there any people test it on firefox ??.. It so terrible. i dont know why “http://tympanus.net” told “firefox was support” ??

  14. Looks like some of the effects don’t work anymore. Its a really cool effect and im wondering what would be causing the problem.

  15. Most of buttons doesn’t work anymore at latest Chrome. Any ideas why? And how to fix it.

  16. Wow! this article is great. Does it still work on google chrome?
    #WeMakeWebsites