透明文本被删去背景

时间:2012-12-18 12:24:09

标签: css css3 svg fonts css-shapes

有没有办法用CSS创建透明文字剪切出背景效果,如下图所示? 这将是可悲的输,因为替换文本图像的所有宝贵的搜索引擎优化。

Transparent text cut out of background

我首先想到阴影,但我无法想出任何事情......

图片是网站背景,绝对定位<img>标记

14 个答案:

答案 0 :(得分:45)

尽管CSS可以实现这一点,但更好的方法是使用inline SVGSVG masking。这种方法比CSS有一些优势:

CodePen演示:SVG text mask

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>

如果您的目标是使文本可选择和可搜索,则需要将其包含在<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>

答案 1 :(得分:44)

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

使用background-clip:text;您可以使用背景作为文本,但您必须将其与页面背景对齐

&#13;
&#13;
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;
}
&#13;
<h1><span>ABCDEFGHIKJ</span></h1>
&#13;
&#13;
&#13;

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

自动对齐

使用一些小的javascript,您可以自动对齐背景:

&#13;
&#13;
$(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"); 
});
&#13;
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;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1><span>ABCDEFGHIKJ</span></h1>
&#13;
&#13;
&#13; http://jsfiddle.net/JGPuZ/1336/

答案 2 :(得分:16)

一种适用于大多数现代浏览器的方法(除了边缘),虽然只有黑色背景,但是要使用

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

在你的文本元素中然后放置你想要的任何背景。乘法基本上将0-255颜色代码映射到0-1,然后将其与背后的任何颜色相乘,因此黑色和黑色保持乘以1并且实际上变为透明。 http://codepen.io/nic_klaassen/full/adKqWX/

答案 3 :(得分:3)

是可能的,但到目前为止只能使用基于Webkit的浏览器(Chrome,Safari,Rockmelt,基于Chromium项目的任何内容)。

诀窍是在白色中有一个与主体具有相同背景的元素,然后在内部元素上使用-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/

答案 4 :(得分:2)

我想你可以实现类似using background-clip的东西,但我还没有测试过。

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

答案 5 :(得分:1)

您可以使用myadzel的Patternizer jQuery插件来跨浏览器实现此效果。目前,没有跨浏览器的方式只使用CSS。

通过将class="background-clip"添加到要将文本绘制为图像模式的HTML元素,并使用其他data-pattern="…"属性指定图像,可以使用模式器。查看demo的来源。 Patternizer将创建一个带有图案填充文本的SVG图像,并将其置于透明呈现的HTML元素中。

如果在问题的示例图像中,文本填充图案应该是延伸到&#34;图案化&#34;之外的背景图像的一部分。我看到两个选项(未经测试,我最喜欢的第一个):

  • 在SVG中使用屏蔽而不是背景图像。web-tiki's answer中一样,使用Patternizer仍然会添加自动生成SVG和顶部不可见的HTML元素文本选择和复制。
  • 或使用模式图像的自动对齐。可以使用与Gijs's answer中类似的JavaScript代码完成。

答案 6 :(得分:1)

您可以使用倒置/负片/反面字体并将其应用于font-face="…" CSS规则。您可能需要使用字母间距来避免字母之间出现小的白色间隙。

如果您不需要特定的字体,那很简单。下载一个可爱的,例如从collection of inverted fonts

如果您需要特定字体(例如,&#34; Open Sans&#34;),那就太难了。您必须将现有字体转换为反转版本。这可以通过Font Creator,FontForge等手动完成,但当然我们需要一个自动化解决方案。我还没有找到相关说明,但有些提示:

答案 7 :(得分:1)

Demo Screenshot

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

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;
}

将它扔到你的window.onload中,将身体的背景设置为你的图像,并观察魔法的发生!

答案 8 :(得分:1)

我刚刚发现了一种新的方法来解决这个问题,我不完全确定它是如何工作的(如果其他人想解释请做)。

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

这里是代码: JSFIDDLE

&#13;
&#13;
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;
}
&#13;
<div></div>
&#13;
&#13;
&#13;

答案 9 :(得分:1)

在不久的将来,我们可以使用element()来实现这一目标

element()函数允许作者使用文档中的元素作为图像。当引用的元素更改外观时,图像也会更改 ref

诀窍是创建带有文本的普通div,然后将element()mask结合使用。

这是一个基本示例,目前仅适用于最新版本的Firefox。

#text {
  font-size:35px;
  font-weight:bold;
  color:#000;
  font-family:sans-serif;
  text-transform: uppercase;
  white-space:nowrap;
  /* we hide it */ 
  position:fixed;
  right:200vw;
  bottom:200vh
}


body {
  background:url(https://picsum.photos/id/1018/800/800) center/cover; 
}

.main {
  margin:50px;
  height:100px;
  background:red;
  -webkit-mask:
    -moz-element(#text) center/contain no-repeat, /* this behave like a background-image*/
    linear-gradient(#fff 0 0);
  mask-composite:exclude;
}
<div id="text">
You can put your text here
</div>

<div class="main">

</div>

它将产生以下内容:

CSS transparent text over background image

这是响应性的,因为我们依靠基本的背景属性,并且可以使用基本CSS轻松更新文本。

我们可以考虑任何种类的内容并创建模式:

#text {
  font-size:30px;
  font-weight:bold;
  color:#000;
  font-family:sans-serif;
  text-transform: uppercase;
  white-space:nowrap;
  padding:20px;
  /* we hide it */ 
  position:fixed;
  right:200vw;
  bottom:200vh
}
#text span {
  font-family:cursive;
  font-size:35px;
}


body {
  background:url(https://picsum.photos/id/1018/800/800) center/cover; 
}

.main {
  margin:50px;
  height:100px;
  background:red;
  -webkit-mask:
    -moz-element(#text) 0 0/20% auto, /* this behave like a background-image*/
    linear-gradient(#fff 0 0);
  mask-composite:exclude;
}
<div id="text">
Your <span>text</span> here ?
</div>

<div class="main">

</div>

CSS text mask over background

为什么不使用某些动画来创建无限滚动文本:

#text {
  font-size:30px;
  font-weight:bold;
  color:#000;
  font-family:sans-serif;
  text-transform: uppercase;
  white-space:nowrap;
  padding:20px 5px;
  /* we hide it */ 
  position:fixed;
  right:200vw;
  bottom:200vh
}


body {
  background:url(https://picsum.photos/id/1018/800/800) center/cover; 
}

.main {
  margin:50px;
  height:100px;
  padding-right:calc(50% - 50px);
  background:red;
  -webkit-mask:
    -moz-element(#text) 0 50%/200% auto content-box, /* this behave like a background-image*/
    linear-gradient(#fff 0 0);
  mask-composite:exclude;
  animation:m 5s linear infinite;
}

@keyframes m{
  to {-webkit-mask-position:200% 50%}
}
<div id="text">
Srolling repeating text here 
</div>

<div class="main">

</div>

animated text using CSS mask

答案 10 :(得分:0)

目前我不敢使用CSS。

最好的办法是简单地使用一张图片(可能是PNG)并在上面放置好的替代/标题文字。

或者您可以使用SPAN或DIV,并将图像作为背景,并将其与您想要的文本一起放入其中,但在屏幕上将文本缩进。

答案 11 :(得分:0)

只是把那个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;

    }

答案 12 :(得分:0)

mix-blend-mode也可能会产生这种效果。

mix-blend-mode CSS属性设置元素的内容应如何与元素的父级内容和元素的背景融合。

h1 {
background:white;
mix-blend-mode:screen;

/* demo purpose from here */
padding:0.25em;
mix-blend-mode:screen;
}


html {
background:url(https://i.picsum.photos/id/1069/367/267.jpg?hmac=w5sk7UQ6HGlaOVQ494mSfIe902cxlel1BfGUBpEYoRw)center / cover ;
min-height:100vh;
display:flex;
}
body {margin:auto;}
h1:hover {border:dashed 10px white;background-clip:content-box;box-shadow:inset 0 0 0 2px #fff, 0 0 0 2px #fff}
<h1>ABCDEFGHIJKLMNOPQRSTUVWXYZ</h1>

答案 13 :(得分:0)

这对我mix-blend-mode: color-dodge 对颜色相反的容器有用。

.main{
 background: url('https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__340.jpg');
 height: 80vh;
 width: 100vw;
 padding: 40px;
}

.container{
   background-color: white;
   width: 80%;
   height: 50px;
   padding: 40px;
   font-size: 3em;
   font-weight: 600;
   mix-blend-mode: color-dodge;
}

.container span{
  color: black;
}
<div class="main">
<div class="container">
<span>This is my text</span>
</div>
</div>