模拟外部笔划::伪元素之前:透明文本问题

drm*_*wer 19 html javascript css svg

我很难相信,没有使用CSS的标准,简单(且与浏览器无关)的方法来文本外部放置笔触效果。

我们确实有,-webkit-text-stroke但是由于某些奇怪的原因,笔画围绕文本的边界居中,而不是文本的边界之外(如此处所哀叹)

因此,我试图基于此想法实现一种变通方法,该方法是将描边的文本放置在原始未描边的文本后面的伪元素中。我已经在jsfiddle中用以下代码演示了这一点

var jQueryAttr = function(selector, attr, setterFunction) {
  document.querySelectorAll(selector).forEach((el, i) => {
    el.setAttribute(attr, setterFunction.call(el, i, attr));
  });
};

jQueryAttr('.myclass', 'data-myclass', function(index, attr) {
  return this.innerHTML;
});
Run Code Online (Sandbox Code Playgroud)
body {
  background: none;
}

.basic {
  color: rgba(186, 218, 85, 1);
  font: 2.5em Georgia, serif;
}

.myclass {
  position: relative;
  background: transparent;
  z-index: 0;
}

.myclass::before {
  content: attr(data-myclass);
  position: absolute;
  -webkit-text-stroke: 0.2em rgba(0, 0, 0, 1);
  z-index: -1;
}

.anotherclass {
  -webkit-text-stroke: 0.2em rgba(0, 0, 0, 1);
}
Run Code Online (Sandbox Code Playgroud)
<p class="basic">Text without any stroke</p>
<p class="myclass basic">Text with outer stroke</p>
<p class="anotherclass basic">Without the trick applied</p>
Run Code Online (Sandbox Code Playgroud)

效果很好,除非文本本身具有一定的透明度,然后您看到下面的黑色笔划(如此变体所示)(唯一的变化是将文本的不透明度固定为0.3)。如您所见,描边元素中的黑色正渗透到文本中(在第一行中)。

那么,有没有另一个巧妙的技巧可以用来解决这个问题呢?我猜有可能在描边层和未描边层之间添加另一个伪元素,使用纯白色文本(或一个与背景匹配的文本),但是我想在我喜欢的情况下应用此技术无法预先知道背景的颜色 ……例如,背景颜色是放置在任意用户选择的图像上的。出于这个原因,我给自己定了backgroundbody,以none在上面的例子。

Tem*_*fif 13

这是一个您可以考虑的想法,可以mix-blend-mode结合使用文本阴影来进行近似。棘手的部分是在需要更大笔触的情况下调整阴影:

.text > span {
  font-family:sans-serif;
  font-size:60px;
  font-weight: bold;
  color:#fff; /*use white*/
  /*create the stroke around text*/
  text-shadow:
    2px 0  0px #000,
    0 2px 0px #000,
    2px 2px 0px #000,
    -2px 0 0px #000,
    0 -2px 0px #000,
    -2px -2px 0px #000,
    -2px 2px 0px #000,
    2px -2px 0px #000;
  mix-blend-mode: darken; /*everything is more dark than white so we always see the background */
}
.text {
  display:inline-block;
  padding:20px;
  background:linear-gradient(to right,red, blue);
}
Run Code Online (Sandbox Code Playgroud)
<div class="text"><span>Some text here</span></div>
Run Code Online (Sandbox Code Playgroud)

使用CSS变量可能会使调整更容易:

.text > span {
  font-family:sans-serif;
  font-size:60px;
  font-weight: bold;
  color:#fff; /*use white*/
  /*create the stroke around text*/
  text-shadow:
    var(--s,2px) 0  var(--c,0) #000,
    0 var(--s,2px) var(--c,0) #000,
    var(--s,2px) var(--s,2px) var(--c,0) #000,
    calc(-1*var(--s,2px)) 0 var(--c,0) #000,
    0 calc(-1*var(--s,2px)) var(--c,0) #000,
    calc(-1*var(--s,2px)) calc(-1*var(--s,2px)) var(--c,0) #000,
    calc(-1*var(--s,2px)) var(--s,2px) var(--c,0) #000,
    var(--s,2px) calc(-1*var(--s,2px)) var(--c,0) #000;
  mix-blend-mode: darken; /*everything is more dark than white so we always see the background */
}
.text {
  display:inline-block;
  padding:20px;
  background:linear-gradient(to right,red, blue);
  background-size:cover;
  background-position:center;
}
Run Code Online (Sandbox Code Playgroud)
<div class="text"><span>Some text here</span></div>

<div class="text" style="--s:4px;--c:2px;background-image:url(https://picsum.photos/800/600?image=1069)"><span>Some text here</span></div>

<div class="text" style="--s:6px;--c:4px;background-image:url(https://picsum.photos/800/600?image=1051)"><span>Some text here</span></div>
Run Code Online (Sandbox Code Playgroud)

如果要为文本提供透明颜色,则可以使用伪元素将其复制:

.text > span {
  font-family:sans-serif;
  font-size:60px;
  font-weight: bold;
  position:relative;
  display:inline-block;
}
.text > span::before,
.text > span::after {
  content:attr(data-text);
}
.text > span::before {
  color:#fff; /*use white*/
  /*create the stroke around text*/
  text-shadow:
    var(--s,2px) 0  var(--c,0) #000,
    0 var(--s,2px) var(--c,0) #000,
    var(--s,2px) var(--s,2px) var(--c,0) #000,
    calc(-1*var(--s,2px)) 0 var(--c,0) #000,
    0 calc(-1*var(--s,2px)) var(--c,0) #000,
    calc(-1*var(--s,2px)) calc(-1*var(--s,2px)) var(--c,0) #000,
    calc(-1*var(--s,2px)) var(--s,2px) var(--c,0) #000,
    var(--s,2px) calc(-1*var(--s,2px)) var(--c,0) #000;
  mix-blend-mode: darken; /*everything is more dark than white so we always see the background */
}
.text > span::after {
  position:absolute;
  top:0;
  left:0;
  color:rgba(0,255,0,0.4); 
}
.text {
  display:inline-block;
  padding:20px;
  background:linear-gradient(to right,red, blue);
  background-size:cover;
  background-position:center;
}
Run Code Online (Sandbox Code Playgroud)
<div class="text"><span data-text="Some text here"></span></div>

<div class="text" style="--s:4px;--c:2px;background-image:url(https://picsum.photos/800/600?image=1069)"><span data-text="Some text here"></span></div>

<div class="text" style="--s:6px;--c:4px;background-image:url(https://picsum.photos/800/600?image=1051)"><span data-text="Some text here"></span></div>
Run Code Online (Sandbox Code Playgroud)


Kai*_*ido 6

SVG实际上是最简单且具有最佳浏览器支持的。
您可以使用:: before进行几乎相同的设置,不同之处在于,背景描边版本可以具有遮罩,该遮罩将仅使外线可见。
从那里,您可以简单地在上面附加相同文本的副本,并且可以在笔触和填充上随意应用不透明度:

body{
  background-image:url(https://picsum.photos/800/200?image=1051);
  font-family: sans-serif;
}
svg {
  font-size: 40px;
  font-weight: bold;
}
.textStroke {
  stroke: black;
  stroke-width: 12px;
  stroke-linejoin: round;
}
.visibleText {
  fill: rgba(186, 218, 85, 1);
  transition: fill-opacity .5s linear;
}
.visibleText:hover {
  fill-opacity: 0;
}
Run Code Online (Sandbox Code Playgroud)
<svg width="350">
  <defs>
    <!-- we type it only once -->
    <text x="10" y="55" id="txt">Text with outline</text>
    <mask id="mymask">
      <!-- white => visible, black => tansparent -->
      <rect x="0" y="0" width="450" height="70" fill="#FFF"></rect>
      <use xlink:href="#txt" fill="#000"/>
    </mask>
  </defs>
  <!-- our stroked text, with the mask -->
  <use xlink:href="#txt" mask="url(#mymask)" class="textStroke"/>
  <!-- fill version -->
  <use xlink:href="#txt" class="visibleText"/>
</svg>
Run Code Online (Sandbox Code Playgroud)