What is the best way to utilize a mask in an inline SVG that is compatible with Chrome browser?

I am looking to visually crop my element using an SVG shape that is defined within the same HTML file (inline SVG).

Using clip-path works perfectly:

div {
  width: 200px;
  height: 200px;
  background-color: red;
  clip-path: url("#c");
}
<div>
  <svg>
    <defs>
      <clippath id="c">
        <circle cx="100" cy="100" r="50" />
      </clippath>
    </defs>
  </svg>
</div>

However, when using a mask, Chrome does not apply any masking effect even though it works fine in Firefox:

div {
  width: 200px;
  height: 200px;
  background-color: red;
  mask: url("#m");
}
<div>
  <svg>
    <defs>
      <mask id="m">
        <circle cx="100" cy="100" r="50" fill="white" />
      </mask>
    </defs>
  </svg>
</div>

After researching (example), it appears that Chrome expects the mask to reference an entire image rather than a definition. Is there a way to refer to an entire image if it's been inlined? Or are there other methods I can try to apply a mask from an inline element?

Answer №1

Discover a creative JavaScript solution that may not be the most aesthetically pleasing but gets the job done:

  • Capture the content of your <mask>,
  • Replicate it in a new SVG element (Chrome thankfully doesn't require width and height),
  • Convert it to a data-URI and assign it to the -webkit-mask-image property.

const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const mask = document.querySelector("mask");
svg.innerHTML = mask.innerHTML;
const markup = new XMLSerializer().serializeToString(svg);
const url = `data:image/svg+xml;charset=utf8,${ encodeURIComponent(markup) }`;
const div = document.getElementById('mask-me');
div.style.webkitMaskImage = `url('${ url }')`;
#mask-me {
  width: 200px;
  height: 200px;
  background-color: red;
  /**
    This will be overidden by -webkit-mask-image even in Firefox.
    We could have avoided it with a CSS variable, e.g
    -webkit-mask-image: var(--workaround-url);
    but Safari acts in all ways as if they did support inline SVG as mask,
    when they don't.
    So, for them, we have to use the workaround everywhere...
  mask-image: url(#m);
  **/
}
<div id="mask-me">
  <svg>
    <defs>
      <mask id="m">
        <circle cx="100" cy="100" r="50" fill="white" />
      </mask>
    </defs>
  </svg>
</div>


For those requiring the mask-mode: luminance function, you'll need to implement it manually within the generated SVG image using a

<feColorMatrix type="luminanceToAlpha"/>
:

const svgNS = "http://www.w3.org/2000/svg";
const svg = document.createElementNS(svgNS, "svg");

const alpha = document.createElementNS(svgNS, "feColorMatrix");
alpha.setAttribute("type", "luminanceToAlpha");
const filter = document.createElementNS(svgNS, "filter");
filter.setAttribute("id", "alpha");
filter.append(alpha);
svg.append(filter);

const g = document.createElementNS(svgNS, "g");
g.setAttribute("filter", "url(#alpha)");

const bg = document.createElementNS(svgNS, "rect");
bg.setAttribute("width", "100%");
bg.setAttribute("height", "100%");
g.append(bg);

var mask = document.querySelector('mask').cloneNode(true);
g.append(...mask.children);
svg.append(g);

const markup = new XMLSerializer().serializeToString(svg);
const url = "data:image/svg+xml;charset=utf8," + encodeURIComponent(markup);
const div = document.getElementById("mask-me");
div.style.webkitMaskImage = `url('${ url }')`;
.border {
  display: inline-block;
  border: 1px solid;
}
#mask-me {
  width: 300px;
  height: 200px;
  background-color: red;
  /** Safari doesn't really support mask-image using inline SVG either...
    mask-image: url(#m);
    mask-mode: luminance;
  **/
}
<div id="mask-me">
  <svg width="0">
    <defs>
      <mask id="m">
        <circle cx="100" cy="100" r="50" fill="white" />
        <rect x="90" y="90" width="20" height="20" fill="black" />
      </mask>
    </defs>
  </svg>
</div>

Answer №2

Recently, I discovered that Chrome does not currently offer full support for the mask property according to my findings. However, it does seem to support the use of mask-image. You can refer to this resource for more details: Browser Support - CSS Masks.

It appears that this is still the current situation regarding Chrome and the mask property.

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

"Angluar4 is throwing an error: it's unable to read the property 'iname' of

This is the code snippet from item.ts file:- export interface item{ $key?:string; available?:boolean; countable?:boolean; iname?:string; price?:string; desc?:string; image?:string; } The items component item.componenet.ts looks like this:- import { Com ...

Is there a way to create a function that can show the pathway on the Browser Console?

I am looking to create a function that will show the path in the Browser Console when a link in the menu of a sub-category is clicked. The menu setup resembles this () on an e-commerce website. For instance: Perfume => ForMen => Cologne How can I r ...

Fetch real-time server information using the img src attribute

Currently, I am using ajax jQuery to dynamically populate an image src with a value that is retrieved from the server. However, I would like to streamline the code and eliminate the need for the jQuery portion. This is the current setup: Javascript (code ...

Creating a Visual Loading Effect in HTML

My website's layout scheme gets lost if the page isn't fully loaded. I'm interested in implementing an animation that is tied to the loading progress, similar to a progress bar but without the visual element of a bar itself. One idea is to ...

Steps for displaying an HTML table in Excel by clicking on a button

My goal is to open an HTML table in XLS format with a single click of a button. Currently, I have a JavaScript function that allows me to export the HTML table to XLS using the "save as" option. However, I want to enhance this functionality so that clickin ...

"Improve text visibility on your website with Google PageSpeed's 'Ensure text remains visible' feature, potentially saving you

Click here for the image reference showing the 0ms potential saving message I'm having trouble with a warning in Google PageSpeed and I've tried everything. This is the code I'm using to define the font-family: @font-face { font-family: ...

What's preventing the buttons from shifting positions?

Having some trouble with my Minesweeper Web Game setup. My buttons are stuck in place and won't budge. Can someone help me figure out what's wrong? Here's the code snippet I've been working on (FYI, using NetBeans 8.1 IDE) HTML: <! ...

How to Show a GIF in ASP.NET Core 3.0 When OnPost() is Invoked

I'm struggling to incorporate a GIF into my website, and after researching different sources, I've discovered that I need to utilize some Ajax and Javascript. However, I lack experience with both of these technologies. Is there anyone who could p ...

I am having issues with Tailwind CSS overriding the responsive padding on my website

I'm currently working on implementing responsive padding for a component. Given that Tailwind CSS follows a mobile-first approach, I have set the mobile padding to p-3, while screens at "md" and larger widths should use p-5. However, it seems like the ...

Full comprehension with a width of 100%

Here is an example where .flex2 has 2 children. 1st child - width: 300px 2nd child - width: 100% .b{ height: 50px; } .flex2{ margin-top: 20px; display: flex; .box{ background-color: blue; width: 300px; } .box1{ backgroun ...

Positioning the horizontal menu and footer links to the right side of the page

Struggling to get my menu and footer links aligned all the way to the right of the page. Here's what it currently looks like http://prntscr.com/32snbr, and this is the desired alignment http://prntscr.com/32snrm I've shared the HTML code below, ...

Modifying content on links that are dynamically created

I have some dynamically added link elements that are initially hidden from the page. These links are generated by a third party telerik control, and I need to change the text of these links using jQuery. I have created a rule (selector) that targets the ...

Is there a way to retrieve the chosen selection from a select dropdown element using JavaScript?

As someone who is still learning JavaScript, I've come across a particular issue. Within a webpage, there is a select dropdown as shown below: <select id="selTipoRap" class="form-control" th:field="*{tipoRappresentante}&qu ...

Using Webflow code in ReactJS/NextJS: Best practices and implementation tips

After exporting my Webflow code to my NextJS app, I noticed that many of the HTML tags are being flagged as errors because they appear to be missing closing tags. Can anyone shed some light on why this is happening and suggest potential solutions? It&apos ...

Web pages that dynamically update without the need for reloading

Recently, I stumbled upon slack.com and was immediately captivated by its user interface. For those unfamiliar with it, navigating the site is quite simple: There's a sidebar on the left and a main content area on the right. When you click on an item ...

Combining cells through the utilization of JavaScript

I've searched for ways to merge cells in a table using JavaScript but haven't been able to find any code that works. Is there a specific approach I can follow to implement cell merging like in MS-WORD tables? Your advice would be greatly apprec ...

"Implementation of Google+ button causing the appearance of a horizontal scrollbar

Adding Facebook and Twitter sharing buttons was easy, but now I'm having trouble with Google+. No matter where I place the code on my page (using a Bootstrap grid), it always adds 2-3 pixels on the right side, creating a horizontal scrollbar: <div ...

Combine multiple jQuery click functions into a single function

One issue I am facing on my website is that there are multiple modules, each of which can be disabled by the user. The problem lies in the fact that I have a separate script for each module. Hence, my query: How can I combine these scripts into one (perhap ...

Display corresponding div elements upon clicking an HTML select option

Is there a way to make a div visible when a corresponding select option is clicked, while hiding others? My JavaScript skills are lacking in this area. CSS #aaa, #bbb, #ccc { display:none; } The HTML (I'm using the same id name for option and d ...

Can someone help me troubleshoot the issue I'm having with this jQuery API function?

Greetings everyone, I'm facing an issue with my jQuery code. I am attempting to use the CoinMarketCap API from cryptokickoff to showcase cryptocurrency statistics on my website. I understand how to display them, but the appending process to my column ...