0

None of the answers I've looked up quite works for my use case.

I want to fix the aspect ratio of a HTML element on my page (specifically, a canvas which I want to always be square) in such a way that

  • it's as large as fits in the alloted space;
  • it fits inside the browser window without scrolling.

I don't think this can be done by CSS alone (please prove me wrong). I did find various CSS tricks purported to do it, but they take into account only either the available width or the available height, not both.

I tried javascript that looks up the size (.parentElement.clientWidth and .parentElement.clientHeight) of the parent element, finds the smaller one and sizes the canvas according to that by setting canvas.style.width and canvas.style.height, but for some reason I don't understand this doesn't work - the canvas ends up too small and only resizes to the correct setting on a window resize. In this case, the parent element's size was determined by flexbox.

EDIT: the following code does almost what I am looking for. There is only one problem, which you can observe by:

  • loading the page in a non-maximed window
  • maximizing and un-maximizing that window.

The resulting layout is not the same as the original (directly after the load).

<!DOCTYPE html>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
    body {
        margin: 0;
        background: #404040;
        height: 100vh;
        min-width: 800px;
        display: flex;
        justify-content: center;
        align-items: stretch;
    }
    main {
        background: yellow;
        flex: 0 1 100vh;
        display: flex;
        flex-direction: column;
    }
    .sidepanel {
        background: blue;
        flex: 0.2 0.4 250px;
        text-align: center;
    }
    .spacer {
        flex: 0.5 1 0;
    }
    #square {
        background: black;
        margin: auto;
    }
</style>
<script type="module">
    const canvas = document.querySelector('#square')
    const parent = canvas.parentElement
    const setSquare = () => {
        const { clientWidth, clientHeight } = parent
        const L = Math.min(clientWidth, clientHeight)
        canvas.style.width = canvas.style.height = `${L}px`
    }
    window.addEventListener('resize', setSquare)
    setSquare()
</script>
<div class="spacer"></div>
<section class="sidepanel">
</section>
<main>
    <canvas id="square"></canvas>
</main>
<section class="sidepanel">
</section>
<div class="spacer"></div>
  • https://www.w3schools.com/howto/howto_css_aspect_ratio.asp – tacoshy May 20 '21 at 10:15
  • Does this answer your question? [Use flexbox and maintain a 1:1 aspect ratio even though content is sized differently](https://stackoverflow.com/questions/44009015/use-flexbox-and-maintain-a-11-aspect-ratio-even-though-content-is-sized-differe) – tacoshy May 20 '21 at 10:16

0 Answers0