SVGサークルはCSSグリッドの高さに重なり合うことなく適応する必要があります


8

次の例では、円はグリッドの幅に適応し、アスペクト比を維持しています。コンテナの幅が縮小すると、円もそれに伴って縮小します...

ただし、高さが幅よりも小さい場合(2番目のボックス)、円はグリッドの外側のオーバーラップを縮小しません。代わりに、アスペクト比を維持しながら高さにも適応させる方法はありますか?

.container {
	display: grid;
	background-color: greenyellow;
	margin: 5px;
	min-height: 10px;
	min-width: 10px;
}

.portrait {
		max-height: 100px;
		max-width: 200px;
}

.landscape {
		max-height: 200px;
		max-width: 100px;
}

.aspect-ratio {
	grid-column: 1;
	grid-row: 1;
	background-color: deeppink;
	border-radius: 50%;
 align-self: center;
	justify-self: center;
}
<div class="container landscape">
  <svg class="aspect-ratio" viewBox="0 0 1 1"></svg>
</div>

<div class="container portrait">
  <svg class="aspect-ratio" viewBox="0 0 1 1"></svg>
</div>

結果は次のようになります。 ここに画像の説明を入力してください


svgコードを編集する可能性はありますか?
thetont

回答:


8

この問題をしばらく試してみたところ、グリッドレイアウトの問題ではないことがわかりました。

あなたが定義することはありませんので、高さ/最大高さ幅/最大幅をあなたのSVGのために、計算されているものがあるwidth:autoheight:auto

注:max-height / max-width幅/高さの値よりも優先されるため、ここで取り上げます。


それでは、なぜ横向きレイアウトが機能し、向きレイアウトが機能しないのですか?なぜなら、幅は身長よりも「優先される」からです。

そのため、ブロックレイアウトでは、自動高さは子孫の合計の高さに基づいており、自動幅はそれを含むブロックの幅に基づいています。

ソース-width:autoの動作がheight:autoと異なるのはなぜですか?

これは、SVGがwidthコンテナとheightその子孫からを取得していることを意味します。

この例では、SVGには子孫はありませんが、定義されたmax-widthを持つ親があります。しかし、これはSVGの高さに対して何を意味するのでしょうか。

SVGは、本質的な比率から高さを計算しています。

「svg」要素の「viewBox」が正しく指定されている場合:

  1. viewboxを 'svg'要素の 'viewBox'属性で定義されたビューボックスにする
  2. viewbox.width / viewbox.heightを返す

ソース

そして、あなたの本質的な比率は1/1 = 1です

だからあなたはあなたを強制している height=width


ソリューション

解決策は、親divの比率に応じてSVGにa widthまたはa marginを設定することです。

あなたが与えた例では、あなたは2:1の比率を持っているので、あなたのSVGはwidth:50%またはを持っているべきmargin: 0 25%です。

つまり、別の比率を設定する場合は、それに応じて調整する必要があります(以下のコードのportrait-1-3を参照)。

height制約でない場合、各比率にCSSルールを設定することは回避できwidthます。SVGとコンテナーにを定義し、要素にを調整heightさせてアスペクト比を維持できるからです。

アスペクト比を維持する必要はないが、セットheightwidthコンテナにSVGを含める必要がある場合の最後の例も追加しました。

.container {
  display: grid;
  background-color: greenyellow;
  margin: 5px;
  min-height: 10px;
  min-width: 10px;
}

.portrait {
  max-height: 100px;
  max-width: 200px;
}


/* Add 25% margin left and right to center the image  OR set the image width to 50% */

.portrait>.aspect-ratio {
  margin: 0 25%;
  /*
    or 
    
    width:50%;
  */
}

.landscape {
  max-height: 200px;
  max-width: 100px;
}

.aspect-ratio {
  grid-column: 1;
  grid-row: 1;
  background-color: deeppink;
  border-radius: 50%;
  align-self: center;
  justify-self: center;
}


/* Set fixed max-height and max-width rule (33% proportion)  */

.portrait-1-3 {
  max-height: 100px;
  max-width: 300px;
}


/* Align image with the new proportion */

.portrait-1-3>.aspect-ratio {
  margin: 0 33.33%;
  /*
    or 
    
    width:33.3%;
  */
}


/* Removed max-height and let the container adjust the height according to the max-width rule and the proportion set  */

.portrait-any-height {
  max-width: 400px;
}


/* Height will be adjusted through the width/margin defined here, so 10% width will correspond to 40px of height (10%*400px)*(aspect ratio=1)*/

.portrait-any-height>.aspect-ratio {
   width:10%;
}


/* Set fixed max-height and max-width rule (proportion doesn't matter)  */

.portrait-squeezed {
  max-height: 100px;
  max-width: 300px;
}


/* Make sure SVG complies with the the given max with and height (squeezing your svg)  */

.portrait-squeezed>.aspect-ratio {
  max-height: inherit;
  max-width: inherit;
}
<div class="container landscape">
  <svg class="aspect-ratio" viewBox="0 0 1 1"></svg>
</div>

<div class="container portrait">
  <svg class="aspect-ratio" viewBox="0 0 1 1"></svg>
</div>

<div class="container portrait-1-3">
  <svg class="aspect-ratio" viewBox="0 0 1 1"></svg>
</div>

<div class="container portrait-any-height">
  <svg class="aspect-ratio" viewBox="0 0 1 1"></svg>
</div>

<div class="container portrait-squeezed">
  <svg class="aspect-ratio" viewBox="0 0 1 1"></svg>
</div>

私はSVGでの作業にあまり熟達していないことに注意してください。この応答は研究と多くの実験の結果です!返信に対する調整や修正があれば喜んでお送りします。


詳細な説明ありがとうございます...残念ながら、あなたの研究では私の結果と同じ結果が返されました。私の要件に対する解決策はないようです:1. SVGアスペクト比が修正されました。2.コンテナのアスペクト比は可変/不明です3.コンテナのサイズは環境に応じて高さと幅の両方によって制限されます(例:ブラウザウィンドウのサイズ)SVGの幅をコンテナの特定のパーセンテージに設定することで提案されるソリューションは、コンテナがアスペクト比は固定されていましたが、そうではありません。
Th3S4mur41

max-heightを
あきらめる

これら3つの要件では、CSS のみを使用するという解決策はないようです。問題の適切なSVG幅を計算するためにJavaScriptを使用していますか?
H.フィゲイレド

それが私の現在の解決策がやっていることです;)
Th3S4mur41

アスペクト比がこれを解決するのに役立つことを願っていますが、それについてはよくわかりません。drafts.c​​sswg.org/css-sizing-4/#aspect-ratio
Th3S4mur41

0

max-height&max-widthとともに、コンテナ固有の高さと幅を追加します。

vwおよびvhユニットを使用して、このレイアウトをより柔軟にすることができます。

  max-height: 100px;
  max-width: 200px;
  width: 100vw;
  height: 100vh;

このようmax-width: 100%; max-height: 100%;に、svg に設定することが可能で、重複しません。


-編集-

svgビューボックスはすでに正しいアスペクト比でレンダリングされているため、svgの背景をsvg自体の中に移動しても、期待どおりの結果が得られます。cicleタグが役立ちます。

マスク内の別の円タグで境界半径を模倣することは可能ですか

svgの他のすべての要素は、マスクされたグループ内に配置する必要があります。つまり:<g mask="url(#mask)">

.container {
  display: grid;
  background-color: greenyellow;
  margin: 5px;
  min-height: 10px;
  min-width: 10px;
}

.portrait {
  max-height: 100px;
  max-width: 200px;
  width: 100vw;
  height: 100vh;
}

.landscape {
  max-height: 200px;
  max-width: 100px;
  width: 100vw;
  height: 100vh;
}

.aspect-ratio {
  grid-column: 1;
  grid-row: 1;
  align-self: center;
  justify-self: center;
  max-width: 100%;
  max-height: 100%;
}

.aspect-ratio .bkg{
  fill: deeppink;
}
<div class="container landscape">
  <svg class="aspect-ratio" viewBox="0 0 1 1">
    <mask id="mask">
      <circle cx=".5" cy=".5" r=".5" fill="#fff"/>
    </mask>
    <circle cx=".5" cy=".5" r=".5" class="bkg"/>
    <g  mask="url(#mask)">

    </g>
  </svg>
</div>

<div class="container portrait">
  <svg class="aspect-ratio"viewBox="0 0 1 1">
    <mask id="mask">
      <circle cx=".5" cy=".5" r=".5" fill="#fff"/>
    </mask>
    <circle cx=".5" cy=".5" r=".5" class="bkg"/>
    <g  mask="url(#mask)">

    </g>
  </svg>
</div>


1
質問では、「アスペクト比を維持しながら高さに合わせる方法はありますか」と指定されていましたが、例ではそうではありません。これはコンテナー内にSVG を強制する方法ですが、意図した結果が生成されません。これは、svgがコンテナーに合うように絞られている私の応答の最後の例と同じです
H. Figueiredo

説明は少し混乱するかもしれませんが、ソリューションでは、svgの高さがコンテナの高さに適応することが示唆されています。
thetont

ただし、SVGのアスペクト比は維持されません。OPが投稿した望ましい結果を見ましたか?
H.フィゲイレド

ああ、すごい... Chromeで確認したところ、あなたの言っていることがわかりました。私はそれをFirefoxでコーディングしましたが、そのブラウザーでは意図したとおりに機能し、結果がそれほど異なるとは思っていませんでした。私の悪い
thetont

これは実際にはかなり興味深い動作です。FirefoxとChromeの計算が100%異なると思いますか?とにかく、私たちは皆間違いを犯します、そうでなければSOは存在しません:D
H. Figueiredo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.