How to have a DIV with fixed aspect ratio and max-height? (Pure CSS/no vh or vw)

610 views Asked by At

My initial problem like many others is to keep a DIV A with a fixed aspect ratio (pure CSS/no JS). It is intended to be reused in any parent DIV B regardless the sizing of B. DIV A should fit the smallest size of B.

DIV with fixed aspect ratio

In this animation, you can see the RED div that is always a square and that fits the outermost div smallest size.

No vh or vw or vmin or vmax is used and I don't want to use any of them because vh is sometimes no more reliable to really represent the viewport height (see CSS3 100vh not constant in mobile browser )

To do this, I used an image (grey rectangle) with a fixed aspect ratio (1/1 here), that expands to fit its parent. It works as follows:

  • 1) #container (thin dashed pink border) is the outermost DIV. It could be the full viewport or any DIV with a given size. Dimensions = H x contW
  • 2) #widthwrapper (blue border) height is H (height: 100%). It wraps the img.
  • 3) #imgwrapper is the image (big grey rectangle). Its height is also H (height: 100%). Since it is a square, its width = H.
  • 4) #widthwrapper wraps the img and its basic width is: fit-content = img width = H. Since its max-width = 100% you have #widthwrapper width = min(H, contW). So #widthwrapper is such as w x h = min(H, contW) x H. #widthwrapper si also position: relative.
  • 5) #content is position: absolute next to #widthwrapper and occupies the same space that #widthwrapper. So #content is such as w x h = min(H, contW) x H.
  • 6) #contentwrapper (dashed red) is vertically centered in #content. With the padding-bottom hack it is a square with width = 100%. So dimensions of #contentwrapper are w x h = min(H, contW) x min(H, contW).
  • <html>
    <head>
    <style>
    #container {top: 5px;left: 5px;right: 5px;bottom: 5px;position: fixed;border: 1px dashed pink;}
    *, *:before, *:after {box-sizing: content-box;}
    #widthwrapper {height: 100%;min-height:100%;max-height:100%;max-width: 100%;margin: auto;width: -moz-fit-content; width: -webkit-fit-content; width: fit-content;position: relative;outline: 1px solid blue;border: 1px dashed blue;}
    #imgwrapper {height: 100%;min-height: 100%;max-height: 100%;}
    #content {position: absolute;top: 0; bottom: 0; right: 0; left: 0;display: flex;flex-direction: column;justify-content: center;align-items: center;}
    #contentwrapper {height: 0;width: 100%;padding-bottom: 100%;outline: 3px dashed red;}
    </style>
    </head>
    
    <body>
    <div id="container">
        <div id="widthwrapper">
            <img id="imgwrapper" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Crect x='0' y='0' width='10' height='10' fill='none' stroke='black' stroke-opacity='0.3' /%3E%3C/svg%3E" />
            <div id="content">
                <div id="contentwrapper">
                </div>
            </div>
        </div>
    </div>
    </body>
    </html>
    

    BUT if on one side it works with Chrome/Safari, it is buggy with Firefox. Indeed, Firefox seems unable to include the image in #widthwrapper once resized. It resizes the image but #widthwrapper stays as if the image were w x h = 0 x 0. More generally, Firefox seems not to propagate to parent DIV an img width with no intrinsic size that is resized on an aspect ratio and height basis...

    problem with Firefox to wrap a resized image with no intrinsic size

    Any ideas to have this working with Firefox is welcome...(I have filled a bug at Bugzilla...if you fell to support it :-) ... https://bugzilla.mozilla.org/show_bug.cgi?id=1491936 )

    0

    There are 0 answers