Texto transparente recortado de fondo


90

¿Hay alguna forma 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 precioso SEO debido a que las imágenes reemplazan al texto.

Texto transparente recortado de fondo

Primero pensé en las sombras pero no puedo descifrar nada ...

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


"Pierde todo el precioso SEO debido a que las imágenes reemplazan al texto". También existen técnicas de reemplazo de imágenes que aún son TAN amigables. Por cierto: en realidad, el fondo detrás de las letras también debe permanecer transparente, que es el problema aquí…
feeela

sí, esto sería una gran práctica, si es posible con css ...
Jessica Lingmn

No veo una razón por la que <h1><img alt="Some Text" /></h1>sea ​​menos amigable con el SEO que <h1>Some Text</h1>. Tradicionalmente, el problema con las imágenes ha sido que se han descargado en la página sin un marcado de apoyo.
cimmanon

@cimmanon Sí, tienes razón. Probablemente podría usar imágenes sin perder puntos de SEO, pero aún no puede seleccionar texto, buscar en la página, vincular será más complicado y será mucho más trabajo actualizar el texto ...: /
Love Dager

2
Para que lo sepas, Google es totalmente genial con las técnicas de reemplazo de imágenes CSS: mezzoblue.com/archives/2008/05/05/image_replac
cimmanon

Respuestas:


46

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

Con clip de fondo: texto; 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 puedes alinear el fondo automáticamente:

$(document).ready(function(){
  //Position of the header in the webpage
  var position = $("h1").position();
  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/


A ustedes, la gente es DEMASIADO rápido: D
Gijs

¡Oh, genial! ¡Probaré la alineación automática tan pronto como llegue a casa! ¡Gracias! : D
Love Dager

es posible que necesite alterar un poco el código, depende de la situación, ahora podría entrar en conflicto con otros elementos y este se escribió muy rápido, si tiene alguna pregunta, la escucharé
Gijs

3
No ignorar la respuesta, que es una solución realmente agradable, pero background-clip:textes una opción no estándar, solo para Webkit. CSS3 no permite el textvalor de este atributo ( ver ).
tanius

1
Esta técnica le permite ver el fondo del elemento donde normalmente estaría el texto. Estoy buscando una manera de ver qué hay debajo del elemento con el texto a través del lugar donde normalmente estaría el texto.
Vince

49

Aunque esto es posible con CSS, un mejor enfoque sería utilizar un SVG en línea con enmascaramiento SVG . Este enfoque tiene algunas ventajas sobre CSS:

Demostración de CodePen: máscara de texto SVG

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 se pueda seleccionar y buscar, debe incluirlo fuera de la <defs>etiqueta. El siguiente ejemplo muestra una forma de hacerlo manteniendo el texto transparente con la <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>


2
Esta parece ser la única solución que funciona en todos los navegadores en la actualidad: IE11, FF, Chrome, Safari. Y no necesita una imagen como fondo como muchas otras soluciones proporcionadas al problema en toda la web.
Timo Kähkönen

1
Inspirado en esta respuesta, hice una animación de fotogramas clave, donde gira el texto SVG transparente en un rectángulo redondeado blanco. El fondo tiene texto e imágenes. Ve y mira: jsbin.com/nipuqu/3 (Se acerca el campeonato mundial :))
Timo Kähkönen

2
Buena solución, pero dado que "seleccionar texto y buscar en la página" parece estar en los requisitos de OP, es posible que desee incluir el <text>exterior de la <defs>pieza. (por cierto, no estoy seguro de cómo los rastreadores SE tratan el contenido SVG en defs). Aquí hay una manera de mantener lo que OP quiere, con un horrible exploit de error de FF: jsfiddle.net/tfneqxxb
Kaiido

¿Y si el texto es dinámico? No ajusta automáticamente el ancho.
Imran Bughio

1
@ImranBughio no, no lo hace. El texto SVG no actúa como texto HTML sin formato. Necesitas colocarlo. Para obtener más información, consulte aquí
web-tiki

16

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

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

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


3
Para fondo blanco con uso de color negro color-dodge, lighteno screenenmix-blend-mode
Imran Bughio

3

Que es posible, pero hasta ahora sólo con navegadores basados en Webkit (Chrome, Safari, RockMelt, todo basado en el proyecto Chromium.)

El truco es tener un elemento dentro del blanco que tenga el mismo fondo que el cuerpo, luego usarlo -webkit- background-clip: text;en el elemento interno que básicamente significa "no extender el fondo más allá del texto" y usar 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/


¡Buen truco! Pero ahora alinear todo correctamente será una perra .. -.-
Love Dager

Sí, ese es otro problema con eso. ¡Todavía está en desarrollo y espero sinceramente que veamos algo como esto pronto! :)
Kyle

Además, siempre puede superponer texto transparente en la imagen, de modo que aún sea seleccionable. Pero estoy seguro de que es una mala práctica para el SEO. Mensajes / palabras clave ocultas y demás.
Kyle

Estoy seguro de que se ve muy bien en los navegadores Webkit, pero para todos los demás es un cuadro blanco semitransparente encima de un césped.
cimmanon

1
Ah, vamos chicos ... Sí, planeo usarlo en producción. ¡Pero, por supuesto, no sin una alternativa! @cimmanon
Love Dager


2

Acabo de descubrir una nueva forma de hacer esto mientras jugaba, no estoy completamente seguro de cómo funciona (si alguien más quiere explicarlo, hágalo).

Parece funcionar muy bien y no requiere fondos dobles ni 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>


1

Puede utilizar una fuente invertida / negativa / inversa y aplicarla con elfont-face="…" regla CSS. Puede que tenga que jugar con el espaciado entre letras para evitar pequeños espacios en blanco entre las letras.

Si no necesita una fuente específica, es simple. Descarga una que te guste, 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. Todavía no pude encontrar instrucciones para eso, pero algunas sugerencias:


1

Puede utilizar el complemento jQuery Patternizer de myadzel para lograr este efecto en todos los navegadores. En este momento, no existe una forma de hacerlo en varios navegadores con solo CSS.

Use Patternizer agregando class="background-clip"elementos HTML donde desea que el texto se pinte como un patrón de imagen y especifique la imagen en un data-pattern="…"atributo adicional . Vea la fuente de la demostración . Patternizer creará una imagen SVG con texto relleno de patrón y la superpondrá al 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 parte de una imagen de fondo que se extienda más allá del elemento "modelado", 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 el uso de Patternizer aún agregará la generación automática del SVG y un elemento HTML invisible en la parte superior que permite la selección y copia de texto.
  • O utilice la alineación automática de la imagen del patrón. Se puede hacer con un código JavaScript similar al de la respuesta de Gijs .

1

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;

    }

1

Captura de pantalla de demostración

Necesitaba hacer un texto que se viera exactamente como en la publicación original, pero no podía simplemente fingir alineando los 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;
}

¡Solo tira eso en tu window.onload, configura el fondo del cuerpo a tu imagen y observa cómo sucede la magia!


0

No es posible con CSS en este momento, me temo.

Su mejor opción es simplemente usar una imagen (probablemente un PNG) y colocar un buen texto alternativo / título en ella.

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


Si, tienes razón. Probablemente podría usar imágenes sin perder puntos de SEO, pero aún no puede seleccionar texto, buscar en la página, vincular será más complicado y será mucho más trabajo actualizar el texto ...: /
Love Dager

0

mix-blend-mode también es una posibilidad para ese tipo de efecto.

La mix-blend-modepropiedad CSS establece cómo el contenido de un elemento debe combinarse con el contenido del elemento principal y el fondo del elemento.

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>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.