带有背景图像的自定义形状
Custom shape with background image
我想为我的导航栏菜单创建一个中间有一个半圆形的水平矩形。除此之外,所有这些形状都必须有背景图像。
像这样:
实现此目标的最佳方法是什么?
使用 SVG:(推荐)
创建此类形状的最佳工具是 SVG 而不是 CSS。 SVG 是可扩展的(对于响应式设计非常有用),它们允许我们更好地控制形状方面——例如圆形或椭圆的 slope/curvature,并且还可以使用图像或渐变作为填充(背景),如下所示。
使用 SVG 绘制形状非常容易。只需使用 path
元素以及移动 (M
)、圆弧 (A
)、直线 (L
) 和 close-path (z
).绘制形状后,使用 pattern
和 image
元素将图像应用为其 fill
。 xlink:href
属性指的是图像的来源。
下面是对上述命令的作用的非常简短的解释。详细解释见this MDN page:
M
- 将笔移动到命令后立即给出的坐标指定的点。
A
- 以指定的 X 和 Y 半径绘制圆弧,在命令后指定的点结束。
L
- 从一个指定点到另一个指定点画一条直线。
z
- 通过从路径的最后一个点到第一个点画一条直线来关闭路径。
path {
fill: url(#g-image);
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg viewBox='0 0 500 60' preserveAspectRatio='none'>
<defs>
<pattern id="g-image" width="1" height="1" patternUnits="objectBoundingBox">
<image xlink:href="http://lorempixel.com/500/60/abstract/6" width="500" height="60" />
</pattern>
</defs>
<path d='M0,0 0,25 205,25 A50,50 0 0,0 295,25 L500,25 500,0z' />
</svg>
使用Clip-path:
另一个替代方法是使用 clip-path
但它的纯 CSS 版本不能使用,因为 (a) 它只能创建 simple/basic 形状而不是路径我们需要并且 (b) 它在 Firefox 中不起作用。因此,我们将不得不使用 clip-path
和一个内联 SVG 元素,如下所示。
使用 clip-path
的缺点是即使使用内联 SVG 元素,这在 IE 中也不起作用。
div {
height: 75px;
width: 600px;
background: url(http://lorempixel.com/500/100/abstract/6);
-webkit-clip-path: url(#clipper);
clip-path: url(#clipper);
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg width='0' height='0'>
<defs>
<clipPath id='clipper' clipPathUnits='objectBoundingBox'>
<path d='M0,0 0,.42 .41,.42 A.1,.83 0 0,0 .59,.42 L1,.42 1,0z' />
</clipPath>
</defs>
</svg>
<div></div>
使用 CSS 掩码:
由于浏览器支持不佳,目前不支持此选项,但当所有浏览器都开始支持它时,它是一个很好的选择。在这种方法中,我们创建了一个基于 radial-gradient
的蒙版,它切掉了图像的底部,圆弧区域除外。由于渐变可以采用固定像素值作为圆形切割的 X 和 Y 轴的半径,因此即使将图像拉伸为响应,该弧形区域的长度也不会增加。
div {
height: 100px;
width: 100%;
background: url(http://lorempixel.com/600/100/abstract/6);
-webkit-mask-image: linear-gradient(to right, white, white), radial-gradient(145px 145px at 50% -25px, white 50%, transparent 51%);
-webkit-mask-position: 0% 0%, 0% 100%;
-webkit-mask-size: 100% 50%;
-webkit-mask-repeat: no-repeat;
}
<div></div>
获得此布局的基本技巧是,我们将尝试创建一个具有纯色层且中心为透明圆圈的叠加层,并将其放置在具有背景图像的元素上方。
这可以通过两种不同的方式实现:
使用径向渐变:
我们将使用 css3 radial-gradient()
创建一个在中心具有特定大小的透明 circle
/ ellipse
的背景图像。使用径向渐变的缺点是中心圆形状不是很平滑。
body {
background: white;
}
.box {
background: url("https://i.imgur.com/waDgcnc.jpg") no-repeat;
background-size: cover;
position: relative;
height: 100px;
}
.overlay {
background: radial-gradient(95px 70px at 50% 0, transparent, transparent 40px, #fff 30px);
position: absolute;
overflow: hidden;
height: 30px;
bottom: 0;
right: 0;
left: 0;
}
<div class="box">
<div class="overlay">
</div>
</div>
使用伪元素:
我们可以使用 ::before
或 ::after
伪元素创建此叠加层,该元素呈圆形,具有较大的框阴影值。中央 circle
/ ellipse
创建看起来比 radial-gradient()
.
更好更流畅
body {
background: white;
}
.box {
background: url("https://i.imgur.com/waDgcnc.jpg") no-repeat;
background-size: cover;
position: relative;
height: 100px;
}
.overlay {
position: absolute;
overflow: hidden;
height: 30px;
bottom: 0;
right: 0;
left: 0;
}
.overlay:before {
box-shadow: 0 0 0 1000px #fff;
transform: translateX(-50%);
border-radius: 100%;
position: absolute;
height: 70px;
content: '';
width: 100px;
bottom: 0;
left: 50%;
}
<div class="box">
<div class="overlay">
</div>
</div>
Note: These method will work only when nearest ancestor with background property has some solid color applied to it. This method will not work if the ancestor is having some image as background or linear / radial gradient.
有用资源:
我想为我的导航栏菜单创建一个中间有一个半圆形的水平矩形。除此之外,所有这些形状都必须有背景图像。
像这样:
实现此目标的最佳方法是什么?
使用 SVG:(推荐)
创建此类形状的最佳工具是 SVG 而不是 CSS。 SVG 是可扩展的(对于响应式设计非常有用),它们允许我们更好地控制形状方面——例如圆形或椭圆的 slope/curvature,并且还可以使用图像或渐变作为填充(背景),如下所示。
使用 SVG 绘制形状非常容易。只需使用 path
元素以及移动 (M
)、圆弧 (A
)、直线 (L
) 和 close-path (z
).绘制形状后,使用 pattern
和 image
元素将图像应用为其 fill
。 xlink:href
属性指的是图像的来源。
下面是对上述命令的作用的非常简短的解释。详细解释见this MDN page:
M
- 将笔移动到命令后立即给出的坐标指定的点。A
- 以指定的 X 和 Y 半径绘制圆弧,在命令后指定的点结束。L
- 从一个指定点到另一个指定点画一条直线。z
- 通过从路径的最后一个点到第一个点画一条直线来关闭路径。
path {
fill: url(#g-image);
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg viewBox='0 0 500 60' preserveAspectRatio='none'>
<defs>
<pattern id="g-image" width="1" height="1" patternUnits="objectBoundingBox">
<image xlink:href="http://lorempixel.com/500/60/abstract/6" width="500" height="60" />
</pattern>
</defs>
<path d='M0,0 0,25 205,25 A50,50 0 0,0 295,25 L500,25 500,0z' />
</svg>
使用Clip-path:
另一个替代方法是使用 clip-path
但它的纯 CSS 版本不能使用,因为 (a) 它只能创建 simple/basic 形状而不是路径我们需要并且 (b) 它在 Firefox 中不起作用。因此,我们将不得不使用 clip-path
和一个内联 SVG 元素,如下所示。
使用 clip-path
的缺点是即使使用内联 SVG 元素,这在 IE 中也不起作用。
div {
height: 75px;
width: 600px;
background: url(http://lorempixel.com/500/100/abstract/6);
-webkit-clip-path: url(#clipper);
clip-path: url(#clipper);
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg width='0' height='0'>
<defs>
<clipPath id='clipper' clipPathUnits='objectBoundingBox'>
<path d='M0,0 0,.42 .41,.42 A.1,.83 0 0,0 .59,.42 L1,.42 1,0z' />
</clipPath>
</defs>
</svg>
<div></div>
使用 CSS 掩码:
由于浏览器支持不佳,目前不支持此选项,但当所有浏览器都开始支持它时,它是一个很好的选择。在这种方法中,我们创建了一个基于 radial-gradient
的蒙版,它切掉了图像的底部,圆弧区域除外。由于渐变可以采用固定像素值作为圆形切割的 X 和 Y 轴的半径,因此即使将图像拉伸为响应,该弧形区域的长度也不会增加。
div {
height: 100px;
width: 100%;
background: url(http://lorempixel.com/600/100/abstract/6);
-webkit-mask-image: linear-gradient(to right, white, white), radial-gradient(145px 145px at 50% -25px, white 50%, transparent 51%);
-webkit-mask-position: 0% 0%, 0% 100%;
-webkit-mask-size: 100% 50%;
-webkit-mask-repeat: no-repeat;
}
<div></div>
获得此布局的基本技巧是,我们将尝试创建一个具有纯色层且中心为透明圆圈的叠加层,并将其放置在具有背景图像的元素上方。
这可以通过两种不同的方式实现:
使用径向渐变:
我们将使用 css3 radial-gradient()
创建一个在中心具有特定大小的透明 circle
/ ellipse
的背景图像。使用径向渐变的缺点是中心圆形状不是很平滑。
body {
background: white;
}
.box {
background: url("https://i.imgur.com/waDgcnc.jpg") no-repeat;
background-size: cover;
position: relative;
height: 100px;
}
.overlay {
background: radial-gradient(95px 70px at 50% 0, transparent, transparent 40px, #fff 30px);
position: absolute;
overflow: hidden;
height: 30px;
bottom: 0;
right: 0;
left: 0;
}
<div class="box">
<div class="overlay">
</div>
</div>
使用伪元素:
我们可以使用 ::before
或 ::after
伪元素创建此叠加层,该元素呈圆形,具有较大的框阴影值。中央 circle
/ ellipse
创建看起来比 radial-gradient()
.
body {
background: white;
}
.box {
background: url("https://i.imgur.com/waDgcnc.jpg") no-repeat;
background-size: cover;
position: relative;
height: 100px;
}
.overlay {
position: absolute;
overflow: hidden;
height: 30px;
bottom: 0;
right: 0;
left: 0;
}
.overlay:before {
box-shadow: 0 0 0 1000px #fff;
transform: translateX(-50%);
border-radius: 100%;
position: absolute;
height: 70px;
content: '';
width: 100px;
bottom: 0;
left: 50%;
}
<div class="box">
<div class="overlay">
</div>
</div>
Note: These method will work only when nearest ancestor with background property has some solid color applied to it. This method will not work if the ancestor is having some image as background or linear / radial gradient.
有用资源: