skip to Main Content

The SVG that is meant to mask the image lies under the image and isn’t masking it. Also, adding WebkitMask to the inline style makes the image disappear from live server page. I’m using CSS modules, hence the inline styling for the mask (referring to IDs from CSS modules is a nightmare I want to deal with later). What am I getting wrong here? I checked the other QnAs available but none of those solutions seem to be working. This is a react, SASS and CSS modules project and I need to see the different opacities implemented on the image along the <rect>s. The SVG in itself occupies space as intended within the viewport just that it isn’t masking the image.

Thanks for your time!

img {
    height: 60vw;
  }
<div>
        <img
          src="https://images.unsplash.com/photo-1506399558188-acca6f8cbf41?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2173&q=80"
          alt="Your Image"
          style={{
            mask: "url(#path-One)",
            WebkitMask: "url(#path-One)",
          }}
        />
        <svg viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
          <mask id="path-One">
            {/* Line 1: */}
            <rect width="20" height="20" fillOpacity="0" />
            <rect x="20" width="20" height="20" fillOpacity="1" />
            <rect x="40" width="20" height="20" fillOpacity="0" />
            <rect x="60" width="20" height="20" fillOpacity="1" />
            <rect x="80" width="20" height="20" fillOpacity="0" />
            <rect x="100" width="20" height="20" fillOpacity="1" />
            <rect x="120" width="20" height="20" fillOpacity="0" />
            <rect x="140" width="20" height="20" fillOpacity="1" />
            <rect x="160" width="20" height="20" fillOpacity="0" />
            <rect x="180" width="20" height="20" fillOpacity="1" />
            <rect x="200" width="20" height="20" fillOpacity="0" />
            {/* Line 2: */}
            <rect y="20" width="20" height="20" fillOpacity="1" />
            <rect y="20" x="20" width="20" height="20" fillOpacity="0" />
            <rect y="20" x="40" width="20" height="20" fillOpacity="1" />
            <rect y="20" x="60" width="20" height="20" fillOpacity="0" />
            <rect y="20" x="80" width="20" height="20" fillOpacity="1" />
            <rect y="20" x="100" width="20" height="20" fillOpacity="0" />
            <rect y="20" x="120" width="20" height="20" fillOpacity="1" />
            <rect y="20" x="140" width="20" height="20" fillOpacity="0" />
            <rect y="20" x="160" width="20" height="20" fillOpacity="1" />
            <rect y="20" x="180" width="20" height="20" fillOpacity="0" />
            <rect y="20" x="200" width="20" height="20" fillOpacity="1" />
            {/* Line 3: */}
            <rect y="40" width="20" height="20" fillOpacity="0" />
            <rect y="40" x="20" width="20" height="20" fillOpacity="1" />
            <rect y="40" x="40" width="20" height="20" fillOpacity="0" />
            <rect y="40" x="60" width="20" height="20" fillOpacity="1" />
            <rect y="40" x="80" width="20" height="20" fillOpacity="0" />
            <rect y="40" x="100" width="20" height="20" fillOpacity="1" />
            <rect y="40" x="120" width="20" height="20" fillOpacity="0" />
            <rect y="40" x="140" width="20" height="20" fillOpacity="1" />
            <rect y="40" x="160" width="20" height="20" fillOpacity="0" />
            <rect y="40" x="180" width="20" height="20" fillOpacity="1" />
            <rect y="40" x="200" width="20" height="20" fillOpacity="0" />
            {/* Line 4: */}
            <rect y="60" width="20" height="20" fillOpacity="1" />
            <rect y="60" x="20" width="20" height="20" fillOpacity="0" />
            <rect y="60" x="40" width="20" height="20" fillOpacity="1" />
            <rect y="60" x="60" width="20" height="20" fillOpacity="0" />
            <rect y="60" x="80" width="20" height="20" fillOpacity="1" />
            <rect y="60" x="100" width="20" height="20" fillOpacity="0" />
            <rect y="60" x="120" width="20" height="20" fillOpacity="1" />
            <rect y="60" x="140" width="20" height="20" fillOpacity="0" />
            <rect y="60" x="160" width="20" height="20" fillOpacity="1" />
            <rect y="60" x="180" width="20" height="20" fillOpacity="0" />
            <rect y="60" x="200" width="20" height="20" fillOpacity="1" />
            {/* Line 5: */}
            <rect y="80" width="20" height="20" fillOpacity="0" />
            <rect y="80" x="20" width="20" height="20" fillOpacity="1" />
            <rect y="80" x="40" width="20" height="20" fillOpacity="0" />
            <rect y="80" x="60" width="20" height="20" fillOpacity="1" />
            <rect y="80" x="80" width="20" height="20" fillOpacity="0" />
            <rect y="80" x="100" width="20" height="20" fillOpacity="1" />
            <rect y="80" x="120" width="20" height="20" fillOpacity="0" />
            <rect y="80" x="140" width="20" height="20" fillOpacity="1" />
            <rect y="80" x="160" width="20" height="20" fillOpacity="0" />
            <rect y="80" x="180" width="20" height="20" fillOpacity="1" />
            <rect y="80" x="200" width="20" height="20" fillOpacity="0" />
          </mask>
        </svg>
      </div>

2

Answers


  1. you need to apply the mask attribute directly to the element instead of using the tag. The tag cannot be masked directly. Here’s the corrected code:

    <div>
      <svg viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
        <mask id="path-One">
          {/* Your rect elements here */}
        </mask>
        <image
          href="https://images.unsplash.com/photo-1506399558188-acca6f8cbf41?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2173&q=80"
          mask="url(#path-One)"
          height="60vw"
        />
      </svg>
    </div>
    

    Also, ensure that the SVG mask is correctly positioned on top of the image using CSS or SVG attributes.

    Here’s the full updated code

    /* CSS */
    .img-container {
      position: relative;
    }
    
    img {
      height: 60vw;
      object-fit: cover; /* Ensure the image covers the container */
    }
    
    .svg-mask {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
    
    /* JSX/React */
    import React from 'react';
    
    function MyComponent() {
      return (
        <div className="img-container">
          <img
            src="https://images.unsplash.com/photo-1506399558188-acca6f8cbf41?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2173&q=80"
            alt="Your Image"
          />
          <svg className="svg-mask" viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
            <mask id="path-One">
              {/* Your rect elements here */}
            </mask>
            {/* Apply the mask to the image using the <image> element */}
            <image
              href="https://images.unsplash.com/photo-1506399558188-acca6f8cbf41?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2173&q=80"
              mask="url(#path-One)"
              height="60vw"
            />
          </svg>
        </div>
      );
    }
    
    export default MyComponent;
    
    Login or Signup to reply.
  2. Suryasish Paul

    You are correct; the image should only be included once within the SVG using the element. Here’s the corrected code:

    /* CSS */
    .img-container {
      position: relative;
    }
    
    img {
      height: 60vw;
      object-fit: cover; /* Ensure the image covers the container */
    }
    
    .svg-mask {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
    
    /* JSX/React */
    import React from 'react';
    
    function MyComponent() {
      return (
        <div className="img-container">
          <svg className="svg-mask" viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
            <mask id="path-One">
              {/* Your rect elements here */}
            </mask>
            {/* Apply the mask to the image using the <image> element */}
            <image
              href="https://images.unsplash.com/photo-1506399558188-acca6f8cbf41?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2173&q=80"
              mask="url(#path-One)"
              height="60vw"
            />
          </svg>
        </div>
      );
    }
    
    export default MyComponent;
    

    The code now includes the image only once within the SVG using the element, and the SVG mask is applied correctly to the image. The outer with the class .img-container is used to position the SVG mask on top of the image using CSS.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search