¿Hay alguna manera de usar SVG como contenido en un pseudo elemento: before o: after

246

Quiero colocar algunas imágenes SVG antes de algunos elementos seleccionados. Estoy usando jQuery pero eso es irrelevante.

Me gustaría tener el :beforeelemento para ser como:

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

Si lo hago como se muestra arriba, solo muestra la cadena. Revisé las especificaciones y parece haber algunas restricciones sobre el contenido que puede ser. ¿Hay alguna solución a esta restricción? Solo el contenido css es relevante para mi pregunta.

Soleado
fuente
1
¿Tiene algún problema usarlo como imagen de fondo?
cimmanon
1
Quiero usarlo para generar punteros elegantes a la información sobre herramientas de JQuery UI. Hago eso ahora con los pseudo elementos CSS, pero eso me da solo triángulos. La imagen de fondo no funcionará en este caso ya que necesito algo que salga del elemento.
Soleado

Respuestas:

253

¡Sí tu puedes! Acabo de probar esto y funciona muy bien, ¡esto es increíble! Todavía no funciona con html, pero sí con svg.

En mi index.html tengo:

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

Y mi test.svg se ve así:

<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
fuente
18
A menos que el IVS son especiales, debe ser capaz de tratarlos de la misma como lo haría con una imagen: content: url(path/to/my.svg). Sin embargo, eso no necesariamente significa que funcionaría con la biblioteca de información sobre herramientas de jQuery UI.
cimmanon
1
@cimmanon hmm, eso es dulce, quiero probar eso. Entonces, en my.html o lo que sea, podría tener un montón de código html para representar ... suena increíble.
dezman
2
Por qué querrías hacer esto? Si ya tiene el código svg en el archivo, no hay necesidad de ponerlo en una pseudoclase. El objetivo de las pseudo-clases es reducir los elementos DOM cuando desea agregar un poco de contenido, pero en su caso si solo usa su código svg normalmente no será peor (y probablemente más limpio) que ponerlo en un pseudo -clase (que también es probablemente imposible). A menos, por supuesto, si desea poner su código svg en un montón de ubicaciones, en cuyo caso debe mantener su código svg en un archivo separado como una imagen.
dezman
66
desafortunadamente, no creo que esta solución funcione con sprites SVG. por ejemplo, en content: url(mysprite.svg#my-icon)realidad no levantará su ícono. sin embargo, me encantaría que me demuestren lo contrario :)
Jason
1
@watson, semántico. La estructura HTML =, CSS = presentación. Si un SVG es decorativo, entonces no debería estar en la estructura HTML, debería estar en CSS.
deathlock
137

Si. Puede agregar el SVG como imagen de fondo de un vacío: después o: antes. Aqui tienes:

.anchor:before {
  display: block;
  content: ' ';
  background-image: url('../images/anchor.svg');
  background-size: 28px 28px;
  height: 28px;
  width: 28px;
}
DerZyklop
fuente
44
Encuentro esta una de las mejores soluciones, después de buscar por un tiempo. Puede controlar todos los aspectos del elemento insertado y funciona de la manera normal en que funcionan las hojas de estilo CSS, con lógica separada. Genial
Danielo515
... ahh esto me ilusionó, hasta que me di cuenta de que background-sizeno es compatible con Opera Mini. Esto es muy frustrante.
deathlock
Funcionó muy bien. @deathlock, el tamaño de fondo no debería ser necesario ya que estás definiendo las dimensiones en el svg, no lo necesitaba.
Eric Soyke
1
Deben ser las respuestas aceptadas ya que la pregunta dice "en un pseudo elemento: antes o: después"
ZalemCitizen
Tuve que agregar <?xml version="1.0" encoding="utf-8"?>al comienzo de mi archivo svg para que funcione.
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;
}

asegúrese de que su svg no contenga comillas dobles, y uriencode cualquier # símbolos

Jenny
fuente
8
Dado que los SVG a menudo usan comillas dobles, también puede usar comillas simples externas. La sugerencia de @ Jenny es una excelente manera de hacerlo si no desea utilizar un archivo SVG externo.
Micros
2
Esto es genial. Desafortunadamente, solo funciona con Chrome para mí (probado en Chrome, Firefox y Edge).
Arsen
2
OK, funciona en FF. Solo necesitaba prestar atención a la parte "no #". También asegúrese de usar la etiqueta div (no parece funcionar con span). Lamentablemente todavía no hay éxito para Edge.
Arsen
Al igual que muchas soluciones brillantes, IE11 no lo admite. url('file.svg')funciona sin embargo.
Bob Stein
66
Lo que encontré importante es agregar xmlns='http://www.w3.org/2000/svg'en la parte <svg> para trabajar en Chrome 66.x. Por ejemplo, el pequeño galón será: 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>");
darth0s
28

El uso de sprites CSS y uri de datos brinda beneficios adicionales interesantes como carga rápida y menos solicitudes Y obtenemos soporte para IE8 usando image / base64:

Codepen muestra 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 IE8, cambie a esto:

  background-image: url(data:image/png;base64,data......);
Un hijo
fuente
Pero esto no es escalable, ¿no? No puedo cambiar su tamaño a 16px o 320px a voluntad.
deathlock el
@deathlock Por supuesto, se escala, aunque no mi muestra, ya que tiene un conjunto de tamaño fijo, 80 px de ancho / alto.
Ason el
1
@deathlock ¿Puedo preguntarle si votó en contra porque la muestra anterior no se amplió?
Ason
¿Cómo lo harías escalar? Y no, no lo hice.
deathlock
@deathlock Gracias, y aquí hay una forma de escalar svg: jsfiddle.net/ess6ywce ... usando el porcentaje. Además, busque SO con scale svgy encontrará muchas más formas
Ason el
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>

Herramienta conveniente para codificar SVG codificador de url

Alexei Zababurin
fuente
5

Tenga cuidado, todas las otras respuestas tienen algún problema en IE.

Tengamos esta situación: botón con el icono antepuesto. Todos los navegadores manejan esto correctamente, pero IE toma el ancho del elemento y escala el contenido anterior para ajustarlo. JSFiddle

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

La solución es establecer el tamaño al elemento anterior y dejarlo donde 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
}

Las soluciones background-image+ también background-sizefuncionan, pero son poco convencionales, ya que debe especificar los mismos tamaños dos veces.

El resultado en IE11:

Representación de IE

zbycz
fuente
5

Para ampliar aún más este tema. En caso de que desee agregar íconos de Font Awesome 5 , debe agregar un poco de CSS adicional.

Los iconos por defecto tienen clases svg-inline--fay fa-w-*.

También hay clases modificadoras como fa-lg, fa-rotate-*y otras. Debe verificar el svg-with-js.cssarchivo y encontrar el CSS adecuado para eso.

Debe agregar su propio color al icono css; de lo contrario, será negro de forma predeterminada, por ejemplo, fill='%23f00'dónde %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
fuente
-1
.myDiv {
  display: flex;
  align-items: center;
}

.myDiv:before {
  display: inline-block;
  content: url(./dog.svg);
  margin-right: 15px;
  width: 10px;
}
Michael Alfandre
fuente
3
Deberías explicar un poco más tu respuesta. Solo por esto, es realmente difícil saber cómo o por qué funciona su respuesta.
ifconfig