0

I have the following page showing the HTML as well as the CSS. I want the five buttons on the left (div id=button1..5) to always be square at any aspect ratio and resolution of the screen. Also, I want the five buttons to always fill the middle div (id=menu). In fact, I AM ABLE TO DO BOTH, but NOT TOGETHER! The latter is easy with Flex and the former as you can see I have done in the code below. I have looked at several examples on SO, notably this one, but they don't do what I am talking about.

Any suggestions? Note: Preferably no Javascript...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style>
html, body {
    margin:0;
    padding:0;
}
#container {
    display:flex;
    flex-direction: column;
    background-color: #444;
    height:100vh;
    width:100%;
    margin:0;
    padding:0;
}
#top{
    background-color: #777;
    height:5%;
    width:100%;
    margin:0;
    padding:0;  
}
#main{
    background-color: #DDD;
    height:100%;
    width:100%; 
    margin:0;
    padding:0;
    align-items: stretch;
}
#menu{
    display:flex;
    flex-direction: column;
    background-color: #FFF;
    height:100%;
    width:10%;
    margin:0;
    padding:0;  
}
.buttons{
    display:inline-block;
    position:relative;
    height:0;
    margin:0;
    padding-bottom:100%;
}
#button1{background-color:blue; margin:2px 0 2px 0;}
#button2{background-color:green; margin:2px 0 2px 0;}
#button3{background-color:red; margin:2px 0 2px 0;}
#button4{background-color:black; margin:2px 0 2px 0;}
#button5{background-color:orange; margin:2px 0 2px 0;}
.img-container {
  justify-content: center;
  display: flex;
  flex-direction: row;
  overflow: hidden;
  padding:16px;
}
.img-container .img-to-fit {
  flex: 1;
  height: 100%;
}

.fill {
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden
}
.fill img {
    flex-shrink: 0;
    min-width: 100%;
    min-height: 100%
}

#bottom {
    height:2%;
    display:flex;
}
#bottom1{background-color:blue;}
#bottom2{background-color:green;}
#bottom3{background-color:red;}
#bottom4{background-color:white;}
#bottom5{background-color:orange;}
.bottoms{
    height:100%;
    width:20%;
    margin:0;
    padding:0;
}
</style>
</head>

<body>
    <div id="container">
        <div id="top"/>
        <div id="main">
             <div id="menu">
                <div id="button1" class="buttons">
                     <div class="img-container">
                         <img class="img-to-fit" src="parcel.png" />
                     </div>         
                </div>
                <div id="button2" class="buttons"/>
                <div id="button3" class="buttons"/>
                <div id="button4" class="buttons"/>
                <div id="button5" class="buttons"/>
            </div>
        </div>
        <div id="bottom">
                <div id="bottom1" class="bottoms"/>
                <div id="bottom2" class="bottoms"/>
                <div id="bottom3" class="bottoms"/>
                <div id="bottom4" class="bottoms"/>
                <div id="bottom5" class="bottoms"/>
        </div>
    </div>
</body>
</html>
41 72 6c
  • 1,600
  • 5
  • 19
  • 30
Chiwda
  • 1,233
  • 7
  • 30
  • 52

2 Answers2

1

You already have squared buttons. The thing you miss is the width of those buttons but it's something you can calculate easily.

The div #menu has a height of 100vh - 7%, it means that your buttons should have a height of (100vh - 7%) / 5.
Their height ise equal to their width, so if they have width: calc(93vh / 5) they will fill the height of the #menu.

Therefore, you can simply add #menu { width: calc(93vh / 5)}

I would also remove #main { height: 100% }, it's not needed.

html, body {
    margin:0;
    padding:0;
}
#container {
    display:flex;
    flex-direction: column;
    background-color: #444;
    height:100vh;
    width:100%;
    margin:0;
    padding:0;
}
#top{
    background-color: #777;
    height:5%;
    width:100%;
    margin:0;
    padding:0;  
}
#main{
    background-color: #DDD;
    /* height:100%; not needed */
    width:100%; 
    margin:0;
    padding:0;
    align-items: stretch;
}
#menu{
    display:flex;
    flex-direction: column;
    background-color: #FFF;
    height:100%;
    width: calc((93vh) / 5); // Width of the menu = Height of the menu divided by the number of buttons
    margin:0;
    padding:0;  
}
.buttons{
    display:block;
    position:relative;
    height:0;
    margin:0;
    padding-bottom:100%;
}
#button1{background-color:blue; margin:2px 0 2px 0;}
#button2{background-color:green; margin:2px 0 2px 0;}
#button3{background-color:red; margin:2px 0 2px 0;}
#button4{background-color:black; margin:2px 0 2px 0;}
#button5{background-color:orange; margin:2px 0 2px 0;}
.img-container {
  justify-content: center;
  display: flex;
  flex-direction: row;
  overflow: hidden;
  padding:16px;
}
.img-container .img-to-fit {
  flex: 1;
  height: 100%;
}

.fill {
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden
}
.fill img {
    flex-shrink: 0;
    min-width: 100%;
    min-height: 100%
}


#bottom {
    height:2%;
    display:flex;
}
#bottom1{background-color:blue;}
#bottom2{background-color:green;}
#bottom3{background-color:red;}
#bottom4{background-color:white;}
#bottom5{background-color:orange;}
.bottoms{
    height:100%;
    width:20%;
    margin:0;
    padding:0;
}
<div id="container">
    <div id="top">
    </div>
    <div id="main">
        <div id="menu">
            <div id="button1" class="buttons">
                <div class="img-container">
                  <img class="img-to-fit" src="parcel.png" />
                </div>          
            </div>
            <div id="button2" class="buttons">

            </div>
            <div id="button3" class="buttons">

            </div>
            <div id="button4" class="buttons">

            </div>
            <div id="button5" class="buttons">

            </div>
        </div>
    </div>
    <div id="bottom">
            <div id="bottom1" class="bottoms">

            </div>
            <div id="bottom2" class="bottoms">

            </div>
            <div id="bottom3" class="bottoms">

            </div>
            <div id="bottom4" class="bottoms">

            </div>
            <div id="bottom5" class="bottoms">

            </div>
    </div>
</div>
Amaury Hanser
  • 3,191
  • 12
  • 30
  • This worked! Is there any way to not use 93vh and use 100% of the parent of the buttons? I ask because the upper/lower bars may change in the future. – Chiwda May 29 '19 at 08:37
  • What if the Top and Bottom were not expressed as a percentage but as fixed pixels? – Chiwda May 29 '19 at 11:46
  • @Chiwda It's just a calculus. *93vh = 100vh - (topHeight + bottomHeight)*, so you just need to do: **`calc((100vh - (topHeight + bottomHeight)) / 5)`**. – Amaury Hanser May 29 '19 at 11:58
  • I just found that it is not working in Chrome. Any ideas? – Chiwda May 29 '19 at 17:14
  • @Chiwda I've just tested in Chrome 74.0.3729.169, it works. – Amaury Hanser May 29 '19 at 19:14
  • The problem appears to be that the #Top is currently empty. And so Chrome renders it at 0 height - which means that the 93vh does not áppear' to fill the space whereas it is. This explains it: https://stackoverflow.com/questions/35532987/heights-rendering-differently-in-chrome-and-firefox So I have to figure out a way around that. – Chiwda May 30 '19 at 04:33
  • 1
    I'm glad you made it ! – Amaury Hanser May 30 '19 at 08:44
0

Try using https://css-tricks.com/aspect-ratio-boxes/ with padding as a container. Make the content with position: absolute to fill the container. It should always keep the proportions this way.

mjanisz1
  • 1,478
  • 3
  • 17
  • 43