我很难相信,没有标准和简单(且与浏览器无关)的方法可以使用CSS在文本的外部周围添加笔触效果。
我们确实有-webkit-text-stroke
,但是由于某些奇怪的原因,笔划围绕文本的边界而不是在文本的 之外,如{{3} }。
因此,我正在尝试实现基于bemoaned here的变通方法,该方法是将描边的文本放置在原始未描边的文本后面的伪元素中。我在this idea中用以下代码进行了演示:
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>
这很好用,除非文本本身具有一定的透明度,然后您看到下面的黑色笔划,如this jsfiddle所示(唯一的更改是将文本的不透明度固定为0.3)。如您所见,描边元素中的黑色正渗透到文本中(在第一行中)。
那么还有另一个巧妙的技巧可以用来解决这个问题吗?我猜有可能在描边层和未描边层之间添加另一个伪元素,使用纯白色文本(或一个与背景匹配的文本),但是我想在我事先不知道背景的颜色 ...例如将其放置在用户选择的任意图像上。因此,在上述示例中,我将background
中的body
设置为none
。
答案 0 :(得分: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);
}
<div class="text"><span>Some text here</span></div>
使用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;
}
<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>
如果您想要文本透明的颜色,则可以使用伪元素将其复制:
.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;
}
<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>
答案 1 :(得分: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;
}
<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>
答案 2 :(得分:2)
要使文字周围变粗,可以使用由依次应用的滤镜组成的组合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>
答案 3 :(得分:1)
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>
不幸的是,每个浏览器(browser compatibility table)都不支持其 ,并且该行为将来可能会改变。