Issue with SVG mask not functioning when transform is applied

I am struggling to apply a mask to a transformed SVG element. When I try to do this with a path, the structure is the same. If I apply the mask to an element outside of the transformed group, it works as expected. However, if I try to do the same inside, the element simply disappears.

Here is the HTML:

<svg width="350pt" height="100pt" >
  <defs>
    <pattern id="circleFill" patternUnits="userSpaceOnUse" width="5" height="5" > 
      <circle cx="2" cy="2" r="2" fill="red"></circle>
    </pattern>
    <mask id="circleMask">
      <rect x="0" y="0" width="100%" height="100%" fill="url(#circleFill)" />
    </mask>
  </defs>

  <g transform="translate(0,150) scale(.1,-.1)">
    <rect class="holder" x="300" y="300" height="1000" width="1000"/>
    <rect class="main t" x="350" y="350" height="400" width="400" />
  </g>
  <rect x="300" y="50" height="50" width="50" class="main masked o" />
</svg>

CSS:

.holder {
    fill: darkgray;
    stroke: black;
    stroke-width: 2px;
}

.o{ fill: red; }
.t{ fill: purple; }
.masked{ mask: url(#circleMask); }

When I add the "masked" class to the second rect (with classes "main t"), it disappears.

The following structure does work:

<g class="masked">
  <g transform="...">
    <rect ... />
  </g>
</g>

However, I have over 50 elements in the image that should have the same transform, and only some of them should be masked (with 5 different masks).

Here is the fiddle link: Fiddle

What could I be doing wrong? Is it possible to mask an element inside a transformed group?

Answer №1

The challenge you are encountering when trying to apply a mask to a transformed SVG element lies in how SVG handles masking and transformations. According to the SVG specification, the mask-image property remains unaffected by the transform property.

As a result, when you apply a transformation to the group containing the masked element, the mask is no longer applied as expected. One way to address this issue is by utilizing the mask-position property, which enables you to define the position of the mask image in relation to the masked element. By setting the mask-position property to match the position of the transformed element, you can ensure proper application of the mask.

If you need to apply a mask to a transformed element with a viewBox (where an explicit viewBox is added), you can combine the mask-position property with the viewBox attribute. The viewBox attribute defines a user space rectangle that should be mapped to the bounds of the SVG viewport. While the viewBox attribute values are pre-transform coordinates, it is crucial to render and adhere to the post-transform coordinates.

In situations where you have over 50 elements in your image and wish to apply masks to specific ones, you can follow the same strategy. Just remember to adjust the mask-position property for each masked element to align with its transformed position.

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

Spin the div in the opposite direction after being clicked for the second time

After successfully using CSS and Javascript to rotate a div by 45 degrees upon clicking, I encountered an issue when trying to rotate it back to 0 degrees with a second click. Despite my searches for a solution, the div remains unresponsive. Any suggestion ...

The process of altering the color of a table row in JavaScript can be done after dismissing a pop-up that was triggered by a button within the same row

I am tasked with changing the color of a specific table row based on user interaction. The table consists of multiple rows, each containing a button or image. When the user clicks on one of these buttons or images, a popup appears. Upon successful data sub ...

What steps should I take to transform this into a :nth-child css selector that is dynamic?

Currently, I am designing a diamond grid system using CSS. I am facing an issue where I need to shift the 5th block to the left and then every 7th subsequent block after that (12th, 19th, 26th, etc). Is there a way to create a dynamic nth selector for th ...

Angular 2's innovative approach to implementing a sticky footer concept

Is there a way to make my footer sticky without being fixed? I attempted using the CSS negative margin trick, but it did not work as expected. In the provided Plunker code, I tried to replicate the issue in my Angular 2 app. The goal is for the footer to s ...

When you initiate a prevent default, both the Angular and Bootstrap UI tabs will become active simultaneously

I am facing a CSS issue while utilizing Angular UI-Tab. The problem arises when I have two tabs and need to stop tab switching based on a specific condition. To achieve this, I implemented prevent default. However, the CSS displays both tabs as active bec ...

Alignment in the vertical direction of two lines

I've been struggling to align some HTML elements visually the way I want. There are two lines of text followed by a link. I'm trying to get the link to be vertically centered between the two lines, rather than just after the second line. Using a ...

Autofill functions may not be compatible with input fields generated using JavaScript

Having trouble with browsers not using autocomplete in login overlays generated with JavaScript? It can be really annoying. Any suggestions on how to fix this issue? Should I create a hidden form within the original HTML and then move it into the overlay? ...

Utilizing reusable styled components with pseudo elements and advanced logic

How can I make the shared style more dynamic by changing the value of left or width based on a passed value or boolean logic across different components? I prefer not to pass it as a prop in the actual component like <bar left="20" />, but ...

Issues with ellipses not functioning properly have been identified specifically on Safari when using the line

Currently, I am using the line-clamp feature to restrict the titles on a blog to only two lines at most. This functionality works perfectly fine on Firefox and Chrome browsers; however, when it comes to Safari, the ellipsis appears in the middle of the sen ...

Hover over two different divs with JQuery

I have a situation where I have two HTML table rows. When I hover over the first row, I want to display the second row. However, once the mouse leaves both rows, the second row should be hidden. Is there a way to achieve this using JQuery? <tr class=" ...

The CSS dropdown navigation bar designed for mobile devices functions properly, however, it is not visible on iPhones

After building this website from scratch using only HTML and CSS, I encountered an issue with the dropdown menu not appearing on iPhones. Despite testing it extensively across different browsers and devices, the problem persists on Apple products. While i ...

Issue with Bootstrap 5 offcanvas when placed inside a fixed div

I am currently incorporating the bootstrap navbar with offcanvas functionality. All nested within a fixed positioned div. The styling of the div is outlined below: .whiteHeader { position: fixed; display: flex; align-items: center; height: ...

What is the best way to customize column width in AG-Grid?

I am looking for a way to dynamically set column width in my table. I have provided a stackblitz example which demonstrates that when changing the screen size, only the table border adjusts, but not the column widths. Is there a way to also change the col ...

Activate all chosen CSS circles

I'm currently working on creating a progress bar using CSS circles. The idea is that when you click on each circle in sequence (1, 2, 3), all three circles and the line connecting them will fill up with red color. If you then go back (3, 2, 1), the co ...

Reducing the slide margins in impress.js?

When using Impress.js, I noticed that the default slides have a large left margin (or padding - it's hard to determine with Firefox's Inspector). I have a slide with a wide <pre> block that would fit if it were aligned to the left, but it d ...

displaying and concealing elements with jquery

Is there a way to hide a div if the screen size exceeds 700px, and only show it when the screen size is less than 700px? Below is the jQuery code I'm attempting to use: jQuery(document).ready(function() { if ((screen.width>701)) { $(" ...

How to create a looping animation effect for a div using CSS on hover

Using Bootstrap framework with Wordpress site .test { position: absolute; z-index: 9; left: 50%; height: 10em; width: 10em; margin-left: -5em; background-size: cover; opacity: 0; transition: opacity 0.5s ease; transform: translateY(- ...

Learn the steps for accessing and utilizing aria-label text in Google Chrome

Struggling with the aria-label attribute for blind users in Chrome. Can't seem to hear the aria-label text. Any insights on how aria-label behaves in Chrome or if I'm using the wrong approach? If I'm heading in the wrong direction or using ...

Is it possible to utilize the ternary operator to handle classnames when working with CSS modules?

I am experiencing difficulty implementing a styling feature using the ternary operator within an element's className. My goal is to have three buttons that render a specific component when clicked. Additionally, I want to change the background color ...

Why is my Tailwind Grid displaying elements in a horizontal layout?

<div className='grid grid-cols-12 gap-12 mb-8'> <div className='col-span-8'> <div className='box'></div> </div> <div className='col-span-4'> <d ...