如何使用CSS创建一个响应式的箭头指针形状?

3
我正在尝试构建一个欧盟能效等级小部件,大致如下所示:
enter image description here 然而,我很难以一种对高度/宽度变化有响应的方式创建箭头形状,此外我需要在每个箭头周围都有黑色边框。
这是我目前为每个箭头想出的东西:
span {
  display: flex;
  flex-direction: row;
  align-items: center;
  font-weight: 700;
  font-size: 1em;
  color: white;
  padding: 2%;
  height: 70%;
  background: #3b7634;
  width: 10%;
}

span::before {
  top: 0;
  background: linear-gradient(to right top, red 50%, transparent 50%);
}

span::after {
  bottom: 0;
  background: linear-gradient(to right bottom, red 50%, transparent 50%);
}

它看起来是这样的:
enter image description here

请注意,提示部分过于"尖锐"且有点粗糙。这确实是响应式的,但不美观,也无法在整个body+tip周围应用边框,因为tip使用了linear-gradient。

那么,有没有更好的方法呢?
顺便说一下,我正在使用Angular。 提前致谢。

3个回答

2
您需要使用三角形而不是线性渐变。例如: https://codepen.io/seanstopnik/pen/072a65f5fa4a4da25e46506f7c19fb3d

* {
  box-sizing: border-box;
}

.arrow {
  position: relative;
  width: 20%;
  height: 22px;
  color: #fff;
  text-align: right;
  background-color: red;
  padding: 2px 10px;
}

.arrow--right:before {
  position: absolute;
  width: 0;
  height: 0;
  content: "";
  border-width: 11px;
  border-style: solid;
  border-color: transparent;
  border-left-color: red;
  top: 0;
  right: -22px;
}
<div class="arrow arrow--right">A</div>


虽然这确实是一个不错的解决方案,但它并没有完全解决响应性问题。我需要箭头的高度/厚度也能够响应。 - Abdul-Qader Haddad
@sean stopnik:做得很好。是否可能有圆角三角形?只是问一下 :) - likith sai

2
您也可以使用clip-path来裁剪箭头。
引用:

clip-path CSS 属性创建一个剪切区域,设置元素应该显示的部分。在区域内的部分被显示,而在区域外的部分被隐藏。

示例

/* cut an arrow shape on the right side */

span {
  clip-path: polygon( 0% 0%, calc(100% - 0.4em) 0%, 100% 50%, calc(100% - 0.4em) 100%, 0% 100%);
}


/* give it a shadow or a border ? */

div {
  filter: drop-shadow(2px 2px 2px);
}


/* styling : size and colors */

span {
  font-size: clamp(1em, 5vmax, 40px);
  padding-right: 0.5em;
  color: white;
  float: left;
  clear: left;
  margin: 0.1em;
}

span:nth-child(1) {
  background: #018133;
  padding-left: 2em;
}

span:nth-child(2) {
  background: #27B432;
  padding-left: 2.8em;
}

span:nth-child(3) {
  background: #88E213;
  padding-left: 3.6em;
}

span:nth-child(4) {
  background: #F0EF00;
  padding-left: 4.2em;
}

span:nth-child(5) {
  background: #FC9000;
  padding-left: 5em;
}

span:nth-child(6) {
  background: #FD0000;
  padding-left: 5.8em;
}

span:nth-child(7) {
  background: #FD001D;
  padding-left: 6.45em;
}
<div>
  <span>A</span>
  <span>B</span>
  <span>C</span>
  <span>D</span>
  <span>E</span>
  <span>F</span>
  <span>G</span>
</div>

Codepen演示

这是一个在线工具,可以帮助您创建第一个形状(有许多准备好的示例可供复制/粘贴)https://bennettfeely.com/clippy/


在尝试了不同的解决方案后,你的方案被证明是最好的,我必须要给你点赞,非常感谢! - Abdul-Qader Haddad
1
太好了!解决方案..救了我的周末..我的女儿会感谢你 :-) 因为我现在可以和她一起玩 :-D - Tokci

1
这是我使用calc和1像素图片想到的最好方法。我想这种技术也适用于正方形的<svg>
缺点是:
  • 我想不出一种完美计算减去突出箭头宽度的方法。
  • 不是纯CSS。但是当您已经使用组件框架时,这个方法非常有效。

箭头提示

我不确定是否有一种方法可以使高度为100%的动态正方形。反之则绝对可行。https://spin.atomicobject.com/2015/07/14/css-responsive-square/

解决方案是使用正方形图片来利用浏览器保持图像纵横比的能力。

这是我在网上找到的一个1像素透明PNG图片。我们还应该注意,不能使用::before::after与图片。

边框

CSS无法实现奇形状的边框,但我们可以通过hack实现。这里我使用了box-shadow,但你也可以使用实际的border。有时,你也可以使用2个不同的矩形来作为边框。
解决方案是将背景颜色和边框分别放在不同的层级上,因为在弯曲处,水平边框实际上需要重叠到倾斜的正方形中。(或者反过来,倾斜的正方形的边框需要重叠到水平边框中。)

总的来说,我认为这最像能源效率箭头。

* { box-sizing: border-box; }

.efficiency {
  border: 1px solid black;
  /* Remove the following rules to support older browsers. */
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.bar {
  display: flex;
  flex-direction: row;
  align-items: center;
  font-weight: 700;
  font-size: 1em;
  color: white;
  flex: 1;
  background: #3b7634;
  position: relative;
  z-index: 0;
  /*
  If you want to support older browsers:
  height: calc(100% / 7 - 3px);
  margin-bottom: 3px;
  */
}

.bar > .text {
  display: flex;
  flex-direction: row;
  align-items: center;
  height: 100%;
  width: 100%;
  border: 2px solid black;
  border-right: none;
  z-index: 1;
}

.a { width: 20%; background-color: #00A851 }
.b { width: 30%; background-color: #4FB947 }
.c { width: 40%; background-color: #C1D82D }
.d { width: 50%; background-color: #FEF200 }
.e { width: 60%; background-color: #FCBA0B }
.f { width: 70%; background-color: #F3711A }
.g { width: 80%; background-color: #EE141F }

.arrow {
  height: calc(100% / 1.41421356237); /* square root 2 */
  transform: translateX(-50%) rotate(45deg);
  position: absolute;
  left: 100%;
  user-select: none;
  background-color: inherit;
  box-shadow: inset -2px 2px black;
}
<h1>These look great</h1>

<div class="efficiency" style="width: 400px; height: 300px">
  <div class="bar a"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">A</div></div>
  <div class="bar b"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">B</div></div>
  <div class="bar c"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">C</div></div>
  <div class="bar d"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">D</div></div>
  <div class="bar e"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">E</div></div>
  <div class="bar f"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">F</div></div>
  <div class="bar g"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">G</div></div>
</div>

<div class="efficiency" style="width: 300px; height: 400px">
  <div class="bar a"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">A</div></div>
  <div class="bar b"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">B</div></div>
  <div class="bar c"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">C</div></div>
  <div class="bar d"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">D</div></div>
  <div class="bar e"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">E</div></div>
  <div class="bar f"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">F</div></div>
  <div class="bar g"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">G</div></div>
</div>

<h1>Just don't go extreme</h1>

<div class="efficiency" style="width: 100px; height: 400px">
  <div class="bar a"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">A</div></div>
  <div class="bar b"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">B</div></div>
  <div class="bar c"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">C</div></div>
  <div class="bar d"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">D</div></div>
  <div class="bar e"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">E</div></div>
  <div class="bar f"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">F</div></div>
  <div class="bar g"><img class="arrow" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="><div class="text">G</div></div>
</div>

enter image description here


我对你的回答之美感到惊叹。非常感谢你。 - Abdul-Qader Haddad
@Abdul-QaderHaddad 没问题。这些确实是一些非常棒的 CSS 技巧,有时会用到它们。希望你从中学到了一些东西。 - Daniel Cheung
1
@Abdul-QaderHaddad 我更新了我的答案,以更好地解释代码。看看你是否觉得有用。 - Daniel Cheung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接