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
:
- Copy the complete mask/blob svg (including the parent svg with viewBox attribute).
- 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
Specifying Style and Weight for Google Fonts
Differencebetween Outline and Border CSS Properties
How to Apply Styles to Multiple Classes at Once
Why Put in Front of the File Name "_" or "_" in SCSS/Css
How to Select the Last N Items with Nth-Child
Using Twitter Bootstrap 2.0 - How to Make Equal Column Heights
Bootstrap 3: Pull-Right for Col-Lg Only
IE7 and the CSS Table-Cell Property
Bootstrap: Position of Dropdown Menu Relative to Navbar Item
How to Align Items in a <H:Panelgrid> to the Right
How to Extend CSS Class with Another Style
How to Combine Two Media Queries
Is Box Sizing Inherited If Declared Inside Universal Selector