I am creating a container using a flexbox with 3 rows which includes a header, the body and the footer. The height of the header and footer must remain fixed while the body portion can vary and will provide scrolling if its content exceeds it's visible height:
html
<div class="container">
<div class="header">
Header
</div>
<div class="contentBody">
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.
</div>
<div class="footer">
<span class="footerMessage">Message goes here</span>
<span class="footerBtn">OK</span>
<span class="footerBtn">Cancel</span>
</div>
css
.container {
display: flex;
flex-direction: column;
max-height: 50vh;
}
.header {
height: 20px;
background-color: #c0c0c0;
}
.contentBody {
flex-grow: 1;
overflow-y: scroll;
}
.footer {
background-color: #c0c0c0;
display: flex;
flex-direction: row;
}
.footerMessage {
flex-grow: 1;
}
.footerBtn {
padding: 5px;
background-color: #ff0000;
margin-left: 10px;
}
If you run the fiddle sample and adjust the width of the result that is shown, the height of the footer does not remain fixed. As you make it smaller, the red buttons within the footer don't remain inside the footer. How can I fix this? Thanks a million!
https://jsfiddle.net/Deepview/bktwkcgk/3/
Consider adding the following properties to your .footer:
.footer {
background-color: #c0c0c0;
display: flex;
flex-direction: row;
height: 20px;
min-height: 20px;
white-space: nowrap;
}
Setting a height and min height will ensure that the footer will remain fixed, even with a very small screensize, overflow: hidden will make sure that elements outside of your footer will not appear (hiding the overflowing element in question). white-space: nowrap; will avoid your footer message being cut off and falling into the second line.
Updated fiddle
Related
This question already has answers here:
Fill remaining vertical space with CSS using display:flex
(6 answers)
Closed 1 year ago.
I am learning flexbox and my goal is to create a simple flexbox of 3 items that would be responsive to a different device (smartphone, tablets, desktop…).
The items should be one on top of the other and together fill all the browser width and height.So basically there should never be a scroll.
(to sum up one item at the very top, one at the bottom of the page and the rest takes the left space inbetween).
The width part on desktop and smartphones seems to work. But how to fill the height of the browser and how the font and the boxes adapt to the different height of the different devices is still a mystery for me.
My temporary solution was to increase the margin for smartphone…
What are your thoughts?
Here is what I did:
.container {
display: flex;
flex-wrap: wrap;
width: 100%;
height: 100%;
font-size: 3em;
}
.item {
border: 5px solid red;
margin-bottom: 40px;
}
#media screen and (max-width: 500px) {
.element {
margin-bottom: 70px;
}
}
.one {
flex-basis: 100%;
display: flex;
}
.two {
flex-basis: 80%;
display: flex;
}
#media screen and (max-width: 64em) {
body {
font-size: 80%;
}
}
#media screen and (max-width: 50em) {
body {
font-size: 70%;
}
}
#media screen and (max-width: 30em) {
body {
font-size: 60%;
}
}
.three {
flex-basis: 100%;
}
<div class="container">
<div class="item one">1</div>
<div class="item two">
"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."
</div>
<div class="item three">3</div>
</div>
Simply use flex-grow: 1; to make a flex-item consume all remaining space within the conatainer.
First at all we need to reset the body margin: body { margin: 0; }
The body margin is set by the UA (default stylesheet of a browser) and as such differs between browsers. This will make it impossible to calculate the correct margins for all browsers and to prevent an overflow.
Next we need to give the flex-container a height to fill the entire viewport height: .container { height: 100vh; }. To emulate the body margin we give it now a padding aswell. To prevent an overflow we add box-sizing: border-box; as otherwise the padding would go on top of the 100vh and overflow vertically.
Then we apply flexbox and change the flex-direction to: .container { flex-direction: column; }
Last but not least we add the mentioned above flex-grow: .two { flex-grow: 1; }. This will make the middle item span the entire remaining height. Also to seperate them form the top and bottom box, we can add a margin like: .two { margin: 6px 0; }
As for the question of your font-size: It is impossible to set it correctly for all devices by using media-queries. It is the completely wrong approach. For that you need to do scripting. Alternativly you could use libraries which would make it easier. A good reference can be found here: Fitting Text to a Container
PS: You could also just simply get rid of the container itself and use the body as container directly in your markup.
body {
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100vh;
padding: 6px;
box-sizing: border-box;
}
.two {
flex-grow: 1;
margin: 6px 0;
}
.item {
border: 2px solid red;
}
/* Edit on OP request */
.two {
display: flex;
align-items: center;
}
<div class="container">
<div class="item one">1</div>
<div class="item two">
"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."
</div>
<div class="item three">3</div>
</div>
I will try to make this sound as easy as possible.
I am trying to place 2 div containers, side by side, and have them be the same height at all times.
The right div will be regular text. The amount of text in here will vary since I plan on using this for different pages.
The left div will be composed of 2 smaller containers - a title block, and an image block beneath it.
Here is a visual example of what I'm trying to achieve. The green box is supposed to be the full photo
Example Photo
I would like the photo in the image block of the left side to take up the full height/width of the box - (similar to background-position: cover that is used in CSS). I'd prefer to use a regular img tag instead of setting it as a div background.
The issue that I am having is that the image height on the left takes priority over the text box on the right hand side, and causes both containers to appear much longer than I want. I want the text block on the right to be prioritized, and the image block changes height based on that.
I've tried using object-fit: contain, but it isn't working, unfortunately. The closest I've gotten is to use width: 100%, but then it makes the height way too big.
Here's what I have so far:
.main {
display: flex;
}
.main .left {
width: 40%;
float: left;
}
.main .left .title {
background-color: black;
text-align: center;
display: block;
height: 90px;
padding: 50px;
color: white;
font-size: 40px;
}
.photo {
height: auto;
width: 100%;
}
.photo img {
width: 100%;
}
.main .right {
width: 60%;
float: right;
}
<div class="main">
<div class="left">
<div class="title">This is my Title</div>
<div class="photo"><img src="https://image.shutterstock.com/z/stock-photo-pastoral-green-field-with-long-shadows-in-tuscany-italy-275372477.jpg"></div>
</div>
<div class="right">
<p>text goes here lalalalalala</p>
<p>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.</p>
<p>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.</p>
</div>
</div>
<style>
.main {
display: flex;
}
.main .left {
width: 40%;
display: flex;
flex-direction: column;
}
.main .left .title {
background-color: black;
text-align: center;
display: block;
height: 90px;
padding: 50px;
color: white;
font-size: 40px;
}
.photo {
width: 100%;
overflow: hidden;
position: relative;
flex-grow: 1;
}
.photo img {
width: 100%;
position: absolute;
}
.main .right {
width: 60%;
}
</style>
Notes:
I made the image absolutely positioned so its own height won't stretch our flex row.
The image is being cropped by height. If the title is taller than the text (or the same height), you won't see the image at all.
I made the left column also display flex and the photo box flex grow so that the title can stay the same height and the photo box will stretch the rest of the way to match the right column.
We don't need float left/right for flex items.
So I have tried using flex styling to center my page which is what a lot of other experts have been telling me in past forums and never use floats. A lot of people suggest either using grid or flex depending on the situation when reducing the page from desktop to tablet and mobile for responsive website.
Here is what I was attempting to do and I got what I like in desktop.
Now the text went over the nav bar in mobile. I would like the image to stack on top and the text on the bottom. How do I fix that? And one more thing. When I tap on my hamburger icon, it blocks out the text and I would like to know how you can bring that down below the nav menu when I expand my menu. I know you can use media queries for when it reaches a certain amount of pixels, but I am not sure specifically what code to use. I know there is one that I like for example which is
display: block;
which works well when it is in a grid instead of flex.
Take a look at my code and tell me what can I do to fix this issue? Here is where I got the idea from using flex. https://css-tricks.com/centering-css-complete-guide/
1. Click on Both Horizontally and Vertically
2. Then click on Can you use flexbox
HTML
<div class="flex-Summary">
<div style="float: left;">
<img src="img/wallpaper1.jpg" style="width: 170px; height: 170px; border-radius:50%;">
</div>
<div style="float: right;">
<h2>Summary</h2>
<p style=" font-size: 20px;">
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.
</P>
</div>
</div>
CSS
.flex-Summary {
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.8);
}
In cases like this, you need to simplify things. I personally think Grid is overkill for you. Flexbox is sufficient for your layout. I've put together a stripped-down demo for you, including only the necessary HTML and CSS, so you can see how the layout works.
Some explanation…
First, the flex container is made to be at least the height of the viewport. With that in place, we can focus on the children. I tell the .content child to occupy the most space that is available using flex-grow: 1. The nav implicitly takes up the remaining space, which is what we want. All markup is part of the document flow and takes up "real" space. It seemed like something may have been absolutely positioned in your example, causing the overflow issues in mobile.
As far as vertically centering the image in the content area, I set it to margin: auto, which keeps it centered without adding complexity to the CSS.
I've included a link to the Fiddle here, and at the end of my answer.
body, html, p {
margin: 0;
}
body,
.container {
min-height: 100vh;
}
.container {
display: flex;
flex-direction: column;
}
nav {
padding: 1em;
background-color: #002eae;
}
nav a {
color: white;
}
.content {
background-color: white;
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
}
.content-summary {
width: 500px;
max-width: 100%;
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 1em 1.5em;
display: flex;
}
.content-summary img {
flex-shrink: 0;
width: 100px;
height: 150px;
padding-right: 10px;
margin: auto;
}
<div class="container">
<nav>
Link 1
Link 2
Link 3
Link 4
Link 5
</nav>
<div class="content">
<div class="content-summary">
<img src="https://placekitten.com/200/300" alt="">
<p>
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.
</p>
</div>
</div>
</div>
http://jsfiddle.net/wzgs5mc2/2/
Alright so this is the third time I've looked for help on a particular element I'm working on in an app so I apologize for the repetition.
I'm building a questionnaire for an application and I want all the questions to be contained in a div and the overflow hidden. The problem I'm currently running into is if the height doesn't exceed 80% of the window size the containing div doesn't collapse into itself and there is an unnecessary amount of whitespace left over.
I have tried to switch the questionnaire-box height style to max-height but this caused the overflow content of the .questions div to be hidden instead of scrollable.
I have a strong suspicion I may need to handle this with js but I prefer straight CSS and HTML if possible.
Anyone have any suggestions?
html, body {
height: 100%;
}
.questionnaire-container {
display: flex;
position: fixed;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 255, .1);
}
.questionnaire-box {
position: relative;
width: 80%;
height: 70%;
margin: 0 auto;
background-color: #ffffff;
overflow: hidden;
}
.questions {
height: 100%;
padding: 1rem 2rem;
overflow-y: auto;
}
<div class="questionnaire-container">
<div class="questionnaire-box">
<div class="questions">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing 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.
</p>
</div>
</div>
</div>
You have to move the padding from .questions to .questionnaire-box. Also, .questions has no (...-)width attributes set anymore, but the .questionnaire-box's max-width is calc(70vh - 2rem).
Fiddle: https://jsfiddle.net/moor131j/2/
First, this is my HTML
<div class="header">
<div class="wrapper">
<div class="navi">
Logo
<ul><!--
--><li>Link 1</li><!--
--><li>Link 2</li><!--
--></ul>
</div>
</div>
</div>
<div class="wrapper">
<div class="content">
<p>"Lorem ipsum dolor sit amet, consectetur adipisicing 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."</p>
</div>
</div>
and CSS
.wrapper {
width: 90%;
max-width: 50em;
margin: 0 auto;
}
.header,
.navi {
width: 100%;
}
.header {
background: grey;
}
.navi {
background: green;
display: table;
text-align: center;
}
.navi ul {
display: table-cell;
vertical-align: middle;
text-align: right;
}
.navi li {
background: orange;
display: inline;
margin-left: 10px;
}
.navilink {
display: inline-block;
width: auto;
}
.logo {
background: red;
float: left;
}
.content {
width: 100%;
background: fuchsia;
}
Fiddle
Fullscreen Fiddle
You see, the wrapper ensures that there is always some kind of gap between content and edge of the viewport and beyond a certain point (50 em), the .wrapper doesn't exceeds any further.
The code I posted here works, but I would like to know if there is any chance to get rid of <div class="wrapper"> achieving the same result. I already tried to apply the .wrapper class directly to the elements, but that isn't working - why?
To clarify: My aim is it to make the markup cleaner. That's why I am interested in a solution then ensures that the elements behave like in the example I posted, but without the use of <div class="wrapper">. The class .wrapper has to stay of course, it's just that div that strikes me. Thats why I tried to add .wrapper directly to the elements.
Remove the wrapper div, and add the two CSS properties to the content div..
.content {
margin: 0 auto;
max-width: 50em;
}