Reputation: 773
I am centering a div
inside another div
using a flexbox. Think of a dialog window that pops up in the center of the screen when needed.
It works fine, however it would look much better if the space above and below the dialog was not exactly equal, having 40% of the remaining space be above and 60% below the dialog. It gets tricky because the dialog height varies with the amount of text inside.
So for example, if the browser height is 1000px, and the dialog window height is 400px, I want the remaining vertical space (600px) to be 240px above and 360px below the dialog.
I could do it with JavaScript, but I'm curious if there is some clever way with CSS. I tried adding a bottom margin to the #dialogBox
div
, but that doesn't work when the dialog height is getting near the browser height.
#dialogBoxPanel {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}
#dialogBox {
width: 350px;
}
<div id="dialogBoxPanel">
<div id="dialogBox">Text</div>
</div>
Upvotes: 23
Views: 719
Reputation: 274272
Use pseudo element and column direction to simulate the white space. Simply adjust the flex-grow
of the pseudo element to control how much free space each one should take. Equal flex-grow will give equal space:
#dialogBoxPanel {
position: absolute;
display: flex;
flex-direction: column;
align-items: center;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
/* the center */
background:linear-gradient(red,red) center/100% 1px no-repeat;
}
#dialogBox {
width: 350px;
border:1px solid;
}
#dialogBoxPanel:before {
content:"";
flex-grow:4;
}
#dialogBoxPanel:after {
content:"";
flex-grow:6;
}
<div id="dialogBoxPanel">
<div id="dialogBox">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc hendrerit diam eu nisl fringilla ornare. Pellentesque aliquam quam et tellus egestas sodales. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin bibendum,</div>
</div>
You can also use 2
and 3
. We simply need to keep the same ratio:
#dialogBoxPanel {
position: absolute;
display: flex;
flex-direction: column;
align-items: center;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
/* the center */
background:linear-gradient(red,red) center/100% 1px no-repeat;
}
#dialogBox {
width: 350px;
border:1px solid;
}
#dialogBoxPanel:before {
content:"";
flex-grow:2;
}
#dialogBoxPanel:after {
content:"";
flex-grow:3;
}
<div id="dialogBoxPanel">
<div id="dialogBox">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc hendrerit diam eu nisl fringilla ornare. Pellentesque aliquam quam et tellus egestas sodales. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin bibendum,</div>
</div>
Another idea is to use top value equal to 40%
and rectify the position with translate (same logic with the 50%
when centring)
#dialogBoxPanel {
position: absolute;;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
/* the center */
background:linear-gradient(red,red) center/100% 1px no-repeat;
}
#dialogBox {
position:relative;
top:40%;
width: 350px;
transform:translateY(-40%);
margin:auto;
border:1px solid;
}
<div id="dialogBoxPanel">
<div id="dialogBox">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc hendrerit diam eu nisl fringilla ornare. Pellentesque aliquam quam et tellus egestas sodales. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin bibendum,</div>
</div>
Upvotes: 11
Reputation: 100
Simple way using position and margin, i assumed that your dialog height is always 40% of browser height.
.modal{
max-height:50%;
width:400px;
margin: 10% auto 5% auto;
position:absolute;
top:0;
bottom:0;
right:0;
left:0;
overflow-y: auto
}
.modal-body{
background-color: beige;
padding: 20px;
line-height: 21px
}
HTML
<div class="modal">
<div class="modal-body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea </div>
</div>
Upvotes: 0
Reputation: 12161
This solution uses display: grid
, it's a new feature so be sure to check the browser support and click here to learn more.
This is the line that controls the top and bottom spaces:
grid-template-rows: 40fr [content-start] auto [content-end] 60fr;
The snippet text content can be edited for you to check that the box keeps centered even if the height changes.
#dialogBoxPanel {
display: grid;
place-content: center;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
grid-template-rows: 40fr [content-start] auto [content-end] 60fr;
}
#dialogBox {
border: 1px solid;
width: 350px;
grid-area: content;
}
<div id="dialogBoxPanel">
<div id="dialogBox" contenteditable>Text</div>
</div>
Upvotes: 5
Reputation: 10824
You can add spacers divs and set the flex-grow with 4:6 ratio.
#dialogBoxPanel {
position: absolute;
display: flex;
flex-direction: column;
align-items: center;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}
#dialogBox {
width: 350px;
border: 1px solid black;
}
.spacer-top{
flex-grow: 4;
}
.spacer-bottom{
flex-grow: 6;
<div id="dialogBoxPanel">
<div class="spacer-top"></div>
<div id="dialogBox">Text</div>
<div class="spacer-bottom"></div>
</div>
Upvotes: 5