¿Cómo hacer que un elemento <svg> se expanda o contraiga a su contenedor principal?

112

El objetivo es que el <svg>elemento se expanda al tamaño de su contenedor principal, en este caso a <div>, sin importar cuán grande o pequeño sea ese contenedor.

El código:

<style>
    svg, #container{
        height: 100%;
        width: 100%;
    }
</style>

<div id="container">
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" >
         <rect x="0" y="0" width="100" height="100" />
    </svg>
</div>

La solución más común a este problema parece establecer el viewBoxatributo en el <svg>elemento.

viewBox="0 0 widthOfContainer heightOfContainer"

Sin embargo, esto no parece funcionar en los casos en que los elementos dentro del <svg>elemento tienen anchos y / o alturas predefinidos. Por ejemplo, el <rect>elemento, en el código anterior, tiene su ancho y alto establecidos explícitamente.

Entonces, la solución obvia es usar% anchuras y% alturas en esos elementos también. Pero, ¿es necesario hacer esto? Especialmente, dado que <img src=test.svg >funciona bien y se expande / contrae sin ningún problema con las <rect>alturas y anchos establecidos explícitamente .

Si los elementos como <rect>, y otros elementos similares, tienen que tener sus anchos y alturas definidos en porcentajes, ¿hay alguna forma en Inkscape de configurarlo para que todos los elementos del <svg>documento usen anchos, alturas, etc. porcentuales en lugar de dimensiones fijas? ?

user782860
fuente
1
Guarde el svg como un archivo, luego haga referencia a él como una imagen, como <img src = "file.svg" /> y de esa manera puede usar ancho: 100% o alto: 100%
Burimi

Respuestas:

56

No viewBoxes la altura del contenedor, es el tamaño de tu dibujo. Defina que su viewBoxancho sea de 100 unidades, luego defina rectque sea de 10 unidades. Después de eso, por grande que sea la escala del SVG, rectserá un 10% del ancho de la imagen.

Robertc
fuente
33
Pero la pregunta es: ¿Cómo escalar el SVG?
Adrian Heine
6
@AdrianLang La escala ocurre automáticamente cuando establece un tamaño en el objeto SVG, como ya se hace en el código de la pregunta. Aquí hay una versión fija del ejemplo .
robertc
Tienes razón, genial, eso realmente funciona para mí. Supongo que mi problema fueron las propiedades de alto y ancho en mi elemento raíz svg.
Adrian Heine
2
Hice algunos ajustes menores en ese violín para hacer que el cambio de tamaño se fuerce horizontal y verticalmente sin preservar la relación de aspecto, y lo hice funcionar en IE, mientras que el violín que @robertc envió no lo fue. ¡Espero que ayude a alguien en el futuro!
Mister Crimson
3
De forma predeterminada, su svg se escalará lo más grande posible para que sea completamente visible pero conserve su relación de aspecto (por lo que un viewBox cuadrado no llenará completamente un padre rectangular). Si realmente desea forzarlo a cubrir completamente el contenedor principal, agregue preserveAspectRatio = "none" al elemento SVG.
patricksurry
24

Supongamos que tengo un SVG que se ve así: pic1

Y quiero ponerlo en un div y hacer que llene el div en respuesta. Mi forma de hacerlo es la siguiente:

Primero abro el archivo SVG en una aplicación como inkscape. En Archivo-> Propiedades del documento, configuro el ancho del documento en 800px y el alto en 600px (puede elegir otros tamaños). Luego coloco el SVG en este documento.

pic2

Luego guardo este archivo como un nuevo archivo SVG y obtengo los datos de ruta de este archivo. Ahora, en HTML, el código que hace la magia es el siguiente:

<div id="containerId">    
    <svg
    id="svgId" 
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    x="0"
    y="0"
    width="100%"
    height="100%"
    viewBox="0 0 800 600"
    preserveAspectRatio="none">
       <path d="m0 0v600h800v-600h-75.07031l-431 597.9707-292.445315-223.99609 269.548825-373.97461h-271.0332z" fill="#f00"/>
    </svg>
</div>

Tenga en cuenta que el ancho y la altura de SVG están configurados al 100%, ya que queremos que llene el contenedor vertical y horizontalmente, pero el ancho y alto del viewBox son los mismos que el ancho y alto del documento en inkscape, que es 800px X 600px. Lo siguiente que debe hacer es establecer preserveAspectRatio en "none". Si necesita más información sobre este atributo, aquí tiene un buen enlace . Y eso es todo lo que hay que hacer.

Una cosa más es que este código funciona en casi todos los navegadores principales, incluso en los antiguos, pero en algunas versiones de Android e iOS es necesario utilizar un código javascrip / jQuery para mantener la coherencia. Utilizo lo siguiente en las funciones de preparación de documentos y cambio de tamaño:

$('#svgId').css({
    'width': $('#containerId').width() + 'px',
    'height': $('#containerId').height() + 'px'
});

¡Espero eso ayude!

Reza Baradaran Gazorisangi
fuente
5
+1 para la nota preserveAspectRatio. Después de buscar altos y bajos para que un SVG se estire (no escale) a un div, esta fue la respuesta correcta.
adelphus
@Gazoris, Gracias por esta maravillosa respuesta. tiene pregunta sobre el mismo. ¿Qué pasa si mi svg está anidado. por ejemplo, <svg> <svg id = "1"> </svg> <svg id = "2"> </svg> </svg> quiero mostrar svg 1 y 2 de forma condicional y debe tener ancho y alto de contenedor. <div id = "container" style = "width: 200px; height: 200px;"> </div> ¿podrías ayudarme con esto?
Prasad Parab
@Reza Baradaran: Genio.
DanMad
6

Lo que me funcionó recientemente es eliminar todos los atributos height=""y width=""de la <svg>etiqueta y todas las etiquetas secundarias. Luego, puede usar la escala utilizando un porcentaje de la altura o el ancho del contenedor principal.

Geoff Colbath
fuente
5
¿Puede dar un ejemplo práctico? No puedo hacer que esto haga nada.
Michael
2

@robertc tiene razón, pero también debe notar que svg, #containerhace que el svg se escale exponencialmente para cualquier cosa menos 100% (una vez por #containery una vez por svg).

En otras palabras, si apliqué 50% h / w a ambos elementos, en realidad es el 50% del 50%, o .5 * .5, que equivale a .25, o 25% de escala.

Un selector funciona bien cuando se usa como sugiere @robertc.

svg {
  width:50%;
  height:50%;
}
Justin Putney
fuente
Esto se debe a que su selector svg, #containercoincide tanto el svgelemento DOM y el #containerelemento DOM. Creo que en su lugar estaba buscando svg #container, pero la especificación de un padre no es necesaria si de todos modos está usando una identificación.
Nit
¿No es eso exactamente lo que dije, "una vez para #container y una vez para svg"?
Justin Putney
1
Oh, perdón, tienes razón, pero tu respuesta está redactada de manera un poco extraña y conduce al malentendido. Parece que al principio estás hablando de un posible problema.
Nit
1

Para tu iphone, puedes usar en tu cabeza:

"width=device-width"
Vincent
fuente