为标签云创建路标样式轮廓

问题描述

我想仅使用 CSS3 创建一个带有略微圆润的箭头作为每个标签的轮廓向右指向的标签云显示。我目前的努力如下所示。

body,html{margin:0;padding:0;}
  body
  {
   padding:1em;
   background-color:#23232f;
   font-family:arial;
  }
  div
  {
   display:inline-block;
   position:relative;
   margin-right:2em;
   margin-bottom:1em;
  }

  

  .tag
  {
   display:inline-block;
   position:relative;
   text-align:center;
   
   height:1.5em;
   z-index:100;
   background-color:transparent;
   color:white;
  }

  .tag > span
  {
   position:relative;
   display:flex; 
   align-items:center;
   justify-content:center;
   height:1.5em;
   border-radius:2px;
   border-top-right-radius:0;
   border-bottom-right-radius:0;
   padding-left:1em;
   padding-right:1em;
   border:1px solid silver;
   border-right-style:none;
   
  }

  .tag > span::after
  {
   content:' ';
   position:absolute;
   top:-0.17em;
   left:calc(100% - 1px);
   width:1.25em;
   height:1.25em;
   border:1px solid silver;
   border-left-style:none;
   
   border-bottom-style:none;
   border-radius:4px;
   transform:rotate(45deg);
   transform-origin:top left;
   z-index:-10;
  }
<div class='tag'>
 <span>Stack Exchange</span>
</div>
<div class='tag'>
 <span>Ask Ubuntu</span>
</div>
<div class='tag'>
 <span>Stack Overflow</span>
</div>

虽然这行得通,但我已经通过反复试验得到了一些正确的东西。特别是我不清楚

  • 为什么我必须将 ::after 伪元素向上移动 0.17em
  • 为什么该元素的高度/宽度必须为 1.25em

纯几何建议,为了得到 1.5em 的高度,伪元素的边长应该是 1.067em。这是因为

  • 边界半径效果
  • 应用 transformheight/width 的顺序?

或者更一般地说,有没有更好的方法来做到这一点 - 请记住,我希望结果始终具有响应性。

解决方法

为了获得更准确的结果,您需要使用 top:-1px,因为您在主元素上有 1px 的边框,而 position:absolute 则考虑填充框,然后考虑您必须使用的大小calc(1.5em/1.41) 是主元素的高度除以 sqrt(2)。您也可以保留 left:100%

body {
  padding: 1em;
  background-color: #23232f;
  font-family: arial;
}

div {
  display: inline-block;
  position: relative;
  margin-right: 2em;
  margin-bottom: 1em;
}

.tag {
  display: inline-block;
  position: relative;
  text-align: center;
  height: 1.5em;
  z-index: 100;
  background-color: transparent;
  color: white;
}

.tag>span {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 1.5em;
  border-radius: 2px;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  padding-left: 1em;
  padding-right: 1em;
  border: 1px solid silver;
  border-right-style: none;
}

.tag>span::after {
  content: ' ';
  position: absolute;
  top: -1px; /* equal to border width */
  left: 100%;
  width: calc(1.5em/1.41);
  height: calc(1.5em/1.41);
  border: 1px solid silver;
  border-left-style: none;
  border-bottom-style: none;
  border-radius: 0 4px 0 0;
  transform: rotate(45deg);
  transform-origin: top left;
  z-index: -10;
}
<div class='tag'>
  <span>Stack Exchange</span>
</div>
<div class='tag'>
  <span>Ask Ubuntu</span>
</div>
<div class='tag'>
  <span>Stack Overflow</span>
</div>