Texto transparente recortado del fondo


¿Hay alguna manera de hacer un texto transparente recortado de un efecto de fondo como el de la siguiente imagen, con CSS?
Sería triste perder todo el valioso SEO debido a que las imágenes reemplazan el texto.

Texto transparente recortado del fondo

Primero pensé en las sombras, pero no puedo entender nada...

La imagen es el fondo del sitio, una etiqueta de posición absoluta <img>

Author: web-tiki, 2012-12-18

11 answers

Es posible con css3 pero no es compatible con todos los navegadores

Con background-clip: text; puede usar un fondo para el texto, pero tendrá que alinearlo con el fondo de la página

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 /

Alineación Automática

Con un poco de javascript puede alinear el fondo automático:

$(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 /
 40
Author: Gijs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-03 06:56:08

Aunque esto es posible con CSS, un mejor enfoque sería usar un SVG inline con SVG masking. Este enfoque tiene algunas ventajas sobre CSS:

CodePen Demo: Texto SVG máscara

fondo de recorte de texto transparente

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>

Si su objetivo es hacer que el texto sea seleccionable y se pueda buscar, debe incluirlo fuera de la etiqueta <defs>. El siguiente ejemplo muestra una forma de hacerlo manteniendo el texto transparente con el <use> etiqueta:

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>
 43
Author: web-tiki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-14 12:28:50

Una forma que funciona en la mayoría de los navegadores modernos (excepto ie, edge), aunque solo con un fondo negro, es usar

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

En su elemento de texto y luego ponga el fondo que desee detrás de eso. Multiply básicamente asigna el código de color 0-255 a 0-1 y luego lo multiplica por lo que está detrás de él, por lo que el negro permanece negro y el blanco se multiplica por 1 y efectivamente se vuelve transparente. http://codepen.io/nic_klaassen/full/adKqWX /

 15
Author: Nic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-30 22:34:38

Es posible, pero hasta ahora solo con navegadores basados en Webkit (Chrome, Safari, Rockmelt, cualquier cosa basada en el proyecto Chromium.)

El truco es tener un elemento dentro del blanco que tenga el mismo fondo que el cuerpo, luego use -webkit- background-clip: text; en el elemento interno que básicamente significa "no extienda el fondo más allá del texto" y use texto transparente.

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 /

 3
Author: Kyle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-18 12:37:43

Supongo que podrías lograr algo así usando background-clip, pero aún no lo he probado.

Ver esto example:
http://www.css3.info/wp-content/uploads/2008/03/webkit-backgroundcliptext_color.html
(Solo Webkit, todavía no se como cambiar el fondo negro por uno blanco)

 2
Author: feeela,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-18 12:37:08

Puede usar una fuente invertida / negativa / inversa y aplicarla con la regla CSS font-face="…". Es posible que tenga que jugar con el espacio entre letras para evitar pequeños espacios blancos entre las letras.

Si no necesita una fuente específica, es simple. Descargue una simpática, por ejemplo, de esta colección de fuentes invertidas.

Si necesita una fuente específica (por ejemplo, "Open Sans"), es difícil. Tienes que convertir tu fuente existente en una versión invertida. Esto es posible manualmente con Font Creator, FontForge, etc., pero por supuesto queremos una solución automatizada. No pude encontrar instrucciones para eso todavía, pero algunas pistas:

 1
Author: tanius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:48

Puede usar el plugin de myadzel Patternizer jQuery para lograr este efecto en todos los navegadores. En este momento, no hay una forma cruzada de hacer esto con solo CSS.

Utiliza Patternizer añadiendo class="background-clip" a los elementos HTML en los que desea que el texto se pinte como un patrón de imagen, y especifique la imagen en un atributo adicional data-pattern="…". Vea la fuente de la demo . Patternizer creará una imagen SVG con texto lleno de patrón y lo subyace a la elemento HTML renderizado de forma transparente.

Si, como en la imagen de ejemplo de la pregunta, el patrón de relleno de texto debe ser una parte de una imagen de fondo que se extiende más allá del elemento "patternized", veo dos opciones (sin probar, mi favorita primero):

  • Utilice enmascaramiento en lugar de una imagen de fondo en el SVG. Como en la respuesta de web-tiki , a la que usando Patternizer todavía agregará la generación automática del SVG y un elemento HTML invisible en la parte superior que permite el texto selección y copia.
  • O utilice la alineación automática de la imagen del patrón. Se puede hacer con código JavaScript similar al de La respuesta de Gijs.
 1
Author: tanius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:35

Captura de Pantalla de Demostración

Necesitaba hacer un texto que se viera exactamente como lo hace en el post original, pero no podía simplemente fingirlo alineando fondos, porque hay algo de animación detrás del elemento. Nadie parece haber sugerido esto todavía, así que esto es lo que hice: (Traté de hacerlo lo más fácil de leer posible.)

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

Simplemente tira eso en tu ventana.onload, establecer el fondo del cuerpo a su imagen, y ver la magia suceder!

 1
Author: Pecacheu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-23 02:19:57

No es posible con CSS ahora mismo, me temo.

Lo mejor es simplemente usar una imagen (probablemente un PNG) y colocar un buen texto alt/título en ella.

Alternativamente, podría usar un SPAN o un DIV y tener la imagen como fondo con el texto que desea para fines de SEO dentro de ella, pero el texto-sangría fuera de la pantalla.

 0
Author: Billy Moat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-18 12:27:11

Solo pon ese 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;

    }
 0
Author: Rashed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-22 06:29:32

Acabo de descubrir una nueva forma de hacer esto mientras bromeo, no estoy del todo seguro de cómo funciona ( si alguien más quiere explicar, por favor ).

Parece funcionar muy bien, y no requiere fondos dobles o JavaScript.

Aquí está el código: 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>
 0
Author: chbchb55,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-10 06:30:44