Texte transparent découpé en arrière-plan

90

Existe-t-il un moyen de faire un texte transparent coupé d'un effet d' arrière-plan comme celui de l'image suivante, avec CSS?
Il serait triste de perdre tout précieux SEO à cause des images remplaçant le texte.

Texte transparent découpé en arrière-plan

J'ai d'abord pensé aux ombres mais je ne peux rien comprendre ...

L'image est l'arrière-plan du site, une <img>balise positionnée en absolu

Amour Dager
la source
"perdez tout précieux SEO à cause des images remplaçant le texte." Il existe également des techniques de remplacement d'image, qui sont toujours aussi conviviales. BTW: en fait, l'arrière-plan derrière les lettres doit également rester transparent, ce qui est le problème ici…
feeela
oui, ce serait une bonne pratique, si possible avec css ...
Jessica Lingmn
Je ne vois aucune raison pour laquelle le <h1><img alt="Some Text" /></h1>référencement est moins convivial que <h1>Some Text</h1>. Traditionnellement, le problème avec les images était qu'elles venaient d'être vidées sur la page sans balisage de prise en charge.
cimmanon
@cimmanon Ouais, tu as raison. Je pourrais probablement utiliser des images sans perdre de points de référencement, mais vous ne pouvez toujours pas sélectionner du texte, rechercher sur la page, les liens seront plus compliqués, et il faudra beaucoup plus de travail pour mettre à jour le texte ...: /
Love Dager
2
Juste pour que vous le sachiez, Google est totalement cool avec les techniques de remplacement d'image CSS: mezzoblue.com/archives/2008/05/05/image_replac
cimmanon

Réponses:

46

C'est possible avec css3 mais ce n'est pas pris en charge dans tous les navigateurs

Avec background-clip: texte; vous pouvez utiliser un arrière-plan pour le texte, mais vous devrez l'aligner avec l'arrière-plan de la 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/


Alignement automatique

Avec un peu de javascript, vous pouvez aligner l'arrière-plan automatiquement:

$(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/

Gijs
la source
A vous les gens sont TROP vite: D
Gijs
Oh génial! Je testerai l'alignement automatique dès mon retour à la maison! Je vous remercie! : D
Love Dager
vous devez modifier un peu le code, cela dépend de la situation, maintenant cela pourrait entrer en conflit avec d'autres éléments et celui-ci a été écrit très rapidement, si vous avez des questions, je les entendrai
Gijs
3
Ne pas ignorer la réponse, qui est une très bonne solution, mais background-clip:textc'est une option non standard uniquement Webkit. CSS3 n'autorise pas la textvaleur de cet attribut ( voir ).
tanius
1
Cette technique vous permet de voir l'arrière-plan de l'élément où le texte se trouverait normalement. Je cherche un moyen de voir ce qu'il y a sous l'élément avec le texte à l'endroit où le texte se trouverait normalement.
Vince
49

Bien que cela soit possible avec CSS, une meilleure approche serait d'utiliser un SVG en ligne avec un masquage SVG . Cette approche présente certains avantages par rapport au CSS:

  • Une meilleure prise en charge des navigateurs : IE10 +, chrome, Firefox, safari ...
  • Cela n'a pas d'impact sur le référencement car les araignées peuvent explorer le contenu SVG ( google indexe le contenu SVG depuis 2010 )

Démo CodePen: masque de texte SVG

fond de détourage de texte transparent

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 vous souhaitez rendre le texte sélectionnable et consultable, vous devez l'inclure en dehors de la <defs>balise. L'exemple suivant montre un moyen de le faire en conservant le texte transparent avec la <use>balise:

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>

web-tiki
la source
2
Cela semble être la seule solution qui fonctionne aujourd'hui sur plusieurs navigateurs: IE11, FF, Chrome, Safari. Et n'a pas besoin d'image comme arrière-plan comme de nombreuses autres solutions fournies au problème partout sur le Web.
Timo Kähkönen
1
Inspiré de cette réponse, j'ai créé une animation d'images clés, dans laquelle le texte SVG transparent sur un rectangle arrondi blanc tourne. L'arrière-plan contient du texte et des images. Allez voir: jsbin.com/nipuqu/3 (Le championnat du monde arrive :))
Timo Kähkönen
2
Belle solution, mais comme "sélectionner du texte et rechercher sur la page" semble être dans les exigences d'OP, vous voudrez peut-être inclure l' <text>extérieur de la <defs>pièce. (btw je ne sais pas comment les robots SE traitent le contenu SVG dans defs). Voici un moyen de garder ce que OP veut, avec un horrible exploit de bug FF: jsfiddle.net/tfneqxxb
Kaiido
Et si le texte est dynamique? Il ne dose pas automatiquement la largeur.
Imran Bughio
1
@ImranBughio non, ce n'est pas le cas. Le texte SVG n'agit pas comme du texte HTML brut. Vous devez le positionner. Pour plus d'informations, voir ici
web-tiki
16

Une façon qui fonctionne sur la plupart des navigateurs modernes (à l'exception du bord par exemple), bien qu'avec un arrière-plan noir, consiste à utiliser

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

dans votre élément de texte, puis mettez l'arrière-plan de votre choix. Multiplier mappe essentiellement le code de couleur 0-255 à 0-1, puis multiplie cela par tout ce qui se trouve derrière, de sorte que le noir reste noir et blanc multiplié par 1 et devient effectivement transparent. http://codepen.io/nic_klaassen/full/adKqWX/

Nic
la source
3
Pour fond blanc avec une couleur noire color-dodge, lightenou screensurmix-blend-mode
Imran Bughio
3

Il est possible, mais jusqu'à présent uniquement avec les navigateurs basés sur Webkit (Chrome, Safari, Rockmelt, quoi que ce soit sur la base du projet Chromium.)

L'astuce est d'avoir un élément dans le blanc qui a le même arrière-plan que le corps, puis de l'utiliser -webkit- background-clip: text;sur l'élément intérieur qui signifie essentiellement "ne pas étendre l'arrière-plan au-delà du texte" et d'utiliser du texte transparent.

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/

Kyle
la source
Cool truc! Mais maintenant, tout aligner correctement sera une salope .. -.-
Love Dager
Ouais, c'est un autre problème avec ça. Il est toujours en développement et j'espère sincèrement que nous verrons bientôt quelque chose comme ça! :)
Kyle
En outre, vous pouvez toujours superposer du texte transparent sur l'image, afin qu'il soit toujours sélectionnable. Mais je suis sûr que c'est une mauvaise pratique pour le référencement .. Messages / mots-clés cachés et autres.
Kyle
Je suis sûr que cela a l'air très bien dans les navigateurs Webkit, mais pour tout le monde, c'est une boîte blanche semi-transparente au-dessus de l'herbe.
cimmanon
1
Ah, allez les gars ... Oui, je prévois de l'utiliser en production. Mais bien sûr pas sans repli! @cimmanon
Love Dager
2

Je viens de découvrir une nouvelle façon de faire cela tout en déconnant, je ne suis pas tout à fait sûr de savoir comment cela fonctionne (si quelqu'un d'autre veut expliquer, faites-le).

Cela semble très bien fonctionner et ne nécessite aucun double arrière-plan ni JavaScript.

Voici le code: 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>

ChrisBrownie55
la source
1

Vous pouvez utiliser une police inversée / négative / inversée et l'appliquer avec la font-face="…"règle CSS. Vous devrez peut-être jouer avec l'espacement des lettres pour éviter les petits espaces blancs entre les lettres.

Si vous n'avez pas besoin d'une police spécifique, c'est simple. Téléchargez-en un sympathique, par exemple à partir de cette collection de polices inversées .

Si vous avez besoin d'une police spécifique (par exemple, "Open Sans"), c'est difficile. Vous devez convertir votre police existante en une version inversée. Ceci est possible manuellement avec Font Creator, FontForge etc., mais nous voulons bien sûr une solution automatisée. Je n'ai pas encore trouvé d'instructions pour cela, mais quelques conseils:

Tanius
la source
1

Vous pouvez utiliser de myadzel Patternizer plugin jQuery pour obtenir cet effet à travers les navigateurs. Pour le moment, il n'y a pas de moyen multi-navigateurs de le faire avec seulement CSS.

Vous utilisez Patternizer en ajoutant class="background-clip"aux éléments HTML où vous souhaitez que le texte soit peint en tant que modèle d'image et en spécifiant l'image dans un data-pattern="…"attribut supplémentaire . Voir la source de la démo . Patternizer créera une image SVG avec du texte rempli de motifs et la calera sur l'élément HTML rendu de manière transparente.

Si, comme dans l'image d'exemple de la question, le motif de remplissage de texte doit faire partie d'une image d'arrière-plan s'étendant au-delà de l'élément "à motifs", je vois deux options (non testées, ma préférée en premier):

  • Utilisez le masquage au lieu d'une image d'arrière-plan dans le SVG. Comme dans la réponse de web-tiki , à laquelle l'utilisation de Patternizer ajoutera toujours la génération automatique du SVG et un élément HTML invisible en haut qui permet la sélection et la copie de texte.
  • Ou utilisez l'alignement automatique de l'image du motif. Peut être fait avec un code JavaScript similaire à celui de la réponse de Gijs .
Tanius
la source
1

il suffit de mettre ce 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;

    }
Rashed
la source
1

Capture d'écran de démonstration

J'avais besoin de créer un texte qui ressemblait exactement à celui de l'article original, mais je ne pouvais pas simplement le simuler en alignant les arrière-plans, car il y a une certaine animation derrière l'élément. Personne ne semble encore avoir suggéré cela, alors voici ce que j'ai fait: (J'ai essayé de le rendre aussi facile à lire que 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;
}

Jetez-le simplement dans votre window.onload, réglez l'arrière-plan du corps à votre image et regardez la magie opérer!

Pecacheu
la source
0

Pas possible avec CSS pour le moment j'en ai peur.

Votre meilleur pari est simplement d'utiliser une image (probablement un PNG) et de placer un bon texte de remplacement / titre dessus.

Alternativement, vous pouvez utiliser un SPAN ou un DIV et avoir l'image comme arrière-plan avec votre texte que vous souhaitez à des fins de référencement à l'intérieur, mais le mettre en retrait hors de l'écran.

Billy Moat
la source
Oui vous avez raison. Je pourrais probablement utiliser des images sans perdre de points de référencement, mais vous ne pouvez toujours pas sélectionner du texte, rechercher sur la page, les liens seront plus compliqués, et il faudra beaucoup plus de travail pour mettre à jour le texte ...: /
Love Dager
0

mix-blend-mode est également une possibilité pour ce genre d'effet.

La mix-blend-modepropriété CSS définit comment le contenu d'un élément doit se fondre avec le contenu du parent de l'élément et l'arrière-plan de l'élément.

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>

G-Cyrillus
la source