2


Hey! Thanks for reading! I've got a web-app login screen. I'm focusing on creating a responsive app-like login page. (no scroll etc)

Issue description:

  • With a viewport-width of 300px, at 463px and shorter viewport heights, all items fill the entirety of the screen, and the content at the bottom of the page begin to get cut off.

  • The same can be said with 528px and 650px height.

  • (so this tells me it's scaling to a particular aspect ratio (phone portrait to relatively squarish aspect ratios. At landscape aspect-ratios, the images become ridiculously big - ...expected but undesired))

Goal: Instead, I would simply like the images to shrink in height and maintain their aspect ratio when the viewport height is changed. (to support the aspect ratio provided by the flex-grow/shrink) as opposed to overflowing and changing that ratio.

note: For those who'd like a simpler example: I think the example is relatively simple. Could it be simpler?, yeah most likely. I'm, not entirely sure what I'd make simpler though.

Codepen: https://codepen.io/gold240sx/pen/eYVdGag (I might suggest to turn devtools on to get a thin width since the design right now is really meant for portrait phones.)

It's quite a bit easier just to copy and paste into whatever editor you prefer.

ORIGINAL:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
 <style>
    * {
        box-sizing: border-box;
    }

    body {
        height:100%; 
        width: 100%; 
        padding: 0; 
        margin: 0; 
        display: flex; 
        flex-direction: column; 
        justify-content: center;
        overflow-x: hidden;
        overflow-y: hidden;
    }

    .container {
        background-color: rgb(162, 162, 162);
        display: flex;
        flex-direction: column;
        min-height: fit-content;
        height: 100%;
    }
    .images{
        background-color: aqua; 
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        width: 100%; 
        flex-grow: 3;
        flex-shrink: 3;
    }

    span img {
        max-width: 100%;
        max-height: 100%;
    }
    .mainImage {
        background-color: rgb(128, 248, 0);
        display: flex;
        max-width: 70%;
        max-height: 100%;

        margin-left: auto;
        margin-right: auto;
    }
    .secondaryImage{
        background-color: rgb(133, 201, 153);
        max-width: 90%;
        position: relative;
        width: auto;

        margin-left: auto;
        margin-right: auto;
    }

    .allButtons {
        background-color: rgb(255, 132, 0);
        display: flex;
        flex-direction: column;
        border: 2px red solid;
        flex-grow: 2;
        flex-shrink: 2;
    }

    .mainButtons{
        display: flex;
        flex-direction: column;
        width: 70%;
        justify-content: space-evenly;

        background-color: rgb(249, 149, 0);
        padding: 5px 0px;
        margin-left: auto;
        margin-right: auto;
        position: relative;
        height: 100%;
    }

    button {
        background-color: rgb(205, 205, 0);
        border: black solid 2px;
        border-radius: 5px;
        width: 100%;
        color: white;
        padding: 20px;
        display: block;
    }


    .bottomButtonContainer {
        width: 100%;
        display: flex; 
        align-items: center;
        justify-content: end;
        margin-top: auto;
    }

    .bottomButton {
        background-color: rgb(101, 103, 0);
        border-radius: 5px 5px 0px 0px;
        margin-left: auto;
        margin-right: auto;
        width: 70%;
        height: 40px;
    }


 </style>
</head>
<body>
    <div class="container">
     <div class="images" style="background-color: aqua; width: 100%; flex-grow: 3; flex-basis: 1;">
      <span class="mainImage">
       <img src="https://i.ibb.co/5YMMtJT/circle-logo-color.png" alt="circle-logo-color">
      </span>
      <span class="secondaryImage">
       <img src="https://i.ibb.co/H4qPCc9/logo-color.png" alt="logo-color">
      </span>
    </div>
    <div class="allButtons">
     <div class="mainButtons">
      <button>SIGNUP!</button>
      <button>LOGIN!</button>
     </div>
      <div class="bottomButtonContainer">
       <button class="bottomButton" style="white-space: nowrap;">LEARN MORE</button>
      </div>
    </div>
</div>

UPDATED CSS (loosely based upon the initial answer provided by Chizaram) - image scale achieved - image aspect ratio not guaranteed yet -:

        }
    * {
        box-sizing: border-box;
        padding: 0; 
        margin: 0; 
    }

    body {
        height:100%; 
        width: 100%; 
        overflow: hidden;
    }

    .container {
        background-color: rgb(162, 162, 162);
        display: flex;
        flex-direction: column;
        min-height: fit-content;
        height: 100vh;
    }

    .images{
        background-color: aqua;
        height: 70vh; 
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
    }

    .mainImage img,
    .secondaryImage img {
        max-height: 100%;
        max-width: 100%;
    }

    .mainImage {
        background-color: rgb(128, 248, 0);
        max-height: 60vw;
        margin: 0 auto;
        display: flex;
        justify-content: center;
    }

    .secondaryImage{
        background-color: rgb(133, 201, 153);
        min-height: 30%;
        max-width: 90vw;
        max-height: 40%;
        margin: 0 auto;
        display: flex;
        justify-content: center;
    }

    .allButtons {
        display: flex;
        flex-direction: column;
        border: 2px red solid;
        height: 30vh;
    }

    .mainButtons{
        display: flex;
        flex-direction: column;
        width: 70%;
        justify-content: space-evenly;
        /* background-color: rgb(249, 149, 0); */
        padding: 5px 0px;
        margin-left: auto;
        margin-right: auto;
        position: relative;
        height: 100%;
    }

    button {
        background-color: rgb(205, 205, 0);
        border: black solid 2px;
        border-radius: 5px;
        width: 100%;
        color: white;
        padding: 10px;
        display: block;
    }


    .bottomButtonContainer {
        width: 100%;
        display: flex; 
        align-items: center;
        justify-content: end;
        margin-top: auto;
    }

    .bottomButton {
        background-color: rgb(101, 103, 0);
        border-radius: 5px 5px 0px 0px;
        margin-left: auto;
        margin-right: auto;
        width: 70%;
        height: 40px;
    }
Michael Martell
  • 141
  • 2
  • 16

2 Answers2

3

UPDATE:

Do not forget to remove the old inline styles you declared in the .images div, so they don't revert to previous styling:

<div class="images">...</div> <!-- Remove old inline styles --> 

ANSWER:

To achieve this, here are the changes you need to make to your code:

(Please note that I use ellipsis ... to indicate segments of the original code which I did not change, and also for brevity.)

  1. Remove flex properties from the body selector as they are not necessary here. The .container div houses everything on the page. I also cleaned the body rule-set a little by moving the padding and margin properties to the universal selector rule-set as well as using the briefer overflow declaration.

    * {
        box-sizing: border-box;
        padding: 0;
        margin: 0;
    }
    
    body {
        height: 100%;
        width: 100%;
        overflow: hidden;
    }
    
  2. Leave flex properties in the container selector instead and change its height to 100vh to take up full viewport of the screen.

    .container {
            background-color: rgb(162, 162, 162);
            display: flex;
            flex-direction: column;
            min-height: fit-content;
            height: 100vh;
        }
    
  3. Give the .images div a height of 70vh and set the vertical and horizontal alignments to center. I also removed the flex-grow and flex-shrink properties because they were not necessary in order to achieve the desired result.

    .images {
        ...
        height: 70vh;
        display: flex;
        flex-direction: column; 
        justify-content: center; /* Vertical alignment in column flex-direction */ 
        align-items: center; /* Horizontal alignment in column flex-direction */
    }
    
  4. Set max widths and heights for center images and their parent divs (totaling 100%). Flex and positioning properties aren't necessary here as well since they are affected by their parent div (.images).

    .mainImage {
        ...
        max-width: 60%;
        max-height: 60%;
        margin: 0 auto;
    }
    
    .secondaryImage {
        ...
        max-width: 60%;
        max-height: 40%;
        margin: 0 auto;
    }
    
  5. Set object-fit type to contain for images. I've also changed the elements from spans to divs to structure the html better. The styles here were previously within the span img rule-set. Copy its styles in this new rule-set and delete it.

    .mainImage img,
    .secondaryImage img {
        ...
        object-fit: contain;
    }  
    
  6. Set the height of the .allButtons div to 30vh to take up the remaining height of the viewport.

    .allButtons {
        ... 
        height: 30vh;
        ...
    }
    
  7. Reduce padding for buttons on smaller screen sizes to solve the height problem. I added in a media query to adjust to original button size on larger screens. Feel free to adjust the breakpoint height to any value you desire.

    button {
        ...
        padding: 10px;
        ...
    }
    
    @media screen and (min-height: 620px) {
        button {
            padding: 20px;
        }
    }
    

The HTML

   <div class="mainImage">
     ...
   </div>
   <div class="secondaryImage">
     ...
   </div>
Chizaram Igolo
  • 907
  • 8
  • 18
  • Hey, Thank you for spending so much time breaking down the changes and fixes! You really helped a lot! Your code (for me at least) had images going outside of the page but I liked the behavior so I built off of it! And sure enough I was quickly able to make the few fixes necessary. Mainly the images were not scaling to size due to the object-fit: continue property. I have a fully scaleable images now, mainly thanks to you, the only issue is that on long portrait screens there images stretch, because I needed to replace the object fit with min and max-heights. Removing the min-heights ensures – Michael Martell May 13 '22 at 17:33
  • that the images will stay in proportion but when I resize the screen, the images remain at whatever the smallest size was. I guess I could include a JS event listener on window resize to "refresh the image to update the images height/width and maintain an aspect ratio (yes I tried the aspect ratio property on the images but it just ended up causing the image to overflow off the viewport on long portrait viewports.) Everything seems to be working well across safari / chrome and cellular: I think its pretty close. Just need to stop the vertical stretching. – Michael Martell May 13 '22 at 17:46
  • I also wanted to give you the opportunity for an approved answer. I updated the original post with where I'm at. (2nd set CSS Only). – Michael Martell May 13 '22 at 17:56
  • also, I realize in the above comment I said continue. In testing, I of course used contain as you specified. – Michael Martell May 13 '22 at 17:58
  • I also realized my update looks good in responsive portrait and landscape but breaks in mobile landscape, so I may have to adjust a few properties to that... – Michael Martell May 13 '22 at 18:03
  • Glad that you found it helpful. A JS event listener won't be necessary since you just want the image to respond to difference screen sizes. At the very most, media queries should be sufficient for responsive image display. Okay, I will take a look at the second CSS. – Chizaram Igolo May 13 '22 at 18:06
  • 1
    In the mean time, have a look at my solution put together here: https://codepen.io/chizaram-igolo/pen/JjpbKvB and see if there anything that was missed in the answer. – Chizaram Igolo May 13 '22 at 18:20
  • Okay, try this; change the max-width and max-height properties of the images to just width and height. Set their object-fit property to 'cover' to prevent the stretching (but with the tradeoff of losing some of the images' area) Then, set the width of the .images div (the parent of the parent divs of the images) to 70vw or something higher. Tweak the dimensions of the parent divs of the images to see which values produce the best results. – Chizaram Igolo May 13 '22 at 19:43
  • 1
    I'm currently involved in some other activity so I can't confirm anything now but follow the instructions at this link and see if they help you achieve your desired result. https://pqina.nl/blog/resize-images-proportionally-while-keeping-the-aspect-ratio/ – Chizaram Igolo May 13 '22 at 19:44
  • Got it. I provided the answer. There may be a cleaner way to do it ( one that doesn't depend on vh or vw.) but I'm happy with it for now. Send me a private msg with your info and we can stay in chat, and I'll send you that gift card I mentioned! I did wind up defining the heights by flex grow / shrink since they forced the images to not extend past their respective boxes: Images / allButtons whereas defining the height based on % or vh caused image and image/button overlap. Anywho, let me know what you think! – Michael Martell May 13 '22 at 21:17
  • I've seen your answer, it's really good. I saw what you did with the flex grow and shrink as well. Well done! Thank you for your kindness but you don't need to, the resolution to your question is rewarding enough. :) – Chizaram Igolo May 14 '22 at 03:15
1

I think I have It!! Both Portrait and Landscape. Granted, because of the use of vh / vw, It may have issues with mobile-browser header bars. :/ Maybe there's some Hacky way to fix. but yeah this is looking good so far. I'd have to test on mobile to see further. Galaxy fold it seems to cut off just a bit off the bottom (just a few px.) In addition, Id take all this CSS and wrap it into a media screen itself, then transitioning into a scrollable webpage... or maybe not. Anyways here's the code... Thank you Chizaram for all you're help! I'm gonna buy you a gift card on payday if you like!

ANSWER:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>webApp</title>
    <style>
        * {
            box-sizing: border-box;
            padding: 0; 
            margin: 0; 
        }

        body {
            height:100%; 
            width: 100%; 
            overflow: hidden;
        }

        .container {
            background-color: rgb(162, 162, 162);
            display: flex;
            flex-direction: column;
            min-height: fit-content;
            height: 100vh;
        }

        .images{
            background-color: aqua;
            flex-grow: 1; 
            flex-shrink: 3;
            display: flex;
            flex-direction: column;
            justify-content: space-around;
            align-items: center;
        
        }

        .mainImage img,
        .secondaryImage img {
            object-fit: contain;
            display: flex;
            justify-self: center;
        }

    .mainImage img {
        max-height: 25vh;
    }

    .secondaryImage img {
        max-height: 20vh;
        width: 100%;
        max-width: 90vw;
    }

    .mainImage {
        background-color: rgb(128, 248, 0);
        max-height: 60vw;
        margin: 0 auto;
        display: flex;
        justify-content: center;
        object-fit: contain;
    }

    .secondaryImage{
        background-color: rgb(133, 201, 153);
        min-height: 30%;
        width: 90vw;
        max-height: 40%;
        margin: 0 auto;
        display: grid;
        align-content: center;
        object-fit: contain;
    }

    .allButtons {
        display: flex;
        flex-direction: column;
        border: 2px red solid;
        height: 30vh;
        flex-grow: 2; 
        flex-shrink: 1;
    }

    .mainButtons{
        display: flex;
        flex-direction: column;
        width: 70%;
        justify-content: space-evenly;
        /* background-color: rgb(249, 149, 0); */
        padding: 5px 0px;
        margin-left: auto;
        margin-right: auto;
        position: relative;
        height: 100%;
    }

    button {
        background-color: rgb(205, 205, 0);
        border: black solid 2px;
        border-radius: 5px;
        width: 100%;
        color: white;
        padding: 2em;
        display: block;
        min-width: fit-content;
    }


    .bottomButtonContainer {
        width: 100%;
        display: flex; 
        align-items: center;
        justify-content: end;
        margin-top: auto;
    }

    .bottomButton {
        background-color: rgb(101, 103, 0);
        border-radius: 5px 5px 0px 0px;
        margin-left: auto;
        margin-right: auto;
        width: 70%;
        height: 40px;
    }

    @media only screen
    and (max-device-width: 1023px)
    /* and (min-device-pixel-ratio : 2.0) */
    and (orientation: landscape) {

        button {
            padding: 1em;
        }

    }
    </style>
</head>

<body>
    <div class="container">
        <div class="images">
            <span class="mainImage">
                <img src="https://i.ibb.co/5YMMtJT/circle-logo-color.png" alt="circle-logo-color">
            </span>
            <span class="secondaryImage">
                <img src="https://i.ibb.co/H4qPCc9/logo-color.png" alt="logo-color">
            </span>
        </div>
        <div class="allButtons">
            <div class="mainButtons">
                <button>SIGNUP!</button>
                <button>LOGIN!</button>
            </div>
            <div class="bottomButtonContainer">
                <button class="bottomButton" style="white-space: nowrap;">LEARN MORE</button>
            </div>
        </div>
    </div>
</body> 
</html>
Michael Martell
  • 141
  • 2
  • 16
  • 1
    Wow! This is wonderful! It looks good here on my end as well. For the mobile-browser header bars, you can set for .container div `height: calc(100vh - {height of header bar})` and `margin-top: {height of header bar}` within a CSS media query that detects only mobile devices. Here's how you can detect only mobile screens: https://stackoverflow.com/a/62793120/11838606. Well done! Thank you for your kindness but helping find the solution to your question is enough reward for me. :) – Chizaram Igolo May 14 '22 at 03:21