如何将一个正方形放入一个长方形中?

huangapple go评论107阅读模式
英文:

How to fit a square into a rectangle?

问题

我尝试将一个正方形放入一个矩形中。我使用了max-widthmax-heightaspect-ratio,但它只在竖屏模式下起作用,在横屏模式下失败。这显示了Firefox的渲染效果:

如何将一个正方形放入一个长方形中? 如何将一个正方形放入一个长方形中?

这是示例。

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->
function portrait() {
  document.body.style.width = "10em";
  document.body.style.height = "14em";
}

function landscape() {
  document.body.style.width = "14em";
  document.body.style.height = "10em";
}

document.getElementById("button0").addEventListener('click', portrait);
document.getElementById("button1").addEventListener('click', landscape);

portrait();
<!-- language: lang-css -->
html, body {
  margin: 0;
}
#page {
  height: 100%;
  box-sizing: border-box;
  border: 1ex solid blue;
  display: grid;
  grid-template-rows: auto min-content;
}
.square {
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1 / 1;
}
canvas {
  box-sizing: border-box;
  border: 1ex solid red;
  display: block;
  width: 100%;
  height: 100%;
}
.buttons {
  box-sizing: border-box;
  border: 1ex solid green;
  width: 100%;
}
<!-- language: lang-html -->
<div id="page">
  <div class="square">
    <canvas width="100" height="100">
    </canvas>
  </div>
  <div class="buttons">
    <input id="button0" type="button" value="Works"/>
    <input id="button1" type="button" value="Fails"/>
  </div>
</div>
<!-- end snippet -->

如何将红色和绿色的框放入蓝色的框中?

英文:

I try to fit a square into a rectangle. I used max-width, max-height and aspect-ratio, but it works only in portrait mode and fails in landscape mode. This shows how Firefox renders it:

如何将一个正方形放入一个长方形中? 如何将一个正方形放入一个长方形中?

This is the example.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function portrait() {
  document.body.style.width = &quot;10em&quot;;
  document.body.style.height = &quot;14em&quot;;
}

function landscape() {
  document.body.style.width = &quot;14em&quot;;
  document.body.style.height = &quot;10em&quot;;
}

document.getElementById(&quot;button0&quot;).addEventListener(&#39;click&#39;, portrait);
document.getElementById(&quot;button1&quot;).addEventListener(&#39;click&#39;, landscape);

portrait();

<!-- language: lang-css -->

html, body {
  margin: 0;
}
#page {
  height: 100%;
  box-sizing: border-box;
  border: 1ex solid blue;
  display: grid;
  grid-template-rows: auto min-content;
}
.square {
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1 / 1;
}
canvas {
  box-sizing: border-box;
  border: 1ex solid red;
  display: block;
  width: 100%;
  height: 100%;
}
.buttons {
  box-sizing: border-box;
  border: 1ex solid green;
  width: 100%;
}

<!-- language: lang-html -->

&lt;div id=&quot;page&quot;&gt;
  &lt;div class=&quot;square&quot;&gt;
    &lt;canvas width=&quot;100&quot; height=&quot;100&quot;&gt;
    &lt;/canvas&gt;
  &lt;/div&gt;
  &lt;div class=&quot;buttons&quot;&gt;
    &lt;input id=&quot;button0&quot; type=&quot;button&quot; value=&quot;Works&quot;/&gt;
    &lt;input id=&quot;button1&quot; type=&quot;button&quot; value=&quot;Fails&quot;/&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

How to fit the red and green boxes into the blue box?

答案1

得分: 1

I've managed to get it to work using container-type. There are nifty container units called cqmin and cqmax. cqmin is the minimum of the inline and block container size, which is handy when the aspect ratio changes. By declaring the square as a container and using the size value rather than inline-size and setting the width of the canvas to be 100cqmin, it fills the height or the width of the grid item, depending on what is the smaller container size (because the size value looks at both the block and inline lengths). Thankfully container queries seem to be nearly universally supported.

<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function portrait() {
  //I changed these from em to px so I could make sure the body and #page div sizes were as specified.
  document.body.style.width = "250px";
  document.body.style height = "300px";
}

function landscape() {
  document.body.style.width = "300px";
  document.body.style.height = "250px";
}

document.getElementById("button0").addEventListener('click', portrait);
document.getElementById("button1").addEventListener('click', landscape);

portrait();
<!-- language: lang-css -->
* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
}

#page {
  height: 100%;
  border: 1ex solid blue;
  display: grid;
  grid-template-rows: 1fr auto;
}

.square {
  container-type: size; /* make it size and not inline-size so the units work for both inline and block dimensions */
}

canvas {
  border: 1ex solid red;
  display: block;
  width: 100cqmin; /* this is the secret sauce */
  aspect-ratio: 1/1;
}

.buttons {
  border: 1ex solid green;
  width: 100%;
}
<!-- language: lang-html -->
<div id="page">
  <div class="square">
    <canvas width="100" height="100"></canvas>
  </div>
  <div class="buttons">
    <input id="button0" type="button" value="Works"/>
    <input id="button1" type="button" value="Works!!!!"/>
  </div>
</div>
<!-- end snippet -->
英文:

I've managed to get it to work using container-type. There are nifty container unit called cqmin and cqmax. cqmin is the minimum of the inline and block container size which is handy when the aspect ratio changes. By declaring the square as a container and using the size value rather than inline-size and setting the width of the canvas to be 100cqmin it fills the height or the width of the grid item, depending on what is the smaller container size (because the size value looks at both the block and inline lengths) Thankfully container queries seem to be nearly universally supported.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function portrait() {
  //I changed these from em to px so I could make sure the body and #page div sizes were as specified.
  document.body.style.width = &quot;250px&quot;;
  document.body.style.height = &quot;300px&quot;;
}

function landscape() {
  document.body.style.width = &quot;300px&quot;;
  document.body.style.height = &quot;250px&quot;;
}

document.getElementById(&quot;button0&quot;).addEventListener(&#39;click&#39;, portrait);
document.getElementById(&quot;button1&quot;).addEventListener(&#39;click&#39;, landscape);

portrait();

<!-- language: lang-css -->

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
}

#page {
  height: 100%;
  border: 1ex solid blue;
  display:grid;
  grid-template-rows: 1fr auto;
}

.square {
  container-type: size; /* make it size and not inline-size so the units work for both inline and block dimensions */
}

canvas {
  border: 1ex solid red;
  display: block;
  width: 100cqmin; /* this is the secret sauce */
  aspect-ratio: 1/1;
}

.buttons {
  border: 1ex solid green;
  width: 100%;
}

<!-- language: lang-html -->

&lt;div id=&quot;page&quot;&gt;
  &lt;div class=&quot;square&quot;&gt;
   &lt;canvas width=&quot;100&quot; height=&quot;100&quot;&gt;&lt;/canvas&gt;
  &lt;/div&gt;
  &lt;div class=&quot;buttons&quot;&gt;
    &lt;input id=&quot;button0&quot; type=&quot;button&quot; value=&quot;Works&quot;/&gt;
    &lt;input id=&quot;button1&quot; type=&quot;button&quot; value=&quot;Works!!!!&quot;/&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

答案2

得分: 0

尝试使用orientation@container规则!MDN文档

注意:如果要根据实际页面尺寸更改@container,请将其更改为@media

function portrait() {
  document.body.style.width = "10em";
  document.body.style.height = "14em";
}

function landscape() {
  document.body.style.width = "14em";
  document.body.style.height = "10em";
}

document.getElementById("button0").addEventListener('click', portrait);
document.getElementById("button1").addEventListener('click', landscape);

portrait();
html, body {
  margin: 0;
}
#page {
  height: 100%;
  box-sizing: border-box;
  border: 1ex solid blue;
  display: block;
  container-type: size;
}
#wrapper {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  height: 100%;
}
.square {
  aspect-ratio: 1 / 1;
}
@container (orientation: landscape) {
  .square {
    flex: 1;
    margin: auto;
  }
}

@container (orientation: portrait) {
  .square {
    width: 100%;
  }
}
canvas {
  box-sizing: border-box;
  border: 1ex solid red;
  display: block;
  width: 100%;
  height: 100%;
}
.buttons {
  box-sizing: border-box;
  border: 1ex solid green;
  width: 100%;
}
<div id="page">
  <div id="wrapper">
    <div class="square">
      <canvas>
      </canvas>
    </div>
    <div class="buttons">
      <input id="button0" type="button" value="Works"/>
      <input id="button1" type="button" value="Fails"/>
    </div>
  </div>
</div>
英文:

Try using orientation and @container rule!
MDN Documentation

Note: If you want to do it by real page size change the @container to @media

<!-- begin snippet: js hide: false console: true babel: null -->

<!-- language: lang-js -->

function portrait() {
  document.body.style.width = &quot;10em&quot;;
  document.body.style.height = &quot;14em&quot;;
}

function landscape() {
  document.body.style.width = &quot;14em&quot;;
  document.body.style.height = &quot;10em&quot;;
}

document.getElementById(&quot;button0&quot;).addEventListener(&#39;click&#39;, portrait);
document.getElementById(&quot;button1&quot;).addEventListener(&#39;click&#39;, landscape);

portrait();

<!-- language: lang-css -->

html, body {
  margin: 0;
}
#page {
  height: 100%;
  box-sizing: border-box;
  border: 1ex solid blue;
  display: block;
  container-type: size;
}

#wrapper {
display: flex;
flex-direction: column;
justify-content: flex-start;
height: 100%;
}
.square {
aspect-ratio: 1 / 1;
}
@container (orientation: landscape) {
.square {
flex: 1;
margin: auto;
}
}

@container (orientation: portrait) {
.square {
width: 100%;
}
}
canvas {
box-sizing: border-box;
border: 1ex solid red;
display: block;
width: 100%;
height: 100%;
}
.buttons {
box-sizing: border-box;
border: 1ex solid green;
width: 100%;
}

<!-- language: lang-html -->
<div id="page">
<div id="wrapper">
<div class="square">
<canvas>
</canvas>
</div>
<div class="buttons">
<input id="button0" type="button" value="Works"/>
<input id="button1" type="button" value="Fails"/>
</div>
</div>
</div>

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年3月9日 23:48:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75686958.html