CSS "filter" property does not work on Safari when using inline SVG in CSS like 'filter: url(data:image, ...)'
Asked Answered
P

1

2

[EDIT] I've reviewed my entire post to add precisions about the problem and for additional ressources. ...

I'm new to SVG usage for webdesign, but I intend to implement a cool CSS feature for a theme. For information, I work with SASS to compile my styles.

What I want to achieve is to obtain a configurable theme that can change of color simply by changing some vars in my SASS files.

To do so :

  • I use "uncolored" SVGs as background for some elements of my website.
  • Then I apply a SVG filter for those elements to "colorize" them.

At this point, I'm pretty happy, because it is working... on almost all browsers : Brave, Chrome, Firefox, Opera, Edge

But it doesn't work on Safari and I'm not sure Why :

  1. it seems that I cannot use the CSS filter with value url('data:image/svg+xml, <svg>...</svg>')

  2. However it seems that I can use the filter property with url value if I'm targeting an element already in the DOM.

I've found an interesting article that talk about the same problem : https://www.stefanjudis.com/today-i-learned/svgs-filters-can-be-inlined-in-css/#til%3A-svg-filters-can-be-inlined-in-css

I tested the included examples in Firefox 84 and and Chrome 87. It worked in Safari 14 but stopped for unknown reason.

The "included example" being inline SVG in the CSS

Do someone know if using inline CSS SVG is possible with Safari ?

Here is an example to illustrate the problem:

/* Basic style for parent */
.parent {
  border: 3px dotted violet;
  background: pink;
  width: 400px;
  height: 50px;
  margin-bottom: 30px;
  position: relative;
}

/* Basic style for children */
.children {
  text-align: center;
  color: #ffffff;
  line-height: 40px;
}

.children::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

/* Using a pseudo element inside childrens that carry the background image */
.v0 .children::after, .v1 .children::after{
  background-image: url('https://public.xspawn.fr/svg-bg-btn.svg');
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

/*Creating a new stack context to be able to display text*/
.parent{position: relative; z-index:0;}
.children::after{ z-index:-1;}

/* Applying a filter to each children 'after' pseudo element to colorize its content (the SVG background or the background color) */
.children.recolor::after{
  filter : url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg"><filter id="recolor" color-interpolation-filters="sRGB"><feColorMatrix type="matrix" values="0 0 0 0 .13725 0 0 0 0 .23137 0 0 0 0 .32157 0 0 0 1 0"/></filter></svg>#recolor');
  );
}

.children.recolor2::after{
  filter : url('#dom-filter');
}
[v0] Element without Without SVG filter
<div class="parent v0">
  <div class="children">No filter</div>
</div>

<strong style='color:orangered;'>[v1] KO : Filtered with "filter: url(data:image... )"</strong>
<div class="parent v1">
  <div class="children recolor">filter: url(data:image..., < svg > .. .< svg \> )</div>
</div>

<strong style='color:green;'>[v2] OK : Filtered with filter DOM SVG and "filter: url('#elementid')"</strong>
<div class="parent v1">
  <div class="children recolor2">filter: url('#dom-filter')</div>
</div>

<svg xmlns="http://www.w3.org/2000/svg"><filter id="dom-filter" color-interpolation-filters="sRGB"><feColorMatrix type="matrix" values="0 0 0 0 .13725 0 0 0 0 .23137 0 0 0 0 .32157 0 0 0 1 0"/></filter></svg>
Proto answered 21/5, 2021 at 10:8 Comment(2)
perhaps you should check whether this is a known webkit issue and report it if not.Nonet
You were right. Known webkit issue : bugs.webkit.org/show_bug.cgi?id=104169Proto
P
-2

Question: "Do someone know if using inline CSS SVG is possible with Safari ?" Answer: "Yes it is possible".

If you use filters on svg elements in css/scss file like this

filter: url(#filter_id);

Transfer the styles from the css/scss file into the svg file separately into styles, and everything will work, like this:

<svg>
...
<g filter="url(#filter)">
..
</g>

<filter id="filter" x="5.54736" y="0" width={width-11.3} height="80.0002" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood floodOpacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="10" result="effect1_foregroundBlur_326_868"/>
</filter>
</svg>
Phelia answered 18/7, 2022 at 11:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.