Transform CSS filters into SVG filters

Implementing CSS filters on the <img /> elements has been successful for me.

For example:

filter: brightness(1) contrast(67%) saturate(250%) grayscale(0%) invert(0%) hue-rotate(330deg) sepia(40%) blur(0px);

Now, I am trying to apply the same filter properties to the <image /> tag within an SVG file.

Unfortunately, methods like:

<g style="-webkit-filter: contrast(67%) saturate(250%);">
    <image xlink:href="image.jpg" />
</g>

or

<image xlink:href="image.jpg" style="-webkit-filter: contrast(67%) saturate(250%) sepia(40%)"/>

are not yielding the desired results.

It seems that combining CSS filters as SVG filters might be necessary.

I discovered a representation of specific CSS filter effects on webplatform.org, such as:

  • invert:

Afterwards, I attempted to merge generated filters with feMerge.

<filter id="clip_1-filter-90117969876336">
    <feComponentTransfer in="SourceGraphic" result="brightness-filter">
      <feFuncR type="linear" slope="22"></feFuncR>
      <feFuncG type="linear" slope="22"></feFuncG>
      <feFuncB type="linear" slope="22"></feFuncB>
    </feComponentTransfer>

    <feComponentTransfer in="brightness-filter" result="contrast-filter">
      <feFuncR type="linear" slope="-15" intercept="7"></feFuncR>
      <feFuncG type="linear" slope="-15" intercept="7"></feFuncG>
      <feFuncB type="linear" slope="-15" intercept="7"></feFuncB>
    </feComponentTransfer>

    <feColorMatrix in="contrast-filter" result="grayscale-filter" type="matrix" values="
       1 0 0 0 0
       0 1 0 0 0
       0 0 1 0 0
       0 0 0 1 0"></feColorMatrix>

    <feComponentTransfer in="SourceGraphic" result="invert-filter">
      <feFuncR type="table" tableValues="0 1"></feFuncR>
      <feFuncG type="table" tableValues="0 1"></feFuncG>
      <feFuncB type="table" tableValues="0 1"></feFuncB>
    </feComponentTransfer>

    <feMerge>
      <feMergeNode in="grayscale-filter"></feMergeNode>
    </feMerge>
    </filter>

However, the outcomes are not meeting my expectations.

What is the correct approach for translating CSS filters to SVG?

Answer №1

It appears that your filter is almost correct, but there may be a small error in the feComponentTransfer 'in' attribute. It seems like you intended to write:

<feComponentTransfer in="grayscale-filter" result="invert-filter">

Keep in mind that using 'result' and 'in' is not necessary if the output of each stage is the input for the next one.

Additionally, if there is only one node, the final feMerge is not required.

<svg width="5cm" height="5cm" viewBox="0 0 500 500">
  <defs>
  <filter id="clip_1-filter-90117969876336">
    <feComponentTransfer in="SourceGraphic">
      <feFuncR type="linear" slope="22"></feFuncR>
      <feFuncG type="linear" slope="22"></feFuncG>
      <feFuncB type="linear" slope="22"></feFuncB>
    </feComponentTransfer>

    <feComponentTransfer>
      <feFuncR type="linear" slope="-15" intercept="7"></feFuncR>
      <feFuncG type="linear" slope="-15" intercept="7"></feFuncG>
      <feFuncB type="linear" slope="-15" intercept="7"></feFuncB>
    </feComponentTransfer>

    <feColorMatrix type="matrix" values="
       1 0 0 0 0
       0 1 0 0 0
       0 0 1 0 0
       0 0 0 1 0"></feColorMatrix>

    <feComponentTransfer>
      <feFuncR type="table" tableValues="0 1"></feFuncR>
      <feFuncG type="table" tableValues="0 1"></feFuncG>
      <feFuncB type="table" tableValues="0 1"></feFuncB>
    </feComponentTransfer>
  </filter>
  </defs>

  <image xlink:href="http://lorempixel.com/500/500/"
         width="500" height="500" filter="url(#clip_1-filter-90117969876336)"/>
  <rect fill="none" stroke="blue"  
        x="1" y="1" width="498" height="498"/>
</svg>

Answer №2

Your current feColorMatrix appears to be an identity matrix rather than a greyscale filter, and the third feComponentTransfer seems to be incorrectly set as an identity transform (using (0 1) instead of (1 0).)

It's unclear what you intended to achieve with the last merge. Are you trying to combine the inversion results with the greyscale effect, or do you want to invert the greyscale itself?

For more information on feColorMatrix, refer to the web platform documentation and check out an introductory article on SVG filters I wrote for .NET magazine. Additionally, reading the specification linked by Robert in the comments may be helpful.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

External CSS stylesheets

I have encountered the following HTML code: <div class="entry"> <p></p> //text-indent here <blockquote> <p></p> //no text-indent here </blockquote> </div> I am trying to apply a ...

ACTUAL preventing a component from losing its focus

I have been exploring ways to effectively stop a DOM element from losing focus. While researching, I came across different solutions on StackOverflow such as: StackOverflow solution 1 StackOverflow solution 2 StackOverflow solution 3 However, these sol ...

Ensure that the height of the div element is equal to 100% of

I've been trying to figure out how to make my div take up all of the vertical height of the screen, but I haven't found a simple solution in the 100% div height discussions. Can anyone help? Here's my code: CSS #mother { width: 100%; ...

Is there a Page Views tracker in sinatra?

Help needed with implementing a page views counter using Sinatra and Ruby. I attempted using the @@ variables, but they keep resetting to zero every time the page is reloaded... Here's an example: Appreciate any advice! ...

Failure to Present Outcome on Screen

Seeking assistance! I attempted to create a mini loan eligibility web app using JavaScript, but encountered an issue where the displayed result did not match the expected outcome upon clicking the eligibility button. Here is the HTML and JavaScript Code I ...

Border only at the bottom of the outline

I need help creating a bottom outline border when the cursor hovers over an image. I prefer to use this inner border style to avoid any layout issues with a traditional border-bottom. Below is my current code, which includes outline margins: .img-lightbox ...

Dynamic column group in Datatable - toggle visibility based on user selection

In my application, I am utilizing Jquery datatable with a table that includes the following columns: Name, Office, A1, B1, Diff1, A2, B2, Diff2, A3, B3, Diff3, A4, B4, Diff4 Additionally, there is a select box containing the options: 1. All 2. Diff1 3. D ...

Is it possible to use a figure tag as a fancybox link?

I am curious, is it possible to turn a figure tag into a fancybox link with just a background image and no content? I understand that this may not be recommended, but I am wondering if it can actually be achieved? <figure class="appear"><a class= ...

Sliding a division using Jquery from the edges of the browser's window

<script> $(function(){ $('#right_image1').hide().delay('10000').fadeIn('5000').animate({right: '0'}, 5000); $('#left_image1').hide().delay('10000').fadeIn('5000').a ...

Tips for adding jQuery UI styling to elements generated dynamically

I have a challenge with generating text fields using jquery while applying jquery ui styling to the form. The issue is that the dynamically created elements do not inherit the css styles from jquery ui: let index = 0; $('#btn_generate').on(& ...

There is a slight gap between the svg element and the path

Here is the size of my path tag (g tag is same size) https://i.sstatic.net/Huk8j.png This is the size of my SVG tag https://i.sstatic.net/VBXQi.png There is a gap between them. These are the inline attributes... <svg preserveAspectRatio="none" cla ...

Having difficulty changing the visibility of a div with Javascript

I've developed a piece of vanilla JavaScript to toggle the visibility of certain divs based on the field value within them. However, I'm encountering an issue where trying to unhide these divs using getElementById is resulting in null values. D ...

Files are nowhere to be found when setting up an angular project

After creating an Angular project, I noticed that some key files were missing in the initial setup, such as app.modules.ts and app-routing.modules.ts The project was generated using the command ng new name Here is a screenshot displaying all the files th ...

Finding the data type based on the button clicked with javascript: A beginner's guide

I am trying to work with a PHP function that generates dynamically created divisions. Each of these divisions contains a different data type and a button. How can I extract the data type of a division when the user clicks on the submit button using JavaScr ...

Guide on adding HTML to a specific div element in jQuery by utilizing the keyword "(this)"

I have been working on a script for my PHP page in Wordpress to add titles to images in my photo gallery that open in a lightbox. Here's what I developed: $(".responsive1").bind("click", function() { $(this).("<div class='imgTitle ...

Create an HTML div element that spans the full width of the

I'm facing an issue on my HTML page where a div containing users from a chat system database is not displaying correctly. The ul li tag within the parent div is not taking up the full width as expected. Here's how it should look: http://prntscr.c ...

Is it possible to dynamically alter the href attribute of a hyperlink within a Twig template in Symfony 2?

Developing a menu for my website has been occupying my time lately, sparking numerous inquiries about its functionality. Essentially, I aim to create a menu with a select option containing all my projects. By clicking on either the modify or delete button, ...

Customizable dropdown menu design using HTML and CSS

Hello everyone, this is my very first post on Stack Overflow and I'm a bit unsure about the rules regarding posting. Please feel free to point out any mistakes I may have made. I've searched through the forums but haven't found a clear answe ...

Put your username onto the page

Is there a method to retrieve and display text inputs? For example: document.getElementById('input_id') <input type="text" placeholder="username" id="input_id"> and the result will be: document.showElementById('box_id') < ...

Incorrect rendering of the <li> tag

I've been working on creating a simple web "to do list" but I've encountered an issue. When I manually add todos and click on them, the 'text-decoration: line-through;' property is ignored, and I can't see the strikethrough effect ...