CSS 从背景中切出的透明文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13932946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 21:04:20  来源:igfitidea点击:

Transparent text cut out of background

csssvgfontscss-shapes

提问by Love Dager

Is there any way to make a transparent text cut out of a backgroundeffect like the one in the following image, with CSS?
It would be sad to lose all precious SEO because of images replacing text.

有没有办法用CSS从背景效果中剪出透明文本,如下图所示?
由于图像替换文本而失去所有宝贵的搜索引擎优化将是可悲的。

Transparent text cut out of background

从背景中切出的透明文本

I first thought of shadows but I can't figure anything out...

我首先想到了阴影,但我什么也想不通......

The image is the site background, an absolute positioned <img>tag

图片为网站背景,绝对定位<img>标签

采纳答案by Gijs

It's possible with css3 but it's not supported in all browsers

css3 可以,但并非所有浏览器都支持

With background-clip: text; you can use a background for the text, but you will have to align it with the background of the page

带有背景剪辑:文本;您可以为文本使用背景,但必须将其与页面背景对齐

body {
    background: url(http://www.color-hex.com/palettes/26323.png) repeat;
    margin:10px;
}
h1 { 
    background-color:#fff;
    overflow:hidden;
    display:inline-block; 
    padding:10px; 
    font-weight:bold;
    font-family:arial;
    color:transparent;
    font-size:200px;
}span { 
    background: url(http://www.color-hex.com/palettes/26323.png) -20px -20px repeat;
    -webkit-text-fill-color: transparent;
    -webkit-background-clip: text;
    display:block;
}
<h1><span>ABCDEFGHIKJ</span></h1>

http://jsfiddle.net/JGPuZ/1337/

http://jsfiddle.net/JGPuZ/1337/

Automatic alignment

自动对齐

with a little javascript you can align the background automatic:

使用一点 javascript,您可以自动对齐背景:

$(document).ready(function(){
  var position = $("h1").position(); //Position of the header in the webpage
  var padding = 10; //Padding set to the header
  var left = position.left + padding;
  var top = position.top + padding;
  $("h1").find("span").css("background-position","-"+left+"px -"+top+"px"); 
});
body {
    background: url(http://www.color-hex.com/palettes/26323.png) repeat;
    margin:10px;
}
h1 { 
    background-color:#fff;
    overflow:hidden;
    display:inline-block; 
    padding:10px; 
    font-weight:bold;
    font-family:arial;
    color:transparent;
    font-size:200px;
}span { 
    background: url(http://www.color-hex.com/palettes/26323.png) -20px -20px repeat;
    -webkit-text-fill-color: transparent;
    -webkit-background-clip: text;
    display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1><span>ABCDEFGHIKJ</span></h1>
? http://jsfiddle.net/JGPuZ/1336/http://jsfiddle.net/JGPuZ/1336/

回答by web-tiki

Although this is possible with CSS, a better approach would be to use an inline SVGwith SVG masking. This approach has some advantages over CSS :

尽管这可以通过 CSS 实现,但更好的方法是使用带有SVG masking内联 SVG。这种方法比 CSS 有一些优势:

CodePen Demo : SVG text mask

CodePen 演示:SVG 文本掩码

transparent text clipping background

透明文字剪裁背景

body,html{height:100%;margin:0;padding:0;}
body{
  background:url('https://farm9.staticflickr.com/8760/17195790401_94fcf60556_c.jpg');
  background-size:cover;
  background-attachment:fixed;
}
svg{width:100%;}
<svg viewbox="0 0 100 60">
  <defs>
    <mask id="mask" x="0" y="0" width="100" height="50">
      <rect x="0" y="0" width="100" height="40" fill="#fff"/>
      <text text-anchor="middle" x="50" y="18" dy="1">SVG</text>
      <text text-anchor="middle" x="50" y="30" dy="1">Text mask</text>
    </mask>
  </defs>
  <rect x="5" y="5" width="90" height="30" mask="url(#mask)" fill-opacity="0.5"/>    
</svg>

If you aim on making the text selectable and searchable, you need to include it outside the <defs>tag. The following example shows a way to do that keeping the transparent text with the <use>tag:

如果您的目标是使文本可选择和可搜索,则需要将其包含在<defs>标签之外。以下示例显示了一种方法来保持透明文本与<use>标签:

body,html{height:100%;margin:0;padding:0;}
body{
  background:url('https://farm9.staticflickr.com/8760/17195790401_94fcf60556_c.jpg');
  background-size:cover;
  background-attachment:fixed;
}
svg{width:100%;}
<svg viewbox="0 0 100 60">
  <defs>
    <g id="text">
      <text text-anchor="middle" x="50" y="18" dy="1">SVG</text>
      <text text-anchor="middle" x="50" y="30" dy="1">Text mask</text>
    </g>
    <mask id="mask" x="0" y="0" width="100" height="50">
      <rect x="0" y="0" width="100" height="40" fill="#fff"/>
      <use xlink:href="#text" />
    </mask>
  </defs>
  <rect x="5" y="5" width="90" height="30" mask="url(#mask)" fill-opacity="0.5"/>
  <use xlink:href="#text" mask="url(#mask)" />
</svg>

回答by Nic

One way that works on most modern browsers (except ie, edge), although only with a black background, is to use

尽管只有黑色背景,但在大多数现代浏览器(即边缘除外)上工作的一种方法是使用

background: black;
color: white;
mix-blend-mode: multiply;

in your text element and then put whatever background you want behind that. Multiply basically maps the 0-255 color code to 0-1 and then multiplies that by whatever is behind it, so black stays black and white multiplies by 1 and effectively becomes transparent. http://codepen.io/nic_klaassen/full/adKqWX/

在你的文本元素中,然后把你想要的任何背景放在它后面。乘法基本上将 0-255 颜色代码映射到 0-1,然后乘以它后面的任何内容,因此黑色保持黑色和白色乘以 1 并有效地变为透明。 http://codepen.io/nic_klaassen/full/adKqWX/

回答by Kyle

It ispossible, but so far only with Webkit based browsers (Chrome, Safari, Rockmelt, anything based on the Chromium project.)

可能的,但目前仅适用于基于 Webkit 的浏览器(Chrome、Safari、Rockmelt,任何基于 Chromium 项目的浏览器。)

The trick is to have an element within the white one that has the same background as the body, then use -webkit- background-clip: text;on the inner element which basically means "don't extend the background beyond the text" and use transparent text.

诀窍是在白色元素中放置一个与正文具有相同背景-webkit- background-clip: text;的元素,然后在内部元素上使用,这基本上意味着“不要将背景扩展到文本之外”并使用透明文本。

section
{
    background: url(http://norcaleasygreen.com/wp-content/uploads/2012/11/turf-grass1.jpg);
    width: 100%;
    height: 300px;
}

div
{
    background: rgba(255, 255, 255, 1);
    color: rgba(255, 255, 255, 0);

    width: 60%;
    heighT: 80%;
    margin: 0 auto;
    font-size: 60px;
    text-align: center;
}

p
{
    background: url(http://norcaleasygreen.com/wp-content/uploads/2012/11/turf-grass1.jpg);
    -webkit-background-clip: text;
}
?

http://jsfiddle.net/BWRsA/

http://jsfiddle.net/BWRsA/

回答by feeela

I guess you could achieve something like that using background-clip, but I haven't tested that yet.

我想你可以使用 实现类似的功能background-clip,但我还没有测试过。

See this example:
http://www.css3.info/wp-content/uploads/2008/03/webkit-backgroundcliptext_color.html
(Webkit only, I don't know yet how to change the black background to a white one)

请参阅此示例:
http: //www.css3.info/wp-content/uploads/2008/03/webkit-backgroundcliptext_color.html
(仅限 Webkit,我还不知道如何将黑色背景更改为白色背景)

回答by ChrisBrownie55

I just discovered a new way to do this while messing around, I'm not entirely sure how it works ( if someone else wants to explain please do ).

我刚刚发现了一种新的方法来做到这一点,同时搞砸了,我不完全确定它是如何工作的(如果其他人想解释,请做)。

It seems to work very well, and requires no double backgrounds or JavaScript.

它似乎工作得很好,并且不需要双重背景或 JavaScript。

Here's the code: JSFIDDLE

这是代码: JSFIDDLE

body {
  padding: 0;
  margin: 0;
}

div {
  background: url(http://www.color-hex.com/palettes/26323.png) repeat;
  width: 100vw;
  height: 100vh;
}

body::before {
  content: '$ALPHABET';
  left: 0;
  top: 0;
  position: absolute;
  color: #222;
  background-color: #fff;
  padding: 1rem;
  font-family: Arial;
  z-index: 1;
  mix-blend-mode: screen;
  font-weight: 800;
  font-size: 3rem;
  letter-spacing: 1rem;
}
<div></div>

回答by Pecacheu

Demo Screenshot

演示截图

I needed to make text that looked exactly like it does in the original post, but I couldn't just fake it by lining up backgrounds, because there's some animation behind the element. Nobody seems to have suggested this yet, so here's what I did: (Tried to make it as easy to read as possible.)

我需要制作与原始帖子完全一样的文本,但我不能仅仅通过排列背景来伪造它,因为元素后面有一些动画。似乎还没有人提出这个建议,所以这就是我所做的:(试图让它尽可能容易阅读。)

var el = document.body; //Parent Element. Text is centered inside.
var mainText = "THIS IS THE FIRST LINE"; //Header Text.
var subText = "THIS TEXT HAS A KNOCKOUT EFFECT"; //Knockout Text.
var fontF = "Roboto, Arial"; //Font to use.
var mSize = 42; //Text size.

//Centered text display:
var tBox = centeredDiv(el), txtMain = mkDiv(tBox, mainText), txtSub = mkDiv(tBox),
ts = tBox.style, stLen = textWidth(subText, fontF, mSize)+5; ts.color = "#fff";
ts.font = mSize+"pt "+fontF; ts.fontWeight = 100; txtSub.style.fontWeight = 400;

//Generate subtext SVG for knockout effect:
txtSub.innerHTML =
"<svg xmlns='http://www.w3.org/2000/svg' width='"+stLen+"px' height='"+(mSize+11)+"px' viewBox='0 0 "+stLen+" "+(mSize+11)+"'>"+
    "<rect x='0' y='0' width='100%' height='100%' fill='#fff' rx='4px' ry='4px' mask='url(#txtSubMask)'></rect>"+
    "<mask id='txtSubMask'>"+
        "<rect x='0' y='0' width='100%' height='100%' fill='#fff'></rect>"+
        "<text x='"+(stLen/2)+"' y='"+(mSize+6)+"' font='"+mSize+"pt "+fontF+"' text-anchor='middle' fill='#000'>"+subText+"</text>"+
    "</mask>"+
"</svg>";

//Relevant Helper Functions:
function centeredDiv(parent) {
    //Container:
    var d = document.createElement('div'), s = d.style;
    s.display = "table"; s.position = "relative"; s.zIndex = 999;
    s.top = s.left = 0; s.width = s.height = "100%";
    //Content Box:
    var k = document.createElement('div'), j = k.style;
    j.display = "table-cell"; j.verticalAlign = "middle";
    j.textAlign = "center"; d.appendChild(k);
    parent.appendChild(d); return k;
}
function mkDiv(parent, tCont) {
    var d = document.createElement('div');
    if(tCont) d.textContent = tCont;
    parent.appendChild(d); return d;
}
function textWidth(text, font, size) {
    var canvas = window.textWidthCanvas || (window.textWidthCanvas = document.createElement("canvas")),
    context = canvas.getContext("2d"); context.font = size+(typeof size=="string"?" ":"pt ")+font;
    return context.measureText(text).width;
}

Just throw that in your window.onload, set the body's background to your image, and watch the magic happen!

只需将其放入 window.onload 中,将主体的背景设置为您的图像,然后观看神奇的发生!

回答by Rashed

just put that css

只要把那个css

    .banner-sale-1 .title-box .title-overlay {
      font-weight: 900;
      overflow: hidden;
      margin: 0;
      padding-right: 10%;
      padding-left: 10%;
      text-transform: uppercase;
      color: #080404;
      background-color: rgba(255, 255, 255, .85);

      /* that css is the main think (mix-blend-mode: lighten;)*/
      mix-blend-mode: lighten;

    }

回答by tanius

You can use myadzel's PatternizerjQuery pluginto achieve this effect across browsers. At this time, there is no cross-browser way to do this with just CSS.

您可以使用 myadzel 的PatternizerjQuery 插件来实现跨浏览器的这种效果。目前,没有跨浏览器的方法可以仅使用 CSS 来做到这一点。

You use Patternizer by adding class="background-clip"to HTML elements where you want the text to be painted as an image pattern, and specify the image in an additional data-pattern="…"attribute. See the source of the demo. Patternizer will create an SVG image with pattern-filled text and underlay it to the transparently rendered HTML element.

您可以通过添加class="background-clip"到 HTML 元素来使用 Patternizer ,您希望将文本绘制为图像模式,并在附加data-pattern="…"属性中指定图像。请参阅演示的来源。Patternizer 将创建一个带有图案填充文本的 SVG 图像,并将其作为透明渲染的 HTML 元素的底层。

If, as in the question's example image, the text fill pattern should be a part of a background image extending beyond the "patternized" element, I see two options (untested, my favourite first):

如果,如问题的示例图像,文本填充图案应该是超出“图案化”元素的背景图像的一部分,我会看到两个选项(未经测试,我最喜欢的第一个):

  • Use masking instead of a background image in the SVG.As in web-tiki's answer, to which using Patternizer will still add automatic generation of the SVG and an invisible HTML element on top that allows text selection and copying.
  • Or use automatic alignment of the pattern image.Can be done with JavaScript code similar to the one in Gijs's answer.
  • 在 SVG 中使用遮罩而不是背景图像。正如在web-tiki 的回答中一样,使用 Patternizer 仍然会添加自动生成 SVG 和一个不可见的 HTML 元素,允许文本选择和复制。
  • 或者使用图案图像的自动对齐。可以使用类似于Gijs's answer 中的JavaScript 代码来完成。

回答by tanius

You can use an inverted / negative / reverse fontand apply it with the font-face="…"CSS rule. You might have to play with letter spacing to avoid small white gaps between letters.

您可以使用反向/负/反向字体并将其与font-face="…"CSS 规则一起应用。您可能需要调整字母间距以避免字母之间出现小的白色间隙。

If you do not require a specific font, it's simple. Download a likeable one, for example from this collection of inverted fonts.

如果您不需要特定字体,这很简单。下载一个可爱的,例如从倒置字体集合中下载。

If you require a specific font (say, "Open Sans"), it's difficult. You have to convert your existing font into an inverted version. This is possible manually with Font Creator, FontForge etc., but of course we want an automated solution. I could not find instructions for that yet, but some hints:

如果您需要特定的字体(例如“Open Sans”),这很困难。您必须将现有字体转换为反转版本。这可以使用 Font Creator、FontForge 等手动完成,但我们当然想要一个自动化的解决方案。我还找不到相关说明,但有一些提示: