Responsive Clip-Path with Inline Svg

Responsive clip-path with inline SVG

References to SVG clip paths are to the clip path definitions themselves and the dimensions or other attributes of the <svg> are meaningless in this context.

What is happening in your example is that you are applying a 4000 px wide clip path to your header. Which is probably only of the order of 900 px wide. So the curvature isn't visible.

If you want a responsive clip path, you should define it using clipPathUnits="objectBoundingBox".

#block-header {    background: Red;    min-height: 100px;    -webkit-clip-path: url(#myClip); clip-path: url(#myClip);}
<h1>SVG image</h1><svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100" viewBox="0 0 1 1" preserveAspectRatio="none"><path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/></svg>
<h1><code>clip-path</code> using the same SVG</h1><header id="block-header"> <svg width="0" height="0"> <defs> <clipPath id="myClip" clipPathUnits="objectBoundingBox"> <path d="M0,0 1,0 1,0.9 C 1,0.9, 0.77,1, 0.5,1 0.23,1, 0,0.9,0,0.9z"/> </clipPath> </defs> </svg></header>

Create responsive SVG clip path / Making SVG path responsive

This answer distorts the shape of the clip path so that it always spans the whole image, regardless of its aspect ratio.

With clipPathUnits="objectBoundingBox", only coordinates between 0 and 1 will lie inside the bounding rectangle of your image. You have to scale down the path for that.

Fortunately, the viewBox for your path names its dimensions. Unfortunately, you cannot leave the computation of the scaling to the renderer, but must give a transformation directly: scale(1 / 810, 1 / 1012). See the restrictions for the content elements of a <clipPath>.

Both the SVG 1.1 and the SVG 2 spec name transform as a possible attribute of the <clipPath> itself, but neither define the coordinate system it should be applied in. For the sake of browser compatibility, it is probably better to leave that alone and use the transform on the <path> element, even if I can see that in Firefox there is no difference in the result.

.clipped-img {    clip-path: url(#raindropClipPath);    width: 100%;    height: auto;}
#raindropSVG { width: 0; height: 0;
}
<svg id="raindropSVG">    <defs>        <clipPath id="raindropClipPath" clipPathUnits="objectBoundingBox">            <path transform="scale(0.0012345, 0.00098814)" d="M0,604.4C0,523.7,30.7,408.8,97.5,320,217,160.9,409.2,0,409.2,0S597.2,167.8,717,331c63,85.7,93,196.4,93,274,0,224.5-181.3,407-405,407S0,829.5,0,604.4Z"/>        </clipPath>    </defs></svg>
<img src="https://i.stack.imgur.com/zubYX.png" alt="Sample Image" class="clipped-img">

SVG Clip path with inline-svg over a video

Group elements are not allowed within clip paths. Remove the <g> and </g> tags, and your example will work.

CSS clip-path with inline SVG not working

objectBoundingBox units are in the range 0..1 Perhaps you meant .73 and 1 as below.

.el-to-clip{  clip-path: url(#nav-path);  width: 500px;  height: 1000px;  background-color: green;}
<svg width="0" height="0">  <defs>  <clipPath id="nav-path" clipPathUnits="objectBoundingBox">    <polygon points="0 0, .73 0, 1 1, 0 1"></polygon>   </clipPath>  </defs></svg>  <div class="el-to-clip"></div>

Problem with CSS SVG Clip path - not working

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 (clip path 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="Sample Image" />
</div>

Responsive clip-path SVG

You can build it using CSS and keep the same size for your circles:

.box {  width:200px;  height:200px;  margin:5px;  background:url(https://i.picsum.photos/id/1074/800/800.jpg) center/cover;  -webkit-mask:    radial-gradient(circle 20px at top    left ,transparent 97%,#fff 100%) top    left,    radial-gradient(circle 20px at top    right,transparent 97%,#fff 100%) top    right,    radial-gradient(circle 20px at bottom left ,transparent 97%,#fff 100%) bottom left,    radial-gradient(circle 20px at bottom right,transparent 97%,#fff 100%) bottom right;  -webkit-mask-size:51% 51%;  -webkit-mask-repeat:no-repeat;  mask:    radial-gradient(circle 20px at top    left ,transparent 97%,#fff 100%) top    left,    radial-gradient(circle 20px at top    right,transparent 97%,#fff 100%) top    right,    radial-gradient(circle 20px at bottom left ,transparent 97%,#fff 100%) bottom left,    radial-gradient(circle 20px at bottom right,transparent 97%,#fff 100%) bottom right;  mask-size:51% 51%;  mask-repeat:no-repeat;}
<div class="box">
</div>
<div class="box" style="width:400px;">
</div>

Animated div with SVG clip-path not responsive?

Part of the problem are your width and max-width definitions.

Essentially you have to ensure your clipped image keeps its aspect ratio.

You might actually use the css aspect-ratio property – but browser support is still not perfect. Thus we take the old-school aspect-ratio hack.

   .imageHero::before {
content: "";
padding-bottom: 100%;
width: 100%;
display: block;
}

.imageHero {
max-width: 65vh;
margin: 0 auto;
clip-path: url('#my-clip-path');
animation: clipRotateAnim 6s linear infinite;
position: relative;
overflow: hidden;
}


/* force aspect ratio 1:1 */
.imageHero::before {
content: "";
padding-bottom: 100%;
width: 100%;
display: block;
}

/* image */
.imageHero::after {
content: "";
position: absolute;
top: -10%;
bottom: -10%;
left: -10%;
right: -10%;
background: var(--i) center;
background-size: cover;
animation: inherit;
animation-direction: reverse;
}

@keyframes clipRotateAnim {
to {
transform: rotate(360deg);
}
}

.imageHero-wrp {
position: relative;
overflow: hidden;
padding: 40px;
background: #eee;
}

.svg-content {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
}
<main>
<div class="imageHero-wrp">
<div class="imageHero" style="--i:url(https://source.unsplash.com/600x600?summer)" width="100%" height="100%">
</div>

<svg class="svg-content" viewBox="0 0 1 1">
<clipPath id="my-clip-path" clipPathUnits="objectBoundingBox">
<path
d="M0.5,0.768 L0.366,1 L0.366,0.732,0.134,0.866 L0.268,0.634 L0,0.634 L0.232,0.5,0,0.366 L0.268,0.366,0.134,0.134 L0.366,0.268 L0.366,0 L0.5,0.232,0.634,0 L0.634,0.268,0.866,0.134 L0.732,0.366 L1,0.366 L0.768,0.5 L1,0.634,0.732,0.634,0.866,0.866 L0.634,0.732 L0.634,1z">
</path>
</clipPath>
</svg>
</div>
</main>

Complex SVG clip-path responsive

As Robert said, when you specify clipPathUnits="objectBoundingBox", the coordinates in the clip path definition are supposed to be between 0,0 (the top left) and 1,1 (the bottom right).

Your paths are about 700x575, so your path is about 600 to 700 times too big.

The simplest solution is to add a transform attribute to your <clipPath> that scales the coordinates down to the correct range.

<clipPath id="map" clipPathUnits="objectBoundingBox" transform="scale(0.00143, 0.00174)">
  • 1/700 ~= 0.00143
  • 1/575 ~= 0.00174

https://codepen.io/anon/pen/GyvZOM



Related Topics



Leave a reply



Submit