I am using flexbox layout to position three divs in a column so that each div has the same height. Each div displays a scrollbar if its content is too large. I would like each section to only expand to the height of its content, but currently what happens is that every section is always the same height regardless of the content in it.
If the container is 900px, each section should be 300px, and if the content of a section is more than 300px tall, a scroll bar should appear. However, if the content of lets say the middle section is only 100px tall, that section should only be 100px, and the remaining sections should fill in the remaining space, so they would each be 400px tall.
Example: http://jsfiddle.net/x6puccbh/2/
As you can see in this example, the middle section is the same height as the other sections, but I would like it to only be as tall as its content. Is this possible using flex layout?
<div class="container">
<div class="panel">
<div class="section">
<div class="header">HEADER</div>
<div class="content">content<br>content<br>content<br>content
<br>content<br>content<br>content<br>content
<br>content<br>content<br>content<br>content</div>
</div>
<div class="section">
<div class="header">HEADER</div>
<div class="content">content</div>
</div>
<div class="section">
<div class="header">HEADER</div>
<div class="content">content<br>content<br>content<br>content
<br>content<br>content<br>content<br>content
<br>content<br>content<br>content<br>content
</div>
</div>
</div>
</div>
.container {
height: 300px;
}
.panel {
display:flex;
flex-direction: column;
height: 100%;
}
.header {
height: 15px;
text-align: center;
flex-shrink: 0;
}
.section {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
height: 100%;
border: 1px solid red;
display: flex;
flex-direction: column;
}
.content {
overflow-y: auto;
height: 100%;
}
If you change your heights to auto I think it does what you are asking. Example and current code below. Let me know if that's not what you were going for
http://plnkr.co/edit/MMjXmANacvZvHofXzYoL
.container {
height: 300px;
}
.panel {
max-height: 100%;
display:flex;
flex-direction: column;
}
.header {
height: 15px;
text-align: center;
flex-shrink: 0;
}
.section {
border: 1px solid red;
display: flex;
flex-direction: column;
max-height: 33%;
flex-grow: 1;
}
.content {
overflow-y: auto;
}
Try setting a max-height property on the container you don't want to get too big but use a vh rather than a % (as in 75vh not 75%).
Related
I'm positioning a modal div in the middle of the page with a max-height defined as a % of its container, in this case it shouldn't exceed 70% of the page height.
The contents of the div are two elements:
A fixed height header div
And a variable height content div
I want the modal to grow with the content until the max-height, then the content div should start scrolling. However whatever I do, the content seems to spill out of the modal like so:
This is my markup and styling:
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.modal {
max-height: 70%;
border: 5px dashed green;
border-radius: 5px;
}
.container {
/* I cannot remove this container */
display: flex;
flex-direction: column;
width: 600px;
}
.header {
flex: none;
background: red;
height: 100px;
}
.content {
flex: 1;
background: yellow;
overflow: auto;
}
.big-stuff {
margin: 10px;
background: orange;
height: 600px;
}
<div class="modal">
<div class="container">
<div class="header">
Header
</div>
<div class="content">
Content. Should shrink or grow to fit content but only to a max of the container height
<div class="big-stuff">
Large content
</div>
</div>
</div>
</div>
Unfortunately I can't change the markup so I'm trying to get this working just by modifying CSS. If I remove the .container div, then everything seems to work but I was hoping there was another way.
Full example available here: https://codepen.io/dyancat/pen/QWaOGpB
You can add flex to the modal, so that the content will not expand out of its parent (modal in this example):
.modal {
max-height: 70%;
border: 5px dashed green;
border-radius: 5px;
display: flex; /* Add this flex */
}
Just add display:flex in the css to the modal class.
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.modal {
max-height: 70%;
border: 5px dashed green;
border-radius: 5px;
display: flex;
}
.container {
/* I cannot remove this container */
display: flex;
flex-direction: column;
width: 600px;
}
.header {
flex: none;
background: red;
height: 100px;
}
.content {
flex: 1;
background: yellow;
overflow: auto;
}
.big-stuff {
margin: 10px;
background: orange;
height: 600px;
}
<div class="modal">
<div class="container">
<div class="header">
Header
</div>
<div class="content">
Content. Should shrink or grow to fit content but only to a max of the container height
<div class="big-stuff">
Large content
</div>
</div>
</div>
</div>
Layout: Mobile, Vertical Layout, Header (fixed height), Footer (fixed height). How to fill remaining space with img, constrained on height & width
This is a very common layout for me on iOS. Trying to understand how to do it in CSS.
Here's what I'm trying:
Using flexbox with flex-direction column
Setting height of header and footer (or can be done with flex-basis)
flex-shrink: 0 for header and footer so they don't shrink
flex-shrink: 1 on the image container so it shrinks if needed
Setting max-width and max-height to 100% on image
object-fit: scale-down so it keeps the aspect ratio of the image (this means there will be horizontal bars or vertical bars)
Issue: the image shrinks to fit the width, but should shrink even more than that to fit the available vertical space
HTML
<div class='container'>
<div class='header'>
Header
</div>
<div class='content'>
<div class='image-container'>
<img class="cat" src="https://jngnposwzs-flywheel.netdna-ssl.com/wp-content/uploads/2019/05/Transparent-OrangeWhiteCat-764x1024.png"/>
</div>
</div>
<div class='footer'>
Footer
</div>
</div>
CSS
.container {
background-color: #aaa;
height: 400px;
width: 175px;
display: flex;
flex-direction: column;
border: 2px solid blue;
}
.box {
border: 2px solid black;
display: flex;
justify-content: center;
align-items: center;
}
.box1 {
height: 100px;
flex-shrink: 0;
}
.box2 {
flex-shrink: 1;
}
.cat {
max-width: 100%;
max-height: 100%;
object-fit: scale-down;
border: 2px solid orange;
}
.box3 {
height: 100px;
flex-shrink: 0;
}
https://codepen.io/jeffrey-robert/pen/yLbNVZp
If you use object-fit, then the trick is to set to img :height:0;min-height:100%;width:100% and it should fill the flex child boxe, the child boxe will require flex-grow:1; too to fill the remaing space.
.container {
background-color: #aaa555;
height: 400px;
width: 175px;
display: flex;
flex-direction: column;
border: 2px solid blue;
}
.box {
border: 2px solid black;
display: flex;
justify-content: center;
align-items: center;
}
.box1 {
height: 100px;
flex-shrink: 0;
}
.box2 {
flex:1 1 auto;
}
.cat {
width: 100%;
height:0;
min-height:100%;
object-fit: scale-down;
border: 2px solid orange;
}
.box3 {
height: 100px;
flex-shrink:1;
}
<div class="container">
<div class="box box1">
1
</div>
<div class="box box2">
<img class="cat" src="https://jngnposwzs-flywheel.netdna-ssl.com/wp-content/uploads/2019/05/Transparent-OrangeWhiteCat-764x1024.png"/>
</div>
<div class="box box3">
3
</div>
</div>
I have the following code structure
.parent {
display: flex;
flex-direction: column;
}
.img {
width: 100%
}
.content {
flex: 1;
overflow-y: scroll;
}
.container {
border: 1px solid;
display: flex;
flex-direction:column;
margin:20px;
}
<div class="parent">
<img src="https://www.everythingcarers.org.au/media/1982/sample.jpg"/>
<div class="content">
</div>
<div class="footer">
<div class="container">
<div><button>Button1</button><div>
<div><button>Button2</button><div>
</div>
</div>
</div>
What I want is the footer to occupy its original width and height(height: 144px) , and make the content scrollable based on the available space according to screen resolution.Currently, the footer is getting cut off on some screens. I've tried changing the flex values for content and footer, but it doesn't work.Thanks
If you want to limit your parent to the height of the screen so the footer is always visible, you need to set a height of 100% on your div (and body and html) and also move the image inside your content container (or have a seperate one that will scroll if it too large for the screen)
body,
html {
margin: 0;
height: 100%;
}
.parent {
height: 100%;
display: flex;
flex-direction: column;
}
img {
display:block;
width: 100%
}
.content {
flex: 1;
overflow-y: scroll;
}
.container {
border: 1px solid;
display: flex;
flex-direction: column;
margin: 20px;
}
<div class="parent">
<div class="content">
<img src="https://www.everythingcarers.org.au/media/1982/sample.jpg" />
</div>
<div class="footer">
<div class="container">
<div><button> Button1 </button></div>
<div><button> Button2 </button></div>
</div>
</div>
</div>
I think setting your parent height to 100vh and giving your footer a fixed height should fix it:
https://codepen.io/chrishalley/pen/zbwRMw
body {
margin: 0;
}
.parent {
display:flex;
flex-direction:column;
background-color: orangered;
height: 100vh;
}
.content {
flex: 1;
overflow-y: scroll;
}
img {
width: 300px;
}
.footer {
height: 144px;
}
I´m building a sidebar using CSS flex and I need it to grow vertically to fill the whole screen vertical height. Here is a skeleton of what I´m doing.
JSFiddle here
.app {
display: flex;
flex-direction: row;
. align-items: flex-start;
height: 100%;
width: 100%;
}
.sidebar {
background-color: red;
height: 100%;
}
.content {
width: 100%;
display: flex;
flex-direction: column;
}
.content-header {
flex: 1;
background-color: grey;
}
.content-main {
flex: 1;
background-color: yellow;
}
<div class='app'>
<div class='sidebar'>
This is sidebar
</div>
<div class='content'>
<div class='content-header'>
Content Header
</div>
<div class='content-main'>
This is the main content
</div>
</div>
</div>
I think I got it pretty close by assigning the full viewport height to your container and then removing flex: 1 from .content children.
.app {
display: flex;
flex-direction: row;
. align-items: flex-start;
height: 100vh;
width: 100%;
}
.sidebar {
background-color: red;
}
.content {
width: 100%;
display: flex;
flex-direction: column;
}
.content-header {
background-color: grey;
}
.content-main {
background-color: yellow;
}
<div class='app'>
<div class='sidebar'>
This is sidebar
</div>
<div class='content'>
<div class='content-header'>
Content Header
</div>
<div class='content-main'>
This is the main content
</div>
</div>
</div>
body, html {
height: 100%;
}
And the fiddle
https://jsfiddle.net/gxkezny9/
One of the parent containers wasn't 100% height
The proper usage of Flexbox, is to make the app take full height by either use height: 100vh, or give html/body a height, html, body { height: 100% } so the app's height work as expected.
Second, as you use align-items: flex-start all items will initially align at the top, but by adding align-self: stretch to the sidebar, it will fill its parent's height.
Note, for flex row item you should not use height: 100%, you should use the align-* properties.
Note 2, the set flex: 1 on content-header and content-main doesn't have any affect, unless their parent content has a height higher than their summed height. i.e. if to change the app's align-items to stretch (and if, the align-self on sidebar can be removed)
Note 3, the flex: 1 won't work properly in IE, use flex-grow: 1 instead, or assign all values, where flex-basis should be auto, i.e. flex: 1 1 auto
Stack snippet
body {
margin: 0;
}
.app {
display: flex;
flex-direction: row;
align-items: flex-start;
height: 100vh; /* changed */
width: 100%;
}
.sidebar {
background-color: red;
align-self: stretch; /* added */
}
.content {
width: 100%;
display: flex;
flex-direction: column;
}
.content-header {
flex: 1; /* for IE, "flex-grow: 1" or "flex: 1 1 auto"
*/
background-color: grey;
}
.content-main {
flex: 1; /* for IE, "flex-grow: 1" or "flex: 1 1 auto"
*/
background-color: yellow;
}
<div class='app'>
<div class='sidebar'>
This is sidebar
</div>
<div class='content'>
<div class='content-header'>
Content Header
</div>
<div class='content-main'>
This is the main content
</div>
</div>
</div>
I'm trying to create a simple header and I'm having problems with the logo image because it's taking more space than needed.
.wrapper {
display: flex;
flex-direction: row;
height: 50px;
}
.logo {
padding: 5px;
}
img {
height: 100%;
}
.content {
padding: 5px;
}
<div class="wrapper">
<div class="logo"><img src="http://placehold.it/350x150"/></div>
<div class="content">content</div>
</div>
As you can see, the "content" text isn't placed near the logo, because the logo wrapper has a width equal to the size of the image before it gets resized by CSS.
I noticed that if I set height: 100% to the .logo element the situation is a bit better, but doing so, the "content" text overlaps a bit the image.
How can I fix it?
Here are two ways to fix the problem:
Method #1 – Remove the extra wrapper. Make the image itself the flex item.
.wrapper {
display: flex;
flex-direction: row;
height: 50px;
}
img {
height: 100%;
}
.content {
padding: 5px;
}
<div class="wrapper">
<img src="http://placehold.it/350x150"/><!-- div wrapper removed -->
<div class="content">content</div>
</div>
Method #2 – Define a height for the image wrapper. (No changes to the HTML.)
.wrapper {
display: flex;
flex-direction: row;
height: 50px;
}
.logo {
height: 100%; /* new */
border: 1px dashed red;
}
img {
height: 100%;
}
.content {
padding: 5px;
margin-left: 5px;
border: 1px dashed red;
}
<div class="wrapper">
<div class="logo"><img src="http://placehold.it/350x150" /></div>
<div class="content">content</div>
</div>
You have to explicitly set image height in pixels. height: 100% will use the image original height, NOT its container height.
I added justify-content and align-items to the flex container so things get properly positioned.
.wrapper {
display: flex;
flex-direction: row;
height: 50px;
justify-content: flex-start;
align-items: flex-start;
}
.logo {
padding: 5px;
}
img {
max-height: 50px
}
.content {
padding: 5px;
}
<div class="wrapper">
<div class="logo"><img src="http://placehold.it/350x150"/></div>
<div class="content">content</div>
</div>