Comment faire en sorte qu'un élément <svg> se développe ou se contracte avec son conteneur parent?

112

Le but est que l' <svg>élément se développe jusqu'à la taille de son conteneur parent, dans ce cas a <div>, quelle que soit la taille de ce conteneur.

Le code:

<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 solution la plus courante à ce problème semble être la définition de l' viewBoxattribut sur l' <svg>élément.

viewBox="0 0 widthOfContainer heightOfContainer"

Cependant, cela ne semble pas fonctionner dans les cas où les éléments de l' <svg>élément ont des largeurs et / ou des hauteurs prédéfinies. Par exemple, l' <rect>élément, dans le code ci-dessus, a sa largeur et sa hauteur explicitement définies.

La solution évidente est donc d'utiliser également des% de largeurs et des% de hauteurs sur ces éléments. Mais est-ce que cela doit même être fait? Surtout, puisque <img src=test.svg >fonctionne bien et se dilate / se contracte sans aucun problème avec des <rect>hauteurs et largeurs explicitement définies .

Si des éléments comme <rect>, et d'autres éléments similaires, doivent avoir leurs largeurs et hauteurs définies en pourcentages, y a-t-il un moyen dans Inkscape de le définir de sorte que tous les éléments avec le <svg>document utilisent des largeurs, des hauteurs, etc. en pourcentage au lieu de dimensions fixes ?

user782860
la source
1
Enregistrez le svg en tant que fichier, puis référencez-le comme une image, comme <img src = "file.svg" /> et de cette façon, vous pouvez utiliser width: 100% ou height: 100%
Burimi

Réponses:

56

Ce viewBoxn'est pas la hauteur du conteneur, c'est la taille de votre dessin. Définissez votre viewBoxlargeur de 100 unités, puis définissez votre valeur rectsur 10 unités. Après cela, quelle que soit la taille du SVG, rectla largeur de l'image sera de 10%.

Robertc
la source
33
Mais la question est: comment mettre à l'échelle le SVG?
Adrian Heine
6
@AdrianLang La mise à l'échelle se produit automatiquement lorsque vous définissez une taille sur l'objet SVG, comme cela est déjà fait dans le code de la question. Voici une version fixe de l'exemple .
robertc
Vous avez raison, super, cela fonctionne vraiment pour moi. Je suppose que mon problème était les propriétés de hauteur et de largeur dans mon élément racine svg.
Adrian Heine
2
J'ai apporté quelques modifications mineures à ce violon pour forcer ce redimensionnement horizontalement et verticalement sans préserver le rapport hauteur / largeur, et je l'ai fait fonctionner dans IE, alors que le violon @robertc soumis ne l'était pas. J'espère que cela aidera quelqu'un sur la route!
Mister Crimson
3
Par défaut, votre svg sera mis à l'échelle aussi grand que possible afin qu'il soit complètement visible mais préserve son rapport hauteur / largeur (donc un viewBox carré ne remplira pas complètement un parent rectangulaire). Si vous voulez vraiment le forcer à couvrir complètement le conteneur parent, ajoutez preserveAspectRatio = "none" à l'élément SVG.
patricksurry
24

Supposons que j'ai un SVG qui ressemble à ceci: pic1

Et je veux le mettre dans un div et le faire remplir le div de manière réactive. Ma façon de procéder est la suivante:

J'ouvre d'abord le fichier SVG dans une application comme inkscape. Dans Fichier-> Propriétés du document, je règle la largeur du document sur 800 px et la hauteur sur 600 px (vous pouvez choisir d'autres tailles). Ensuite, je place le SVG dans ce document.

pic2

Ensuite, j'enregistre ce fichier en tant que nouveau fichier SVG et j'obtiens les données de chemin de ce fichier. Maintenant, en HTML, le code qui fait la magie est le suivant:

<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>

Notez que la largeur et la hauteur de SVG sont toutes deux définies à 100%, car nous voulons qu'il remplisse le conteneur verticalement et horizontalement, mais la largeur et la hauteur de la viewBox sont les mêmes que la largeur et la hauteur du document dans inkscape qui est de 800px X 600px. La prochaine chose que vous devez faire est de définir la préserveAspectRatio sur «aucun». Si vous avez besoin de plus d'informations sur cet attribut, voici un bon lien . Et c'est tout ce qu'il y a à faire.

Une autre chose est que ce code fonctionne sur presque tous les principaux navigateurs, même les anciens, mais sur certaines versions d'Android et d'ios, vous devez utiliser du code javascrip / jQuery pour le garder cohérent. J'utilise ce qui suit dans les fonctions de prêt de document et de redimensionnement:

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

J'espère que ça aide!

Reza Baradaran Gazorisangi
la source
5
+1 pour la note PreserveAspectRatio. Après avoir chassé haut et bas pour obtenir un SVG qui s'étire réellement (pas l'échelle) en div, c'était la bonne réponse.
adelphus
@Gazoris, merci pour cette merveilleuse réponse. ont une question sur le même. Et si mon svg est imbriqué. par exemple, <svg> <svg id = "1"> </svg> <svg id = "2"> </svg> </svg> je veux afficher les svg 1 et 2 conditionnellement et cela devrait prendre la largeur et la hauteur du conteneur. <div id = "container" style = "width: 200px; height: 200px;"> </div> pouvez-vous s'il vous plaît m'aider à ce sujet.
Prasad Parab
@Reza Baradaran: Génie.
DanMad
6

Ce qui est travaillé pour moi est récemment pour supprimer tous height=""et width=""attributs de l' <svg>étiquette , et de l' enfant. Ensuite, vous pouvez utiliser la mise à l'échelle en utilisant un pourcentage de la hauteur ou de la largeur du conteneur parent.

Geoff Colbath
la source
5
Pouvez-vous donner un exemple concret? Je ne peux rien faire faire.
Michael
2

@robertc a raison, mais vous devez également noter que svg, #containerle svg est mis à l'échelle de manière exponentielle pour tout sauf 100% (une fois pour #containeret une fois pour svg).

En d'autres termes, si j'ai appliqué 50% h / w aux deux éléments, c'est en fait 50% de 50%, ou 0,5 * 0,5, ce qui équivaut à une échelle de 0,25 ou 25%.

Un sélecteur fonctionne correctement lorsqu'il est utilisé comme @robertc le suggère.

svg {
  width:50%;
  height:50%;
}
Justin Putney
la source
C'est parce que votre sélecteur svg, #containercorrespond à la fois à l' svgélément dom et à l' #containerélément dom. Je crois que vous cherchiez plutôt svg #container, mais la spécification d'un parent n'est pas nécessaire si vous utilisez de toute façon un identifiant.
Nit
N'est-ce pas exactement ce que j'ai dit, "une fois pour #container et une fois pour svg"?
Justin Putney
1
Oh pardon, vous avez raison, mais votre réponse est un peu étrangement formulée, ce qui conduit à un malentendu. On dirait que vous parlez d'un éventuel gotcha au début.
Nit
1

Pour votre iPhone, vous pouvez utiliser dans votre tête balise:

"width=device-width"
Vincent
la source