Home > Software engineering >  Masking/clipping an image with a custom SVG shape
Masking/clipping an image with a custom SVG shape

Time:12-23

I need to mask an image with a custom shape SVG (it's like an arch as you see in the images below). Here is the actual code with the path of the SVG shape:

    img {
      clip-path: path('M451.715 154.05C451.79 152.468 451.828 150.88 451.828 149.286C451.828 66.8376 350.683 0 225.914 0C101.145 0 0 66.8376 0 149.286C0 150.88 0.0378114 152.468 0.112874 154.05H0V536H451.828V154.05H451.715Z');
    }

This is the original SVG:

<svg width="452" height="536" viewBox="0 0 452 536" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M451.715 154.05C451.79 152.468 451.828 150.88 451.828 149.286C451.828 66.8376 350.683 0 225.914 0C101.145 0 0 66.8376 0 149.286C0 150.88 0.0378114 152.468 0.112874 154.05H0V536H451.828V154.05H451.715Z" fill="#FF0809"/>
</svg>

It seems work but I need to center the shape on the image and it has to keep its ratio (not stretching). Below I attach an image with details that explains better than words.

Any idea?

enter image description here

CodePudding user response:

This promotes my own library, pathfit. It is aimed at exactly that problem. If you need a solution only as a one-off, it could be appropriate to compute a new path in a node environment and be done. If you expect various responsive sizes, it might be a better idea to include the lib on your page and let it compute on the fly.

const Pathfit = require('pathfit');

const path = 'M451.715 154.05C451.79 152.468 451.828 150.88 451.828 149.286C451.828 66.8376 350.683 0 225.914 0C101.145 0 0 66.8376 0 149.286C0 150.88 0.0378114 152.468 0.112874 154.05H0V536H451.828V154.05H451.715Z';

const base = {
    viewBox: '0 0 452 536'
};

const pathfitter = new Pathfit(base, undefined, path);

// set width and height to the size of the image to be clipped
pathfitter.scale_with_aspect_ratio(width, height);

CodePudding user response:

In my experience I used an inline svg element. Tried many things before like clip-path but couldn't get it to work properly.

This is what I ended up with:

HTML

<div >
    <svg viewBox="0 0 750 750" preserveAspectRatio="xMidYMid meet">
    ...
    </svg>
    <img src="..." alt="" />
</div>

CSS

svg {
    overflow: hidden;
}

.svg-image {
    position: relative;
    width: 100%;
    overflow: hidden;
}

.svg-image img {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    z-index: -1;
    width: 100%;
    object-fit: cover;
    object-position: center;
}

DEMO

I tweaked your svg file a bit in Illustrator and created a "compound path" of the original path. I also added a background path (M489,535H-36V0h525V535z) and merged both paths.

<svg viewBox="0 0 452 536" preserveAspectRatio="xMidYMid meet">
    <g>
        <path fill="#FFFFFF" d="M489,535H-36V0h525V535z M451.7,154.1c0.1-1.6,0.1-3.2,0.1-4.8C451.8,66.8,350.7,0,225.9,0S0,66.8,0,149.3c0,1.6,0,3.2,0.1,4.8H0v382h451.8v-382H451.7z" />
    </g>
</svg> 

This can now be used as an inline svg mask. Let's see if I can get it to work with CSS instead...

EDIT: Unfortunatly I don't see an easy option to make this clip-path responsive. If it was a basic shape then we could use % or em but as this is not the case I'm convinced an inline svg is your only option. Unless someone else has a better idea? https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path

  • Related