Использование SVG:
Вот альтернативное решение, использующее SVG (хотя вы не отметили его). Преимущества использования SVG:
- Имеет лучшую поддержку браузера по сравнению с радиальными градиентами.
- SVG может поддерживать изображения внутри фигуры в отличие от подхода с тенями.
Хотя SVG не поддерживается <= IE8, в то время как box-shadow есть, возможны запасные варианты. </p>
svg {
height: 150px;
width: 150px;
}
polygon {
fill: black;
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<!-- Sample 1 - Using Clip Path -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<defs>
<clipPath id='clipper'>
<path d='M0,0 a50,50 0 1,0 100,0 l 0,100 -100,0' />
</clipPath>
</defs>
<polygon points='0,0 100,0 100,100 0,100' clip-path='url(#clipper)' />
</svg>
<!-- Sample 2 - Using Path -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<pattern id='bg' width='100' height='100' patternUnits='userSpaceOnUse'>
<image xlink:href='http://lorempixel.com/100/100/nature/1' height='100' width='100' />
</pattern>
<path d='M0,0 a50,50 0 1,0 100,0 l 0,100 -100,0 0,-100' fill='url(#bg)' />
</svg>
Использование CSS:
CSS также имеет clip-path
спецификации, и мы можем попробовать что-то вроде приведенного ниже фрагмента.
.shape {
position: relative;
width: 100px;
height: 100px;
background-color: purple;
}
.shape:after {
position: absolute;
content: '';
top: 0px;
left: 0px;
height: 100%;
width: 100%;
background: white;
-webkit-clip-path: ellipse(50% 20% at 50% 0%);
clip-path: ellipse(50% 20% at 50% 5%);
}
.shape.image{
background: url(http://lorempixel.com/100/100);
}
#shape-2 {
width: 100px;
height: 100px;
background-color: purple;
-webkit-clip-path: ellipse(50% 20% at 50% 20%);
clip-path: ellipse(50% 20% at 50% 20%);
}
/* Just for demo */
.shape{
float: left;
margin: 20px;
}
#shape-2 {
margin: 150px 20px 0px;
}
<div class="shape"></div>
<div class="shape image"></div>
<br/>
<div id="shape-2"></div>
Но в отличие от SVG clip-path, чистая версия CSS (то есть без использования встроенного или внешнего SVG), кажется, не в состоянии поддерживать path
. Он поддерживает только фигуры, поэтому в этом случае, если вы используете clip-path
непосредственно на родительском элементе, он просто создаст эллипс (как показано во фрагменте). Чтобы преодолеть это, мы должны были бы поместить путь обрезки на дочерний элемент (или псевдоэлемент), и это означало бы, что обрезанная область не будет прозрачной .
Использование Canvas:
То же самое можно сделать и с помощью Canvas. Команды Canvas очень похожи на SVG, и их преимущества также очень похожи. Однако Canvas основывается на растре и, следовательно, не масштабируется так, как SVG.
window.onload = function() {
/* Canvas example with path */
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'http://lorempixel.com/150/300';
ctx.beginPath();
ctx.moveTo(110, 0);
ctx.arc(60, 0, 50, 0, 3.14, false);
ctx.lineTo(10, 145);
ctx.lineTo(110, 145);
ctx.closePath();
ctx.fill();
/* Use below for using image as a fill */
/*img.onload = function(){
var ptrn = ctx.createPattern(img,'no-repeat');
ctx.fillStyle = ptrn;
ctx.fill();
}*/
}
/* Canvas example with clip path */
var canvasClip = document.getElementById('canvas-clip');
if (canvasClip.getContext) {
var ctxClip = canvasClip.getContext('2d');
ctxClip.beginPath();
ctxClip.moveTo(10, 145);
ctxClip.lineTo(10, 0);
ctxClip.arc(60, 0, 50, 0, Math.PI * 2, true);
ctxClip.lineTo(110, 145);
ctxClip.lineTo(10, 145);
ctxClip.clip();
ctxClip.fillStyle = 'tomato';
ctxClip.fill();
}
}
canvas {
height: 150px;
width: 300px;
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<canvas id='canvas'></canvas>
<canvas id='canvas-clip'></canvas>
Использование масок :
Эта фигура может быть создана с использованием CSS (или) SVG-масок. Маски CSS имеют очень слабую поддержку и в настоящее время работают только в браузерах на основе Webkit, но маски SVG имеют гораздо лучшую поддержку и должны работать в IE9 +.
/* CSS Mask */
.shape {
width: 150px;
height: 150px;
background-color: black;
-webkit-mask-image: radial-gradient(circle closest-corner at 50% 0%, transparent 98%, white 99%);
mask-image: radial-gradient(circle closest-corner at 50% 0%, transparent 98%, white 99%);
}
/* End of CSS Mask */
svg {
height: 150px;
width: 150px;
}
polygon#shape {
fill: black;
mask: url(#masker);
}
/* Just for demo */
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<!-- CSS Mask -->
<div class='shape'></div>
<!-- SVG Mask -->
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<defs>
<mask id='masker' x='0' y='0' width='100' height='100'>
<polygon points='0,0 100,0 100,100 0,100' fill='#fff' />
<circle r='50' cx='50' cy='0' fill='#000' />
</mask>
</defs>
<polygon points='0,0 100,0 100,100 0,100' id='shape' />
</svg>