web-dev-qa-db-fra.com

Texte transparent coupé en arrière-plan

Existe-t-il un moyen de créer un texte transparent découpé dans un effet d’arrière-plan comme celui de l’image suivante, avec CSS?
Il serait triste de perdre tout précieux référencement en raison du remplacement du texte par des images.

Transparent text cut out of background

J'ai d'abord pensé aux ombres mais je n'arrive pas à comprendre quoi que ce soit ... 

L'image est l'arrière-plan du site, une balise <img> positionnée de manière absolue. 

77
Love Dager

C'est possible avec css3 mais ce n'est pas supporté par tous les navigateurs

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

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

43
Gijs

Bien que cela soit possible avec CSS, une meilleure approche consisterait à utiliser un masquage SVG inline with SVG masking . Cette approche présente certains avantages par rapport à CSS:

  • Beaucoup de meilleur support du navigateur: IE10 +, chrome, Firefox, safari ...
  • Cela n'a pas d'incidence sur le référencement, car les spiders peuvent analyser le contenu SVG ( Google indexe le contenu SVG depuis 2010 )

Démo CodePen: Masque de texte 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>

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

45
web-tiki

Une façon qui fonctionne sur la plupart des navigateurs modernes (sauf Edge), bien que seulement avec un fond noir, consiste à utiliser

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

dans votre élément de texte et mettez ensuite l’arrière-plan de votre choix. Multiply fait essentiellement correspondre le code de couleur 0-255 à 0-1, puis multiplie ce qui est derrière, ainsi le noir reste noir et blanc multiplié par 1 et devient effectivement transparent . http://codepen.io/ nic_klaassen/full/adKqWX/

16
Nic

Cela est possible, mais uniquement avec les navigateurs Webkit (Chrome, Safari, Rockmelt, tout ce qui est basé sur le projet Chromium.)

L'astuce consiste à avoir un élément dans l'élément blanc qui a le même arrière-plan que le corps, puis utilisez -webkit- background-clip: text; sur l'élément interne, ce qui signifie fondamentalement "ne prolongez pas l'arrière-plan au-delà du texte" et utilisez 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/

3
Kyle

Je suppose que vous pourriez obtenir quelque chose comme ça en utilisant background-clip , mais je ne l’ai pas encore testé. 

Voir cet exemple:
http://www.css3.info/wp-content/uploads/2008/03/webkit-backgroundcliptext_color.html
(Webkit uniquement, je ne sais pas encore comment changer le fond noir en blanc)

2
feeela

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

Il semble fonctionner très bien et ne nécessite pas de double arrière-plan ou 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>

1
chbchb55

 Demo Screenshot

Je devais créer un texte qui ressemblait exactement à celui du message d'origine, mais je ne pouvais pas simplement le simuler en alignant des arrière-plans, car il y avait une animation derrière l'élément. Personne ne semble l'avoir suggéré encore, 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;
}

Il suffit de jeter cela dans le chargement de votre fenêtre, de définir le fond du corps à votre image et de regarder la magie se produire!

1
Pecacheu

Vous pouvez utiliser une police inversée/négative/inverse et l'appliquer à l'aide de la règle CSS font-face="…". 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 un fichier 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 souhaitons bien sûr une solution automatisée. Je n'ai pas encore trouvé d'instructions à ce sujet, mais quelques astuces:

1
tanius

Vous pouvez utiliser Patternizer jQuery plugin de myadzel pour obtenir cet effet sur tous les navigateurs. À l'heure actuelle, il n'y a pas de moyen de navigation croisée entre les navigateurs pour le faire uniquement avec CSS.

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

Si, comme dans l'exemple d'image 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 "modelé", je vois deux options (non testé, mon préféré en premier):

  • Utilisez le masquage à la place d'une image d'arrière-plan dans le SVG. Comme dans la réponse de web-tiki , à laquelle l'utilisation de Patternizer ajoutera encore la génération automatique du fichier SVG et un élément HTML invisible permettant 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 Réponse de Gijs .
1
tanius

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;

    }
0
Rashed

Pas possible avec CSS tout à l'heure, j'ai bien peur.

Votre meilleur choix est simplement d’utiliser une image (probablement un fichier PNG) et d’y placer un bon texte alt/titre.

Sinon, vous pouvez utiliser un SPAN ou un DIV et avoir l’image en arrière-plan avec le texte que vous voulez, à des fins de référencement, mais en la mettant en retrait à l’écran.

0
Billy Moat