Existe uma maneira de usar SVG como conteúdo em um pseudo elemento: before or: after

246

Quero colocar algumas imagens SVG antes de alguns elementos selecionados. Estou usando jQuery, mas isso é irrelevante.

Eu gostaria de ter o :beforeelemento para ser como:

#mydiv:before {
  content: '<svg.. code here</svg>';
  display: block;
  width: 22px;
  height: 10px;
  margin: 10px 5px 0 10px;
}

Se eu fizer isso como mostrado acima, ele apenas exibirá a string. Verifiquei as especificações e parece haver algumas restrições quanto ao conteúdo. Existe uma solução alternativa para essa restrição? Somente o conteúdo css é relevante para minha pergunta.

Ensolarado
fonte
1
Há algo errado em usá-lo como imagem de fundo?
Cimmanon
1
Eu quero usá-lo para gerar ponteiros extravagantes para dicas de ferramentas da interface do usuário do JQuery. Faço isso agora com pseudo-elementos CSS hackear, mas isso me dá apenas triângulos. A imagem de plano de fundo não funcionará neste caso, pois preciso de algo que saia do elemento.
Sunny

Respostas:

252

Sim você pode! Apenas testei isso e funciona muito bem, isso é incrível! Ainda não funciona com html, mas com svg.

No meu index.html eu tenho:

<div id="test" style="content: url(test.svg); width: 200px; height: 200px;"></div>

E meu test.svg fica assim:

<svg xmlns="http://www.w3.org/2000/svg">
   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
   <polyline points="20,20 40,25 60,40 80,120 120,140 200,180" style="fill:none;stroke:black;stroke-width:3"/>
</svg> 
dezman
fonte
18
A menos que SVGs são especiais, você deve ser capaz de tratá-los da mesma forma que você faria com uma imagem: content: url(path/to/my.svg). Isso não significa necessariamente que funcionaria com a biblioteca de dicas de interface do usuário do jQuery.
Cimmanon 09/10/2013
1
@ cimmanon hmm, isso é doce, eu quero testar isso. Assim, em my.html ou o que quer que eu possa ter um monte de código html para renderizar ... parece incrível.
Dez13
2
Por que você quer fazer isso? Se você já possui o código svg no arquivo, não há necessidade de colocá-lo em uma pseudo-classe. O ponto principal das pseudo-classes é reduzir os elementos DOM quando você deseja adicionar um pouco de conteúdo, mas no seu caso, se você apenas usar seu código svg normalmente, não será pior (e provavelmente mais limpo) do que colocá-lo em um pseudo -class (que provavelmente também é impossível). A menos, é claro, se você deseja colocar seu código svg em vários locais, nesse caso, você deve apenas manter seu código svg em um arquivo separado, como uma imagem.
Dez13
6
infelizmente, não acredito que esta solução funcione com sprites SVG. por exemplo, content: url(mysprite.svg#my-icon)não exibirá seu ícone. Eu adoraria ser provado errado, no entanto :)
Jason
1
@ watson, semântico. O HTML = estrutura, CSS = apresentação. Se um SVG é decorativo, não deve estar na estrutura HTML, deve estar em CSS.
Deathlock
137

Sim. Você pode adicionar o SVG como imagem de fundo de um vazio: after ou: before. Aqui está:

.anchor:before {
  display: block;
  content: ' ';
  background-image: url('../images/anchor.svg');
  background-size: 28px 28px;
  height: 28px;
  width: 28px;
}
DerZyklop
fonte
4
Acho essa uma das melhores soluções, depois de um tempo. Você pode controlar todos os aspectos do elemento inserido e funciona da maneira normal como funciona as folhas de estilo CSS, com lógica separada. Grande
Danielo515
... ahh, isso aumentou minhas esperanças, até eu perceber que isso background-sizenão é suportado no Opera Mini. Isso é tão frustrante.
Deathlock
Trabalhou muito bem. @ deadlock, tamanho do plano de fundo não deve ser necessário, pois você está definindo as dimensões no próprio svg, eu não precisava disso.
Eric Soyke
1
Devem ser as respostas aceitas, já que a pergunta diz "em um pseudo-elemento: antes ou: depois"
ZalemCitizen
Eu tive que adicionar <?xml version="1.0" encoding="utf-8"?>ao início do meu arquivo svg para fazê-lo funcionar.
Nicolas Boisteault
130
#mydiv:before {
    content: url("data:image/svg+xml; utf8, <svg.. code here</svg>");
    display:block;
    width:22px;
    height:10px;
    margin:10px 5px 0 10px;
}

verifique se o seu svg não contém aspas duplas e uriencode quaisquer # símbolos.

Jenny
fonte
8
Como os SVGs costumam usar aspas duplas, você também pode usar aspas simples externas. A sugestão de @ Jenny é uma ótima maneira de fazer isso, se você não quiser usar um arquivo SVG externo.
Micros
2
Isso é ótimo. Infelizmente, ele só funciona com o Chrome para mim (testado no Chrome, Firefox e Edge).
Arsen
2
OK, funciona em FF. Só precisava prestar atenção na parte "não #". Certifique-se também de usar a tag div (parece não funcionar com extensão). Infelizmente ainda não houve sucesso para o Edge.
Arsenale #
Como muitas soluções brilhantes, ele não é suportado pelo IE11. url('file.svg')funciona no entanto.
Bob Stein
6
O que eu achei importante é adicionar xmlns='http://www.w3.org/2000/svg'a parte <svg> para funcionar no Chrome 66.x. Por exemplo - a pequena content:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24px' height='24px' fill='white'><path d='M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z' /></svg>");
divisa
28

Usar sprites CSS e uri de dados oferece benefícios interessantes adicionais, como carregamento rápido e menos solicitações E obtemos suporte para o IE8 usando image / base64:

Exemplo de Codepen usando SVG

HTML

<div class="div1"></div>
<div class="div2"></div>

CSS

.div1:after, .div2:after {
  content: '';
  display: block;
  height: 80px;
  width: 80px;
  background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20height%3D%2280%22%20width%3D%22160%22%3E%0D%0A%20%20%3Ccircle%20cx%3D%2240%22%20cy%3D%2240%22%20r%3D%2238%22%20stroke%3D%22black%22%20stroke-width%3D%221%22%20fill%3D%22red%22%20%2F%3E%0D%0A%20%20%3Ccircle%20cx%3D%22120%22%20cy%3D%2240%22%20r%3D%2238%22%20stroke%3D%22black%22%20stroke-width%3D%221%22%20fill%3D%22blue%22%20%2F%3E%0D%0A%3C%2Fsvg%3E);
}
.div2:after {
  background-position: -80px 0;
}

Para o IE8, mude para isso:

  background-image: url(data:image/png;base64,data......);
Um filho
fonte
Mas isso não é escalável, não é? Não consigo redimensioná-lo para 16 ou 320 pixels à vontade.
Deathlock
@deathlock É claro que ele escala, embora não seja minha amostra, pois possui um tamanho fixo definido, 80 px de largura / altura.
Ason
1
@deathlock Posso perguntar se você votou negativamente porque a amostra acima não foi dimensionada?
Ason
como você faria isso escalar? E não, eu não fiz.
Deathlock
Obrigado, e aqui está uma maneira de escalar svg: jsfiddle.net/ess6ywce ... usando porcentagem. Também, pesquise SO com scale svge você vai encontrar muitas outras maneiras
Ason
22
<div class="author_">Lord Byron</div>

.author_ {  font-family: 'Playfair Display', serif; font-size: 1.25em; font-weight: 700;letter-spacing: 0.25em; font-style: italic;
  position:relative;
  margin-top: -0.5em;
  color: black;
  z-index:1;
  overflow:hidden;
  text-align:center;
 
}


.author_:after{
   left:20px;
  margin:0 -100% 0 0;
  display: inline-block;
  height: 10px;
  content: url(data:image/svg+xml,%0A%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22120px%22%20height%3D%2220px%22%20viewBox%3D%220%200%201200%20200%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%0A%20%20%3Cpath%20stroke%3D%22black%22%20stroke-width%3D%223%22%20fill%3D%22none%22%20d%3D%22M1145%2085c17%2C7%208%2C24%20-4%2C29%20-12%2C4%20-40%2C6%20-48%2C-8%20-9%2C-15%209%2C-34%2026%2C-42%2017%2C-7%2045%2C-6%2062%2C2%2017%2C9%2019%2C18%2020%2C27%201%2C9%200%2C29%20-27%2C52%20-28%2C23%20-52%2C34%20-102%2C33%20-49%2C0%20-130%2C-31%20-185%2C-50%20-56%2C-18%20-74%2C-21%20-96%2C-23%20-22%2C-2%20-29%2C-2%20-56%2C7%20-27%2C8%20-44%2C17%20-44%2C17%20-13%2C5%20-15%2C7%20-40%2C16%20-25%2C9%20-69%2C14%20-120%2C11%20-51%2C-3%20-126%2C-23%20-181%2C-32%20-54%2C-9%20-105%2C-20%20-148%2C-23%20-42%2C-3%20-71%2C1%20-104%2C5%20-34%2C5%20-65%2C15%20-98%2C22%22%2F%3E%0A%3C%2Fsvg%3E%0A);
}
.author_:before {
  right:20px;
  margin:0 0 0 -100%;
  display: inline-block;
  height: 10px;
  content: url(data:image/svg+xml,%0A%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22120px%22%20height%3D%2220px%22%20viewBox%3D%220%200%201200%20130%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%0A%20%20%3Cpath%20stroke%3D%22black%22%20stroke-width%3D%223%22%20fill%3D%22none%22%20d%3D%22M55%2068c-17%2C6%20-8%2C23%204%2C28%2012%2C5%2040%2C7%2048%2C-8%209%2C-15%20-9%2C-34%20-26%2C-41%20-17%2C-8%20-45%2C-7%20-62%2C2%20-18%2C8%20-19%2C18%20-20%2C27%20-1%2C9%200%2C29%2027%2C52%2028%2C23%2052%2C33%20102%2C33%2049%2C-1%20130%2C-31%20185%2C-50%2056%2C-19%2074%2C-21%2096%2C-23%2022%2C-2%2029%2C-2%2056%2C6%2027%2C8%2043%2C17%2043%2C17%2014%2C6%2016%2C7%2041%2C16%2025%2C9%2069%2C15%20120%2C11%2051%2C-3%20126%2C-22%20181%2C-32%2054%2C-9%20105%2C-20%20148%2C-23%2042%2C-3%2071%2C1%20104%2C6%2034%2C4%2065%2C14%2098%2C22%22%2F%3E%0A%3C%2Fsvg%3E%0A);
}
	<div class="author_">Lord Byron</div>

Ferramenta conveniente para codificação SVG de codificador de URL

Alexei Zababurin
fonte
5

Tenha cuidado, todas as outras respostas têm algum problema no IE.

Vamos ter essa situação - botão com o ícone anexado. Todos os navegadores lidam com isso corretamente, mas o IE pega a largura do elemento e dimensiona o conteúdo anterior para ajustá-lo. JSFiddle

#mydiv1 { width: 200px; height: 30px; background: green; }
#mydiv1:before {
    content: url("data:url or /standard/url.svg");
}

A solução é definir o tamanho como elemento anterior e deixá-lo onde está:

#mydiv2 { width: 200px; height: 30px; background: green; }
#mydiv2:before {
    content: url("data:url or /standard/url.svg");
    display: inline-block;
    width: 16px; //only one size is alright, IE scales uniformly to fit it
}

As soluções background-image+ também background-sizefuncionam, mas são pouco práticas, pois é necessário especificar os mesmos tamanhos duas vezes.

O resultado no IE11:

IE rendering

zbycz
fonte
5

Para estender ainda mais este tópico. Caso você queira adicionar ícones do Font Awesome 5, é necessário adicionar um CSS extra.

Os ícones por padrão têm classes svg-inline--fae fa-w-*.

Há também aulas modificadoras como fa-lg, fa-rotate-*e outros. Você precisa verificar o svg-with-js.cssarquivo e encontrar o CSS adequado para isso.

Você precisa adicionar sua própria cor ao ícone css, caso contrário, ficará preto por padrão, por exemplo, fill='%23f00'onde %23está codificado #.

h1::before{

  /* svg-inline--fa */
  display:inline-block;
  font-size:inherit;
  height:1em;
  overflow:visible;
  vertical-align:-.125em;
  
  /* fa-w-14 */
  width:.875em;
  
  /* Icon */
  content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='%23f00' d='M400 256H152V152.9c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v16c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-16C376 68 307.5-.3 223.5 0 139.5.3 72 69.5 72 153.5V256H48c-26.5 0-48 21.5-48 48v160c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48zM264 408c0 22.1-17.9 40-40 40s-40-17.9-40-40v-48c0-22.1 17.9-40 40-40s40 17.9 40 40v48z'%3E%3C/path%3E%3C/svg%3E");
  
  /* Margin */
  margin-right:.75rem;
}
<h1>Lorem Ipsum</h1>

Jakub Muda
fonte
-1
.myDiv {
  display: flex;
  align-items: center;
}

.myDiv:before {
  display: inline-block;
  content: url(./dog.svg);
  margin-right: 15px;
  width: 10px;
}
Michael Alfandre
fonte
3
Você deve explicar um pouco mais a sua resposta. Só assim, é realmente difícil dizer como ou por que sua resposta funciona.
ifconfig