Search code examples
csssvgsvg-filterssvg-animate

SVG filters applied to HTML content act very strange in Safari


I'm trying to use SVG filters (orginal example by Tomislav Jezidžić) on text in order to simulate some sort of "water effect". The result is ok in Chrome and Firefox, but Safari behaves strangely.

I tried to break up the code and figure out which part of the code is wrong, but without success. Safari 12+ correctly supports SVG-filters: https://caniuse.com/#feat=svg-filters

Codepen

* {
  margin: 0;
  padding: 0;
}

.main {
  font-family: sans-serif;
  font-weight: 600;
  align-items: center;
  justify-content: center;
  display: flex;
  filter: blur(2px);
  flex-direction: column;
  width: 100%;
  filter: url('#water');
}


.main-text {
  letter-spacing: 0.04em;
  height: 50vh;
  font-size: 48px;
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <defs>   
    <filter id="water">
      <feTurbulence type="fractalNoise" baseFrequency="0.01" numOctaves="1" result="turbolence"/>
      <feColorMatrix in="turbolence" in2="SourceGraphic" type="hueRotate">
        <animate attributeType="XML" attributeName="values" values="0;110;150;210;360" dur="4s" repeatCount="indefinite"/>
      </feColorMatrix>
      <feDisplacementMap in="SourceGraphic" xChannelSelector="R" yChannelSelector="G" scale="30" />
    </filter>
  </defs>
</svg>


<main class="main">
  <div class="main-text">
    Help me,<br>
    please
  </div>
</main>

Chrome, Firefox: the text is animated correctly
Safari: the text is frozen and in some cases the noise effect generated with <feTurbulence> appears

Result with Safari 12.0.2


Solution

  • Safari has poor support for using SVG filters on non-SVG content. The only stuff that really works is what they had to implement to support the packaged CSS filters (blur(), invert() etc.)

    If you want to implement this using SVG text elements, this will work just fine.

    Nevertheless, you have malformed syntax in your filters. You should have a values attribute in your feColorMatrix - and feColorMatrix takes just one input and you have two.