使用 CSS 创建具有动态高度和向内箭头的 div
Creating a div with dynamic height and an arrow facing inwards using CSS
我用 CSS 个伪元素创建了下面的箭头 div。它在固定高度下工作正常,但是当我将其高度设置为自动并增加文本时,它会变成这样。现在是不是以一种随着文本增加高度的方式设置箭头。
我们可以使用 jQuery 来做到这一点,但是否可以仅在 CSS 中做到这一点?
.label-box-st1::after {
border-bottom: 73px solid #800080;
border-right: 45px solid rgba(0, 0, 0, 0);
border-top: 73px solid #800080;
content: "";
position: absolute;
right: -43px;
top: 0;
width: 20px;
}
使用线性渐变:
您可以像下面的代码片段一样使用几个成角度的线性渐变来实现。从代码片段中可以看出,即使内容环绕(或)跨越多行,它也可以适应任何高度。
形状创建如下:
- 一对线性渐变(使用
to [side] [side]
语法)几乎 50%
是彩色的,其余 50%
是透明的。这两个渐变在 Y 轴上都有 50%
大小(即元素高度的一半)并且在 X 轴上有 20px
大小(这意味着它具有固定的三角形宽度)。
- 这些线性渐变位于元素的右上角和右下角以产生三角形效果。
- 再添加一个线性渐变(实际上是纯色),其 Y 轴大小为父级高度的 100%,X 轴大小为
20px
小于 100%
(使用 calc
)。这会产生三角形区域以外的彩色区域。
这种方式的优点如下:
- 它不需要任何额外的元素(真实的或伪的),因此标记中没有不必要的混乱,伪元素可以用于其他事情。
- 正如在最后一个
div
中所看到的,即使 div
的 width
也发生变化,它也会自行调整。
- 右侧的三角形切口是透明的,因此如果需要,还可以通过切口看到页面的背景。
这种方法仅有的两个缺点如下:
- 与伪元素(仅适用于 IE10+)和
相比,渐变具有较低的浏览器支持
- 在一些非常宽的角度下,倾斜的边会有点锯齿。
.shape {
position: relative;
width: 200px;
color: white;
padding: 8px;
margin: 4px;
background: linear-gradient(to bottom right, rgb(128, 0, 128) 49%, transparent 51%), linear-gradient(to top right, rgb(128, 0, 128) 49%, transparent 51%), linear-gradient(to right, rgb(128, 0, 128), rgb(128, 0, 128));
background-size: 20px 50%, 20px 50%, calc(100% - 20px) 100%;
background-position: 100% 0%, 100% 100%, 0% 0%;
background-repeat: no-repeat;
}
.shape.wide {
width: 300px;
}
<div class='shape'>Some div with small content</div>
<div class='shape'>Some div with large content that wraps around into multiple lines</div>
<div class='shape'>Some div with large content that wraps
<br>around into multiple lines
<br>even spanning multiple lines</div>
<div class='shape'>Some div with
<br>large content that wraps
<br>around into multiple lines
<br>even spanning
<br>multiple lines</div>
<div class='shape wide'>Some div with
<br>large content that wraps
<br>around into multiple lines
<br>even spanning
<br>multiple lines</div>
使用 SVG:(推荐的方法,但在下面添加为问题 CSS)
使用 SVG 也可以实现相同的形状。使用 SVG,我们需要做的就是使用 SVG 的 path
元素创建一个路径,然后相对于该元素绝对定位 path
(连同 z-index: -1
将其放在文本后面) . SVG 本质上是可扩展的,因此即使容器的宽度 and/or 高度增加,它们也可以适应。
SVG 的优点与基于梯度的方法几乎相似。 SVG 优于基于渐变的方法的方式是它具有更好的浏览器支持(应该在 IE9+ 中工作)并且锯齿状边缘也不那么明显。
.shape {
position: relative;
width: 200px;
color: white;
padding: 8px;
margin: 4px;
}
.shape.wide {
width: 300px;
}
.shape svg {
position: absolute;
height: 100%;
width: 100%;
top: 0px;
left: 0px;
z-index: -1;
}
.shape path {
fill: rgb(128, 0, 128);
}
<div class='shape'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with small content</div>
<div class='shape'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with large content that wraps around into multiple lines</div>
<div class='shape'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with large content that wraps
<br>around into multiple lines
<br>even spanning multiple lines</div>
<div class='shape'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with
<br>large content that wraps
<br>around into multiple lines
<br>even spanning
<br>multiple lines</div>
<div class='shape wide'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with
<br>large content that wraps
<br>around into multiple lines
<br>even spanning
<br>multiple lines</div>
注意:您可以阅读更多关于 SVG 的 path
元素及其命令(如 M
、z
、L
、A
等)在 this MDN Tutorial 中。我个人建议您看一下 SVG,因为它可以帮助您轻松地创建许多复杂的形状 :)
除了 Harry 的答案,您还可以使用倾斜的伪元素来创建这种形状。
div {
height: 20vh;
width: 50%;
background: #800080;
position: relative;
transition: all 0.4s;
cursor:pointer;
}
div:before,
div:after {
content: "";
position: absolute;
left: 0;
width: 100%;
height: 50%;
background: #800080;
z-index: -1;
}
div:before {
top: 0;
transform: skewX(-45deg);
transform-origin: bottom left;
}
div:after {
top: 50%;
transform: skewX(45deg);
transform-origin: top left;
}
/*demo only*/
div:hover {
width: 80%;
height: 50vh;
}
<div>Hover to see resized element</div>
我用 CSS 个伪元素创建了下面的箭头 div。它在固定高度下工作正常,但是当我将其高度设置为自动并增加文本时,它会变成这样。现在是不是以一种随着文本增加高度的方式设置箭头。
我们可以使用 jQuery 来做到这一点,但是否可以仅在 CSS 中做到这一点?
.label-box-st1::after {
border-bottom: 73px solid #800080;
border-right: 45px solid rgba(0, 0, 0, 0);
border-top: 73px solid #800080;
content: "";
position: absolute;
right: -43px;
top: 0;
width: 20px;
}
使用线性渐变:
您可以像下面的代码片段一样使用几个成角度的线性渐变来实现。从代码片段中可以看出,即使内容环绕(或)跨越多行,它也可以适应任何高度。
形状创建如下:
- 一对线性渐变(使用
to [side] [side]
语法)几乎50%
是彩色的,其余50%
是透明的。这两个渐变在 Y 轴上都有50%
大小(即元素高度的一半)并且在 X 轴上有20px
大小(这意味着它具有固定的三角形宽度)。 - 这些线性渐变位于元素的右上角和右下角以产生三角形效果。
- 再添加一个线性渐变(实际上是纯色),其 Y 轴大小为父级高度的 100%,X 轴大小为
20px
小于100%
(使用calc
)。这会产生三角形区域以外的彩色区域。
这种方式的优点如下:
- 它不需要任何额外的元素(真实的或伪的),因此标记中没有不必要的混乱,伪元素可以用于其他事情。
- 正如在最后一个
div
中所看到的,即使div
的width
也发生变化,它也会自行调整。 - 右侧的三角形切口是透明的,因此如果需要,还可以通过切口看到页面的背景。
这种方法仅有的两个缺点如下:
- 与伪元素(仅适用于 IE10+)和 相比,渐变具有较低的浏览器支持
- 在一些非常宽的角度下,倾斜的边会有点锯齿。
.shape {
position: relative;
width: 200px;
color: white;
padding: 8px;
margin: 4px;
background: linear-gradient(to bottom right, rgb(128, 0, 128) 49%, transparent 51%), linear-gradient(to top right, rgb(128, 0, 128) 49%, transparent 51%), linear-gradient(to right, rgb(128, 0, 128), rgb(128, 0, 128));
background-size: 20px 50%, 20px 50%, calc(100% - 20px) 100%;
background-position: 100% 0%, 100% 100%, 0% 0%;
background-repeat: no-repeat;
}
.shape.wide {
width: 300px;
}
<div class='shape'>Some div with small content</div>
<div class='shape'>Some div with large content that wraps around into multiple lines</div>
<div class='shape'>Some div with large content that wraps
<br>around into multiple lines
<br>even spanning multiple lines</div>
<div class='shape'>Some div with
<br>large content that wraps
<br>around into multiple lines
<br>even spanning
<br>multiple lines</div>
<div class='shape wide'>Some div with
<br>large content that wraps
<br>around into multiple lines
<br>even spanning
<br>multiple lines</div>
使用 SVG:(推荐的方法,但在下面添加为问题 CSS)
使用 SVG 也可以实现相同的形状。使用 SVG,我们需要做的就是使用 SVG 的 path
元素创建一个路径,然后相对于该元素绝对定位 path
(连同 z-index: -1
将其放在文本后面) . SVG 本质上是可扩展的,因此即使容器的宽度 and/or 高度增加,它们也可以适应。
SVG 的优点与基于梯度的方法几乎相似。 SVG 优于基于渐变的方法的方式是它具有更好的浏览器支持(应该在 IE9+ 中工作)并且锯齿状边缘也不那么明显。
.shape {
position: relative;
width: 200px;
color: white;
padding: 8px;
margin: 4px;
}
.shape.wide {
width: 300px;
}
.shape svg {
position: absolute;
height: 100%;
width: 100%;
top: 0px;
left: 0px;
z-index: -1;
}
.shape path {
fill: rgb(128, 0, 128);
}
<div class='shape'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with small content</div>
<div class='shape'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with large content that wraps around into multiple lines</div>
<div class='shape'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with large content that wraps
<br>around into multiple lines
<br>even spanning multiple lines</div>
<div class='shape'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with
<br>large content that wraps
<br>around into multiple lines
<br>even spanning
<br>multiple lines</div>
<div class='shape wide'>
<svg viewBox='0 0 1 1' preserveAspectRatio='none'>
<path d='M0,0 1,0 0.9,0.5 1,1 0,1z' />
</svg>
Some div with
<br>large content that wraps
<br>around into multiple lines
<br>even spanning
<br>multiple lines</div>
注意:您可以阅读更多关于 SVG 的 path
元素及其命令(如 M
、z
、L
、A
等)在 this MDN Tutorial 中。我个人建议您看一下 SVG,因为它可以帮助您轻松地创建许多复杂的形状 :)
除了 Harry 的答案,您还可以使用倾斜的伪元素来创建这种形状。
div {
height: 20vh;
width: 50%;
background: #800080;
position: relative;
transition: all 0.4s;
cursor:pointer;
}
div:before,
div:after {
content: "";
position: absolute;
left: 0;
width: 100%;
height: 50%;
background: #800080;
z-index: -1;
}
div:before {
top: 0;
transform: skewX(-45deg);
transform-origin: bottom left;
}
div:after {
top: 50%;
transform: skewX(45deg);
transform-origin: top left;
}
/*demo only*/
div:hover {
width: 80%;
height: 50vh;
}
<div>Hover to see resized element</div>