frontcodelover
frontcodelover

Reputation: 337

Problem with CSS SVG Clip path - not working

I have a problem with a clip path css. When I put clip path on my css fill, image wont show... I m on chrome. So you have any idea ?

I use this generator https://10015.io/tools/svg-blob-generator

.card .content .picture img {
    width: 100%;
    height: 100%;
    border-radius:50%;
    border: 1px solid #fff;
    backdrop-filter: blur(10px);
    box-shadow: 0 0 4px 2px #fff;
    clip-path: path('M317.5,327.5Q297,415,179.5,392.5Q62,370,103.5,270.5Q145,171,210,151.5Q275,132,306.5,186Q338,240,317.5,327.5Z');
}

Upvotes: 2

Views: 3438

Answers (1)

herrstrietzel
herrstrietzel

Reputation: 17165

As an easy workaround you might also use mask-image:

  1. Copy the complete mask/blob svg (including the parent svg with viewBox attribute).
  2. Convert the svg to a data-url (e.g. via Yoksel's URL-encoder for SVG )

Example 1: css mask-image (mask svg inlined as data url)

svg {
  display: inline-block;
  width: 10em;
}

.picture {
  border: 1px solid #ccc;
  width: 500px;
  height: auto;
  aspect-ratio: 1/1;
  resize: horizontal;
  overflow: auto;
}

.imgMask {
  object-fit: cover;
  width: 100%;
  height: 100%;
  mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 480 480' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' %3E%3Cpath fill='%23474bff' d='M465.5,291Q452,342,416,379Q380,416,335.5,439Q291,462,239.5,464Q188,466,144,440.5Q100,415,62.5,379Q25,343,13.5,291.5Q2,240,16,189.5Q30,139,61.5,97.5Q93,56,141,36Q189,16,239,20.5Q289,25,334,45.5Q379,66,412,103.5Q445,141,462,190.5Q479,240,465.5,291Z' /%3E%3C/svg%3E");
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 480 480' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' %3E%3Cpath fill='%23474bff' d='M465.5,291Q452,342,416,379Q380,416,335.5,439Q291,462,239.5,464Q188,466,144,440.5Q100,415,62.5,379Q25,343,13.5,291.5Q2,240,16,189.5Q30,139,61.5,97.5Q93,56,141,36Q189,16,239,20.5Q289,25,334,45.5Q379,66,412,103.5Q445,141,462,190.5Q479,240,465.5,291Z' /%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: contain;
  mask-size: contain;
}
<div class="picture">
  <img class="imgMask" src="https://placekitten.com/g/300/300" alt="" />
</div>

Unfortunately you will need some vendor-prefixes (e.g. -webkit-mask-image) to provide the best compatibility.
Those required prefixed properties can also "bloat" your css file size (albeit negligible when using rather lightweight svg code or just a few mask-images).

Example 2: using clip-path:

.picture {
  height: auto;
  aspect-ratio: 1/1;
}

.resize{
  width: 500px;
  resize: horizontal;
  overflow: auto;
  border: 1px solid #ccc;
}

.img{
  aspect-ratio:1/1;
  object-fit: cover;
  width: 100%;
  height: 100%;
}

.imgClip {
  aspect-ratio: 1/1;
  -webkit-clip-path: url(#my-clip-path);
  clip-path: url(#my-clip-path);
}

.clipPath{
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden
}
<h3>Clip-path </h3>
<div class="resize">
  <img class="img imgClip " src="https://placekitten.com/g/300/300" alt="" />
</div>
<!--hidden clip path svg-->
<svg class="clipPath">
  <!-- scale path to fit a 1x1 viewBox: 1/480 = 0.002 -->
  <clipPath id="my-clip-path" clipPathUnits="objectBoundingBox" transform="scale(0.002 0.002)"><path fill="#474bff" d="M465.5,291Q452,342,416,379Q380,416,335.5,439Q291,462,239.5,464Q188,466,144,440.5Q100,415,62.5,379Q25,343,13.5,291.5Q2,240,16,189.5Q30,139,61.5,97.5Q93,56,141,36Q189,16,239,20.5Q289,25,334,45.5Q379,66,412,103.5Q445,141,462,190.5Q479,240,465.5,291Z" />
  </clipPath>
</svg>

Example 3: mask vs. clip-path

As pointed out here "Is the just a bad alternative to ?" there are still significant differences:

  • <mask>supports semi-transparent areas
  • <mask> is usually less performant (compared to <clipPath>) since

Note that SVG ‘path’s, shapes (e.g., ‘circle’) and ‘text’ are all treated as four-channel RGBA images for the purposes of masking operations.

14.4.2.1. Calculating mask values

  • unlike <clipPath>, <mask> won't change/clip an element's hit area for pointer events

svg {
  display: inline-block;
  width: 10em;
}

.picture {
  border: 1px solid #ccc;
  width: 500px;
  height: auto;
  aspect-ratio: 1/1;
  resize: horizontal;
  overflow: auto;
}

.imgMask {
  object-fit: cover;
  width: 100%;
  height: 100%;
  mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 480 480' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' %3E%3Cpath fill='%23474bff' d='M465.5,291Q452,342,416,379Q380,416,335.5,439Q291,462,239.5,464Q188,466,144,440.5Q100,415,62.5,379Q25,343,13.5,291.5Q2,240,16,189.5Q30,139,61.5,97.5Q93,56,141,36Q189,16,239,20.5Q289,25,334,45.5Q379,66,412,103.5Q445,141,462,190.5Q479,240,465.5,291Z' /%3E%3C/svg%3E");
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 480 480' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' %3E%3Cpath fill='%23474bff' d='M465.5,291Q452,342,416,379Q380,416,335.5,439Q291,462,239.5,464Q188,466,144,440.5Q100,415,62.5,379Q25,343,13.5,291.5Q2,240,16,189.5Q30,139,61.5,97.5Q93,56,141,36Q189,16,239,20.5Q289,25,334,45.5Q379,66,412,103.5Q445,141,462,190.5Q479,240,465.5,291Z' /%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: contain;
  mask-size: contain;
}


.imgClip:hover,
.imgMask:hover{
background:red;
  opacity:0.5;
}

.picture {
  height: auto;
  aspect-ratio: 1/1;
}

.resize{
  width: 500px;
  resize: horizontal;
  overflow: auto;
  border: 1px solid #ccc;
}

.img{
  aspect-ratio:1/1;
  object-fit: cover;
  width: 100%;
  height: 100%;
}

.imgClip {
  aspect-ratio: 1/1;
  -webkit-clip-path: url(#my-clip-path);
  clip-path: url(#my-clip-path);
}

.clipPath{
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden
}
<h1>Pointer areas: mask vs. clip</h1>
<h2>Masked image still has an unchanged rectangular hit area</h2>
<div class="picture">
  <img class="imgMask" src="https://placekitten.com/g/300/300" alt="" />
</div>

<h3>Clip-path </h3>
<div class="resize">
  <img class="img imgClip " src="https://placekitten.com/g/300/300" alt="" />
</div>
<!--hidden clip path svg-->
<svg class="clipPath">
  <!-- scale path to fit a 1x1 viewBox: 1/480 = 0.002 -->
  <clipPath id="my-clip-path" clipPathUnits="objectBoundingBox" transform="scale(0.002 0.002)"><path fill="#474bff" d="M465.5,291Q452,342,416,379Q380,416,335.5,439Q291,462,239.5,464Q188,466,144,440.5Q100,415,62.5,379Q25,343,13.5,291.5Q2,240,16,189.5Q30,139,61.5,97.5Q93,56,141,36Q189,16,239,20.5Q289,25,334,45.5Q379,66,412,103.5Q445,141,462,190.5Q479,240,465.5,291Z" />
  </clipPath>
</svg>

Further reading: About clip-path caveats and pitfalls

Eric Meyer: Scaling SVG Clipping Paths for CSS Use
Css-tricks: Unfortunately, clip-path: path() is Still a No-Go
Css-tricks: Clipping and Masking in CSS

Clip path helper

Convert SVG absolute clip-path to relative

Upvotes: 4

Related Questions