Existe uma maneira de usar texto como plano de fundo com CSS?

90

Eu gostaria de usar texto dinâmico como plano de fundo de certos elementos na minha tag. Por isso, posso usar imagens (texto dinâmico). Como faço isso apenas com CSS ou JavaScript?

chustar
fonte

Respostas:

81

Você pode ter um elemento posicionado absolutamente dentro de seu elemento posicionado relativo:

<div id="container">
    <div id="background">
    Text to have as background
    </div>
    Normal contents
</div>

E então o CSS:

#container {
   position: relative;
}

#background {
   position: absolute;
   top: 0;
   left: 0;
   bottom: 0;
   right: 0;
   z-index: -1;
   overflow: hidden;
}

Aqui está um exemplo disso .

Paolo Bergantino
fonte
144

Imagem de fundo de texto SVG

body {
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='50px' width='120px'><text x='0' y='15' fill='red' font-size='20'>I love SVG!</text></svg>");
}
<p>I hate SVG!</p><p>I hate SVG!</p><p>I hate SVG!</p><p>I hate SVG!</p>
<p>I hate SVG!</p><p>I hate SVG!</p><p>I hate SVG!</p><p>I hate SVG!</p>

Aqui está uma versão recuada do CSS para que você possa entender melhor. Observe que isso não funciona , você precisa usar o single liner SVG do snippet acima:

body {
  background-image:url("data:image/svg+xml;utf8,
  <svg xmlns='http://www.w3.org/2000/svg' version='1.1'
       height='50px' width='120px'>
    <text x='0' y='15' fill='red' font-size='20'>I love SVG!</text>
  </svg>");
}

Não tenho certeza de quão portátil isso é (funciona no Firefox 31 e Chrome 36), e é tecnicamente uma imagem ... mas a fonte é inline e texto simples, e pode ser dimensionada infinitamente.

@senectus descobriu que funciona melhor no IE se você codificá-lo em base64: https://stackoverflow.com/a/25593531/895245

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fonte
Interessante. Eu só consegui fazer isso funcionar no Firefox 31, mas não no Chrome 36 ou Safari 7.
JP Richardson
@JPRichardson True, mesmo aqui. No Chrome 36 Tenho a impressão de que o fundo está lá, mas em muito pequenas letras. Talvez eu esteja esquecendo de definir algum parâmetro de tamanho de fundo / SVG?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Sim, estou experimentando com ele no momento ... parece talvez "viewBox"? Eu ainda estou brincando com isso.
JP Richardson
1
Ciro: com base na sua resposta, consegui juntar tudo ... funcionou muito bem! Obrigado! codepen.io/jprichardson/pen/GnxKr
JP Richardson
2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功 ótima resposta! Você tem alguma ideia sobre como melhorar a renderização no Chrome? Parece muito ruim lá. Agradecemos antecipadamente
Alejandro García Iglesias
46

Pode ser possível (mas muito hackeado) apenas com CSS usando os pseudo elementos: before ou: after:

.bgtext {
  position: relative;
}

.bgtext:after {
  content: "Background text";
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
}
<div class="bgtext">
  Foreground text
</div>

Isso parece funcionar, mas você provavelmente precisará ajustá-lo um pouco. Observe também que ele não funcionará no IE6 porque não oferece suporte :after.

DisgruntledGoat
fonte
Atualização: por enquanto, todos os navegadores modernos suportam pseudoelementos. Por exemplo, é assim que FontAwesome funciona para ícones CSS (usando: before on inline elements).
Cédric Françoys
21

A solução de Ciro sobre um fundo de URI de dados SVG contendo o texto é muito inteligente.

No entanto, não funcionará no IE se você apenas adicionar a fonte SVG simples ao URI de dados.

Para contornar isso e fazê-lo funcionar no IE9 e superior, codifique o SVG para base64. Essa é uma ótima ferramenta.

Então, é isso:

background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><text x="5%" y="5%" font-size="30" fill="red">I love SVG!</text></svg>');

Torna-se isto:

background:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjx0ZXh0IHg9IjUlIiB5PSI1JSIgZm9udC1zaXplPSIzMCIgZmlsbD0icmVkIj5JIGxvdmUgU1ZHITwvdGV4dD48L3N2Zz4=');

Testado e funciona em IE9-10-11, WebKit (Chrome 37, Opera 23) e Gecko (Firefox 31).

http://jsfiddle.net/qapp5dLn/

senectus
fonte
1
Esta é uma ferramenta melhor: jpillora.com/base64-encoder simpile, sem erros, preenchimento automático, visualização de imagem. Sim, é melhor aos trancos e barrancos.
Jack Giffin de
9

@Ciro

Você pode quebrar o código SVG embutido com uma barra invertida "\"

Testado com o código abaixo no Chrome 54 e Firefox 50

body {
    background: transparent;
    background-attachment:fixed;
    background-image: url(
    "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='170px' height='50px'> \
    <rect x='0' y='0' width='170' height='50' style='stroke:white; fill:gray; stroke-opacity: 0.3; stroke-width: 3px; fill-opacity: 0.7; stroke-dasharray: 10 5; stroke-linecap=round; '/> \
    <text x='85' y='30' style='fill:lightBlue; text-anchor: middle' font-size='16' transform='rotate(10,85,25)'>I love SVG!</text></svg>");
}

Eu até testei isso,

background-image: url("\
data:image/svg+xml;utf8, \
  <svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='170px' height='50px'> \
    <rect x='0' y='0' width='170' height='50'\
      style='stroke:white; stroke-width: 3px; stroke-opacity: 0.3; \
             stroke-dasharray: 10 5; stroke-linecap=round; \
             fill:gray;  fill-opacity: 0.7; '/> \
    <text x='85' y='30' \
      style='fill:lightBlue; text-anchor: middle' font-size='16' \
      transform='rotate(10,85,25)'> \
      I love SVG! \
    </text> \
  </svg>\
");

e funciona (pelo menos no Chrome 54 e Firefox 50 ==> uso em NWjs e Electron garantido)

Athmailer
fonte
5

Usando CSS puro:

(Mas use isso em raras ocasiões, porque o método HTML é a MANEIRA PREFERIDA ).

.container{
	position:relative;
}
.container::before{ 
	content:"";
	width: 100%; height: 100%; position: absolute; background: black; opacity: 0.3; z-index: 1;  top: 0;   left: 0;
	background: black;
}
.container::after{ 
	content: "Your Text"; position: absolute; top: 0; left: 0; bottom: 0; right: 0; z-index: 3; overflow: hidden; font-size: 2em; color: red;    text-align: center; text-shadow: 0px 0px 5px black; background: #0a0a0a8c; padding: 5px;
	animation-name: blinking;
	animation-duration: 1s;
	animation-iteration-count: infinite;
	animation-direction: alternate;
}
@keyframes blinking {
	0% {opacity: 0;}
	100% {opacity: 1;}
}
<div class="container">here is main content, text , <br/> images and other page details</div>

T.Todua
fonte
2

Você pode fazer com que o elemento que contém o texto bg tenha uma ordem de empilhamento inferior (índice z, posição) e possivelmente até mesmo defina a opacidade. Portanto, o elemento que você precisa no topo precisaria de uma ordem de empilhamento maior (índice z: 5; posição: relativo; por exemplo) e o elemento atrás precisaria de algo menor (padrão ou apenas um índice z menor como 3 e posição: relativo ;).

Meder Omuraliev
fonte