Имитация внешнего удара :: перед псевдоэлементами: проблема с прозрачным текстом

Мне трудно поверить, что не существует стандартного и простого (и независимого от браузера) способа поместить эффект обводки вокруг текста с помощью 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;
});
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);
}
<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>

Ответы

Ответ 1

Вот идея, где вы можете рассмотреть 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);
}
<div class="text"><span>Some text here</span></div>

Ответ 2

Самым простым и с лучшей поддержкой браузера может быть 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;
}
<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>

Ответ 3

CSS-свойство paint-order может помочь:

.stroke {
  -webkit-text-stroke: 0.2em rgba(0, 0, 0, 1);
  paint-order: stroke fill;
}

.basic {
  color: rgba(186, 218, 85, 1);
  font: 2.5em Georgia, serif;
}
<span class="basic">Text without stroke</span><br>
<span class="basic stroke">Text with stroke</span>

Ответ 4

Решение с использованием фильтров SVG

Чтобы feMorphology текст, вы можете использовать комбинированный SVG-фильтр, состоящий из последовательно применяемых фильтров: feMorphology, feComposite и feColorMatrix.

body{
  background-image:url(https://picsum.photos/800/800?image=1061);
  background-size:cover;
  font-family: serif;
  
}
<svg  viewBox="0 0 350 350" >
  <defs>
    <filter id="groupborder" filterUnits="userSpaceOnUse"
            x="-20%" y="-20%" width="300" height="300">
      <feMorphology operator="dilate" in="SourceAlpha"
                    radius="5" result="e1" />
      <feMorphology operator="dilate" in="SourceAlpha"
                    radius="2" result="e2" />
      <feComposite in="e1" in2="e2" operator="xor"
                   result="outline"/>
      <feColorMatrix type="matrix" in="outline"
                     values="0 0 0 0 0.1
                             0 0 0 0 0.2
                             0 0 0 0 0.2
                             0 0 0 1 0" result="outline2"/>
      <feComposite in="outline2" in2="SourceGraphic"
                   operator="over" result="output"/>
    </filter>
  </defs>
  <g id="group" filter="url(#groupborder)">
    <text x="10" y="100"  stroke-width="1" fill="#1D3A56"  font-family="serif" font-size="30" font-weight="700" > Text with outline </text>
  </g>
</svg>