Como fazer um elemento <svg> expandir ou contrair para seu contêiner pai?

112

O objetivo é fazer com que o <svg>elemento seja expandido até o tamanho de seu contêiner pai, neste caso a <div>, não importa o quão grande ou pequeno esse contêiner seja.

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

A solução mais comum para esse problema parece ser definir o viewBoxatributo no <svg>elemento.

viewBox="0 0 widthOfContainer heightOfContainer"

No entanto, isso não parece funcionar nos casos em que os elementos dentro do <svg>elemento têm larguras e / ou alturas predefinidas. Por exemplo, o <rect>elemento, no código acima, tem sua largura e altura definidas explicitamente.

Portanto, a solução óbvia é usar% larguras e% alturas nesses elementos também. Mas isso ainda precisa ser feito? Especialmente porque <img src=test.svg >funciona bem e expande / contrai sem problemas com <rect>alturas e larguras explicitamente definidas .

Se elementos como <rect>, e outros elementos como ele, precisam ter suas larguras e alturas definidas em porcentagens, existe uma maneira no Inkscape de configurá-lo de forma que todos os elementos com o <svg>documento usem larguras percentuais, alturas, etc. em vez de dimensões fixas ?

user782860
fonte
1
Salve o svg como um arquivo, em seguida, referencie-o como uma imagem, como <img src = "file.svg" /> e dessa forma você pode usar largura: 100% ou altura: 100%
Burimi

Respostas:

56

Não viewBoxé a altura do contêiner, é o tamanho do seu desenho. Defina sua viewBoxlargura como 100 unidades e, em seguida, defina rectcomo 10 unidades. Depois disso, por maior que seja o tamanho do SVG, rectele terá 10% da largura da imagem.

robertc
fonte
33
Mas a questão é: como dimensionar o SVG?
Adrian Heine
6
@AdrianLang O dimensionamento acontece automaticamente quando você define um tamanho no objeto SVG, como já é feito no código em questão. Aqui está uma versão fixa do exemplo .
robertc
Você está certo, ótimo, isso realmente funciona para mim. Acho que meu problema eram as propriedades de altura e largura em meu elemento raiz svg.
Adrian Heine de
2
Fiz alguns pequenos ajustes nesse violino para fazer com que o redimensionamento fosse forçado horizontalmente e verticalmente sem preservar a proporção de aspecto e o fiz funcionar no IE, enquanto o violino @robertc enviado não. Espero que ajude alguém no caminho!
Senhor Crimson
3
Por padrão, seu svg será dimensionado o maior possível para que seja completamente visível, mas preserva sua proporção de aspecto (portanto, um viewBox quadrado não preencherá completamente um pai retangular). Se você realmente deseja forçá-lo a cobrir completamente o contêiner pai, adicione preserveAspectRatio = "none" ao elemento SVG.
patricksurry
24

Suponha que eu tenha um SVG parecido com este: pic1

E eu quero colocá-lo em um div e fazê-lo preencher o div responsivamente. Minha maneira de fazer isso é a seguinte:

Primeiro, abro o arquivo SVG em um aplicativo como o inkscape. Em Arquivo-> Propriedades do documento, defino a largura do documento em 800px e a altura em 600px (você pode escolher outros tamanhos). Então eu ajustei o SVG neste documento.

pic2

Em seguida, salvo esse arquivo como um novo arquivo SVG e pego os dados do caminho desse arquivo. Agora, em HTML, o código que faz a mágica é o seguinte:

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

Observe que a largura e a altura do SVG estão configuradas para 100%, pois queremos que ele preencha o contêiner vertical e horizontalmente, mas a largura e a altura do viewBox são iguais à largura e altura do documento no inkscape, que é 800px X 600px. A próxima coisa que você precisa fazer é definir o preserveAspectRatio como "nenhum". Se você precisar de mais informações sobre este atributo, aqui está um bom link . E isso é tudo que há para fazer.

Mais uma coisa é que esse código funciona em quase todos os principais navegadores, mesmo os antigos, mas em algumas versões do Android e iOS você precisa usar algum código javascrip / jQuery para mantê-lo consistente. Eu uso o seguinte nas funções de preparação de documentos e redimensionamento:

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

Espero que ajude!

Reza Baradaran Gazorisangi
fonte
5
+1 para a nota preserveAspectRatio. Depois de pesquisar alto e baixo para fazer um SVG realmente se esticar (não escalar) para um div, esta foi a resposta correta.
adelphus
@Gazoris, Obrigado por esta resposta maravilhosa. tem dúvidas sobre o mesmo. E se meu svg estiver aninhado. por exemplo, <svg> <svg id = "1"> </svg> <svg id = "2"> </svg> </svg> quero exibir svg 1 e 2 condicionalmente e deve ter largura e altura do recipiente. <div id = "container" style = "width: 200px; height: 200px;"> </div> você pode me ajudar nisso.
Prasad Parab
@Reza Baradaran: Genius.
DanMad
6

O que funcionou para mim recentemente foi remover todos os atributos height=""e width=""da <svg>tag e todas as tags filhas. Em seguida, você pode usar o dimensionamento usando uma porcentagem da altura ou largura do contêiner pai.

Geoff Colbath
fonte
5
Você pode dar um exemplo prático? Não consigo fazer com que isso aconteça
Michael
2

@robertc está certo, mas você também precisa notar que svg, #containerfaz com que o svg seja escalado exponencialmente para qualquer coisa menos 100% (uma vez para #containere uma vez para svg).

Em outras palavras, se eu aplicar 50% h / w a ambos os elementos, é na verdade 50% de 50%, ou 0,5 * 0,5, que é igual a 0,25 ou escala de 25%.

Um seletor funciona bem quando usado como @robertc sugere.

svg {
  width:50%;
  height:50%;
}
Justin Putney
fonte
Isso porque seu seletor svg, #containercombina tanto o svgelemento DOM e o #containerelemento DOM. Acredito que você estava procurando svg #container, mas a especificação de um pai não é necessária se você estiver usando um ID de qualquer maneira.
Nit
Não foi exatamente isso que eu disse, "uma vez para #container e uma vez para svg"?
Justin Putney
1
Oh, desculpe, você está certo, mas sua resposta é um pouco estranhamente formulada levando a um mal-entendido. Parece que você está falando sobre um problema potencial em primeiro lugar.
Nit
1

Para o seu iphone, você pode usar na sua cabeça:

"width=device-width"
Vincent
fonte