【问题标题】:Dynamically aligning pseudo element according to parent height根据父高度动态对齐伪元素
【发布时间】:2018-06-25 14:31:49
【问题描述】:

我正在尝试创建一个箭头标签,使用 css :after

.one-line {
  font-size: 2em;
  width: 150px;
  min-height: 50px;
  height: auto;
  background: blue;
  margin: 5px;
  position: relative;
  color: #fff;
}

.one-line:after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  left: 100%;
  width: 0;
  height: 0;
  border-top: 25px solid transparent;
  border-bottom: 25px solid transparent;
  border-left: 25px solid red;
}
<div class="one-line">text<br>text<br></div>

我希望后元素采用与父元素相同的高度,如何通过 css 或 js 做到这一点?

注意:标签内的文本是动态填充的。 [最大文本长度:2 行]

正如我所想,可能无法将其调整为父母的任何高度。目前我正在尝试调整一行和两行文本。

【问题讨论】:

  • 这是个好问题,因为知道 :before 元素不是 dom 元素,所以不能被 js 访问(为了设置边框底部和顶部 = div 的高度 / 2)。还实用地添加样式标签仅适用于一个 div(如果多个 div 具有相同的类...)

标签: html css css-shapes


【解决方案1】:

这是使用clip-path 的解决方案。这个想法是在多边形中使用 % 值来仅显示所需的形状,并且无论高度如何,它都将始终有效:

.one-line {
  font-size: 2em;
  width: 150px;
  min-height: 50px;
  height: auto;
  background: blue;
  margin: 5px;
  position: relative;
  color: #fff;
}

.one-line:after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  width: 25px;
  right: -25px;
  background: red;
  -webkit-clip-path: polygon(100% 50%, 0 0, 0 100%);
  clip-path: polygon(100% 50%, 0 0, 0 100%);
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>

<div class="one-line">text</div>

<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>

这是另一种解决方案,它同时依赖伪元素和一些 skew 转换来创建箭头。你会注意到这个会保持箭头的比例。

.one-line {
  font-size: 2em;
  width: 150px;
  min-height: 50px;
  height: auto;
  background: blue;
  margin: 5px;
  position: relative;
  color: #fff;
}

.one-line:after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  height: 50%;
  width: 50%;
  right: -25px;
  background: red;
  transform: skewX(20deg) translateX(-33%);
  transform-origin: top;
  z-index: -1;
}

.one-line:before {
  content: '';
  display: block;
  position: absolute;
  bottom: 0;
  height: 50%;
  width: 50%;
  right: -25px;
  background: red;
  transform: skewX(-20deg) translateX(-33%);
  transform-origin: bottom;
  z-index: -1;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>

<div class="one-line">text</div>

<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>

另一种方式,只有 一个 伪元素和linear-gradient

.one-line {
  font-size: 2em;
  width: 150px;
  min-height: 50px;
  height: auto;
  background: blue;
  margin: 5px;
  position: relative;
  color: #fff;
}

.one-line:after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  height: 100%;
  width: 50px;
  right: -50px;
  background: 
   linear-gradient(to bottom left, transparent 49.4%, red 50%) top, 
   linear-gradient(to top left,    transparent 49.4%, red 50%) bottom;
  background-size:100% 50.2%;
  background-repeat:no-repeat;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>

<div class="one-line">text</div>

<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>

最后没有任何伪元素,只有主元素的背景:

.one-line {
  font-size: 2em;
  width: 200px;
  padding-left:50px;
  min-height: 50px;
  height: auto;
  background: 
   linear-gradient(blue,blue) left/calc(100% - 50px) 100%,
   linear-gradient(to bottom left, transparent 49.4%, red 50%) top right/50px 50.2%, 
   linear-gradient(to top left, transparent 49.4%, red 50%) bottom right/50px 50.2%;
  background-repeat:no-repeat;
  margin: 5px;
  position: relative;
  color: #fff;
}
<div class="one-line">text<br>text<br></div>
<div class="one-line">text<br>text<br>text<br></div>

<div class="one-line">text</div>

<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>

【讨论】:

  • 感谢@Temani 的回答,你总是一个帮助。我会寻找浏览器的兼容性。
  • @bhansa 欢迎 ;) 顺便说一句,我猜你只会像往常一样发现 IE 的问题 :)
  • @bhansa 我添加了另一个应该得到更多支持的解决方案:)
【解决方案2】:

好吧,您可以选择保持箭头大小不变,并通过将顶部更改为 top: 50%; 并添加 transform: translateY(-50%); 将其对齐在中间

.one-line{
  
  width: 150px;
  min-height: 50px;
  height: auto;
  background: blue;
  margin: 5px;
  position: relative;
  color: #fff;
  
}

.one-line:after{
  content: '';
  display: block;
  position: absolute;
  left: 100%;
  width: 0; 
  height: 0; 
  border-top: 25px solid transparent;
  border-bottom: 25px solid transparent;
  border-left: 25px solid red;
  
  top: 50%;
  transform: translateY(-50%);
}
<div class="one-line">text<br>text<br>text<br>text</div>

<div class="one-line">text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text</div>

【讨论】:

  • 感谢您的回答,我有这个想法。我仍在努力实现上述行为。虽然只是最多两行文本。
【解决方案3】:

使用 svg 路径作为 background-image,您可以将 background-size 属性拉伸到 100% 100%。只要确保 svg 有 preserveAspectRatio="none"

.one-line:after {
    background-image: url('data:image/svg+xml;charset=UTF-8,<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" preserveAspectRatio="none" viewBox="0 0 25.1 50" style="enable-background:new 0 0 25.1 50;" xml:space="preserve"><polygon class="st0" points="0,50 0,50 25,25 0,0" fill="#ff0000"/></svg>');
    position: absolute;
    top: 0;
    left:100%;
    height: 100%;
   width: 25px;
    background-size: 100% 100%;
    background-repeat:no-repeat;
    display: block;
    content:'';
}

https://jsfiddle.net/7jm54u6L/

【讨论】:

  • 它应该是background-repeat 而不是重复。顺便说一句很好的解决方案
  • 感谢您指出这一点。用你的修复编辑了我的回复
猜你喜欢
  • 1970-01-01
  • 2018-09-06
  • 2012-02-27
  • 1970-01-01
  • 2021-12-29
  • 2020-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多