Adjusting the height of images in flex layout - html

I've developed the following layout using the Flexbox CSS model:
html {
box-sizing: border-box;
overflow-y: none;
}
*,
*:before,
*:after {
margin: 0;
padding: 0;
box-sizing: inherit;
}
#all {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background: #03a9f4;
}
#app {
width: 500px;
background: #ffffff;
border: solid 6px yellow;
}
header {
display: flex;
justify-content: center;
align-items: center;
border: solid 4px blue;
}
#header-para-container {
flex: 1;
}
#header-image-container {
flex: 0.6;
background: #888;
}
#header-image-container > img {
display: block;
width: 100%;
height: auto;
}
section {
display: flex;
flex-wrap: wrap;
border: solid 4px tomato;
}
figure {
display: flex;
justify-content: center;
align-items: center;
flex-basis: 50%;
border: solid 4px green;
}
figure > img {
max-width: 80%;
height: auto;
}
<div id="all">
<div id="app-container">
<div id="app">
<header>
<div id="header-para-container">
<p>Hello, this is CSS flexbox layout. Thank you for visiting this page.</p>
</div>
<div id="header-image-container">
<img src="http://placekitten.com/g/300/300" />
</div>
</header>
<section id="grid-images">
<figure>
<img src="http://placekitten.com/g/300/300" />
</figure>
<figure>
<img src="http://placekitten.com/g/300/300" />
</figure>
<figure>
<img src="http://placekitten.com/g/300/300" />
</figure>
<figure>
<img src="http://placekitten.com/g/300/300" />
</figure>
</section>
</div>
</div>
</div>
https://jsfiddle.net/petebere/fsLpw1vb/.
Would you know how to reduce responsively the height of the images and the main display element (in yellow frame) as the viewport height decreases?
The idea is that the element in yellow frame should be always fully visible and there should be no need for vertical scrolling.
At the moment when the viewport height drops, the height of the yellow container stays constant. This is probably because the browser wants to keep the sizes that I've applied to the container of the header image:
#header-image-container {
...
flex: 0.6;
...
}
and to the containers of the grid images:
figure {
...
flex-basis: 50%;
...
}
I've produced this graphic to show what I'm trying to achieve when the window height is reduced:

The images aren't scaling because they aren't bound by a fixed height on their immediate containers.
For example, the first image in the layout (in the header section), has neither a parent (.header-image-container) nor a grandparent (header) with a defined height. Here's the actual code:
header {
display: flex;
justify-content: center;
align-items: center;
border: solid 4px blue;
}
#header-image-container {
flex: 0.6;
background: #888;
}
With the code above, the image has no need to be responsive. There is no height confinement.
Try this instead:
header {
display: flex;
justify-content: center;
align-items: center;
border: solid 4px blue;
height: 20vh; /* NEW */
}
#header-image-container {
flex: 0.6;
background: #888;
height: 100%; /* NEW */
}
#header-image-container > img {
/* display: block; */
/* width: 100%; */
/* height: auto; */
height: 100%; /* NEW */
}
revised demo
The same concept above applies to the #grid-images section:
section {
display: flex;
flex-wrap: wrap;
border: solid 4px tomato;
height: 60vh; /* NEW */
}
figure {
display: flex;
justify-content: center;
align-items: center;
flex-basis: 50%;
border: solid 4px green;
height: 50%; /* NEW */
}
figure > img {
/* max-width: 80%; */
/* height: auto; */
height: 100%; /* NEW */
}
revised demo
Additional notes:
In your original code you're trying to make your images responsive with width: 100%; height: auto (in the header section) and max-width: 80%; height: auto (in the grid section). This set-up (using percentage widths) is more suited for horizontal screen re-sizing. Your question seeks vertical re-sizing, so use percentage heights instead.
In your original layout, you may have noticed that when you reduce the screen height, the layout disappears at the top of the screen, with no access via vertical scroll. This is a known issue with flexbox. The solution is to use margin: auto on the centered flex item, instead of justify-content: center; align-items: center on the flex container. Full details here: Can't scroll to top of flex item that is overflowing container

Related

CSS Make Div Expand to Fill Parent but not Overflow

I am working on a project which requires some basic HTML/CSS. I have a code pen which may be easier to visualize: https://codepen.io/Sean713/pen/yLEZVEe
My objective is to make the innerBottomHalf element expand to fully fill the bottomHalf element (barring any padding). I would also like the navbar + wholePage element to take up the full VH.
I currently have it set so that the wholePage takes up the full VH, I'm not sure how to subtract the navbar height from this.
I also see that my innerBottomHalf expands outside of my BottomHalf, I do not know why this is, because I've set its height to be 100%.
I tried a lot of solutions online, the GPT chatbot, and prodding around with the code, but have been unable to figure it out. I appreciate any help.
My code is as follows:
ul {
list-style-type: none;
display: flex;
align-items: center;
}
li a {
display: block;
text-align: center;
padding: 10px 15px;
text-decoration: none;
}
div {
padding: 10px;
}
.wholePage {
background-color: blue;
display: flex;
flex-direction: column;
height: 100vh;
}
.topHalf {
background-color: purple;
display: flex;
justify-content: space-between;
}
.bottomHalf {
background-color: grey;
height: 100%;
}
.innerBottomHalf {
background-color: brown;
height: 100%;
}
.topLeftHalf {
background-color: green;
flex: 1;
height: 50vh;
}
.topRightHalf {
background-color: orange;
flex: 1;
height: 50vh;
}
<ul>
<li><a>Solve</a></li>
<li><a>About</a></li>
<li><a>Other</a></li>
</ul>
<div class="wholePage">
<div class="topHalf">
<div class="topLeftHalf">
This is the top left
</div>
<div class="topRightHalf">
This is the top right
</div>
</div>
<div class="bottomHalf">
This is the bottom half
<div class="innerBottomHalf">
This is the inner bottom half
</div>
</div>
</div>
With height: 100% on nested elements you'll get an overflow because there are heights from other elements being added. Instead of percentage heights, just use flex properties all the way.
body {
display: flex;
flex-direction: column;
height: 100vh;
margin: 0; /* remove default margins */
}
.wholePage {
background-color: blue;
display: flex;
flex-direction: column;
/* height: 100vh; */
flex: 1; /* new */
}
.bottomHalf {
background-color: grey;
/* height: 100%; */
display: flex;
flex-direction: column;
flex: 1;
}
.innerBottomHalf {
background-color: brown;
/* height: 100%; */
flex: 1;
}
/* no adjustments below this line */
ul {
list-style-type: none;
display: flex;
align-items: center;
}
li a {
display: block;
text-align: center;
padding: 10px 15px;
text-decoration: none;
}
div {
padding: 10px;
}
.topHalf {
background-color: purple;
display: flex;
justify-content: space-between;
}
.topLeftHalf {
background-color: green;
flex: 1;
height: 50vh;
}
.topRightHalf {
background-color: orange;
flex: 1;
height: 50vh;
}
<ul>
<li><a>Solve</a></li>
<li><a>About</a></li>
<li><a>Other</a></li>
</ul>
<div class="wholePage">
<div class="topHalf">
<div class="topLeftHalf">
This is the top left
</div>
<div class="topRightHalf">
This is the top right
</div>
</div>
<div class="bottomHalf">
This is the bottom half
<div class="innerBottomHalf">
This is the inner bottom half
</div>
</div>
</div>

Flexbox items alignment with same height & item aligment

I have a simple layout with image on Left and Title of blog on right with light grey background for large screen or were width is minimum 800px. for smaller screens it should show image on top and Title below image. It is working fine except two thing
It show extra space under image which is shown as yellow background in this case.
I want Title Item to be same height as Image element with light grey background, in this case which is represented as red.
.flex-container {
display: flex;
align-items: stretch;
flex-direction: row;
border: 1px solid blue;
height: 100%;
}
.flex-container>div {
background-color: yellow;
color: #555;
width: 50%;
height: 100%;
margin: 0px;
text-align: center;
align-self: center;
font-size: 30px;
}
.title-wrapper {
background-color: #f00 !important;
}
.imgx {
width: 100%;
}
#media (max-width: 800px) {
.flex-container {
flex-direction: column;
}
.flex-container>div {
width: 100%;
margin: 0px;
}
.imgx {
width: 100%;
}
}
<div class="flex-container">
<div class="image-wrapper"><img class="imgx" src="https://dummyimage.com/600x400/000/add413&text=IMAGE"></div>
<div class="title-wrapper">This is the title</div>
</div>
To avoid the gap under the image, 2 classical options :
reset vertical-align: to top or bottom
or reset display to block.
To center content inside the second box, make it also a grid or flex box
Possible fix :
.flex-container {
display: flex;
flex-direction: row;
border: 1px solid blue;
height: 100%;
}
.flex-container>div {
background-color: yellow;
color: #555;
width: 50%;
text-align: center;
font-size: 30px;
}
.flex-container .title-wrapper {
background-color: #f00;
display:flex;
align-items:center;
justify-content:center;
margin:0;
}
.imgx {
width: 100%;
display:block;
}
#media (max-width: 800px) {
.flex-container {
display:grid;/* or block*/
}
.flex-container>div ,
.imgx {
width: 100%;
}
}
<div class="flex-container">
<div class="image-wrapper"><img class="imgx" src="https://dummyimage.com/600x400/000/add413&text=IMAGE"></div>
<div class="title-wrapper">This is the title</div>
</div>
To get rid of the space beneath the image, the image needs to be display: block, then to make the title full height and still aligned centre, you need to remove the height and then make the title itself flex and use align and justify on it (see comments in css below):
.flex-container {
display: flex;
align-items: stretch;
flex-direction: row;
border: 1px solid blue;
height: 100%;
}
.flex-container>div {
background-color: yellow;
/* remove height from here */
color: #555;
width: 50%;
margin: 0px;
font-size: 30px;
}
.title-wrapper {
background-color: #f00 !important;
/* add the following to here */
display: flex;
justify-content: center;
align-items: center;
}
.imgx {
width: 100%;
display: block; /* add this */
}
#media (max-width: 800px) {
.flex-container {
flex-direction: column;
}
.flex-container>div {
width: 100%;
margin: 0px;
}
.imgx {
width: 100%;
}
}
<div class="flex-container">
<div class="image-wrapper"><img class="imgx" src="https://dummyimage.com/600x400/000/add413&text=IMAGE"></div>
<div class="title-wrapper">This is the title</div>
</div>
you have to remove height and align-self in .flex-container > div
.flex-container > div {
background-color: yellow;
color: #555;
width: 50%;
margin: 0px;
text-align: center;
font-size: 30px;
}
are you sure to use align-self or did you mean align-items and justify-content?

How can I make a div grow to fit its content, up to the max size of the parent container?

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>

Keep flex items inside parent container

I'm trying to create an element that will hold various images that should be responsive (width AND height). So far using flexbox has been successful except for one thing. Every time I reduce the width of my window, at a certain point, the flex items overflow the parent container and spill out beyond the containers width.
nav {
position: fixed;
top: 0;
left: 0;
height: 80px;
line-height: 80px;
background: black;
color: #fff;
width: 100%;
text-align: center;
}
body, p {
margin: 0;
padding: 0;
width: 100vw;
}
.wrapper {
height: 100vh;
margin: 100px auto;
min-width: 0;
}
.flex {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
max-width: 100%;
min-width: 200px;
flex-wrap: nowrap;
}
img {
max-height: 100%;
max-width: 100%;
}
.txt-rt {
text-align: right;
}
.footer {
background: darkgray;
height: 300px;
text-align: center;
}
<nav>This is a Navbar</nav>
<div class="wrapper">
<div class="flex">
<p>hello</p>
<img src="https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg" alt="">
<p class="txt-rt">world</p>
</div>
</div>
<div class="footer">
<h3 class="footer">Footer content</h3>
</div>
In this CodePen example, each time the window width is <560px or so and the height is at least 600px, the image is no longer responsive in width and the content overflows outside the screen.
All the other functionality looks like it's working as expected, but once I reduce my window width to a certain point the image will not shrink down. This prevents all 3 flex items being viewable in the width of the screen. Is there code I should be adding - not media queries since various sizes of images will be used - to make sure the image is responsive no matter the size of the window? Note: I don't want the items to wrap down to a second line.
You can use this code
* {
box-sizing: border-box;
}
body {
display: flex;
min-height: 100vh;
flex-direction: column;
margin: 0;
text-align: center;
}
#main {
display: flex;
flex: 1;
flex-direction: column;
}
#main>article {
flex: 1;
text-align: center;
}
#main>nav,
#main>aside {
background: beige;
}
#main>nav {
order: -1;
}
header,
footer {
background: yellowgreen;
height: 20vh;
}
header,
footer,
article,
nav,
aside {
padding: 1em;
}
#media screen and (min-width: 576px) {
#main {
flex-direction: row;
}
#main>nav,
#main>aside {
flex: 0 0 20vw;
}
}
<header>This is a Navbar</header>
<div id="main">
<article><img src="https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg" alt=""></article>
<nav>hello</nav>
<aside>world</aside>
</div>
<footer>Footer content</footer>
.flex {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
max-width: 100%;
min-width: 200px;
flex-wrap: wrap; // this will move your content to new line if there is less space
}

Flexbox align one element center and another at the bottom of the page

I have the following sidebar
What I want to achieve here is have the logo centered and the copyright at the bottom of the page.
Here is what I have so far:
HTML
<aside class="flex">
<div class="flex inner_content">
<img src="./img/logo.svg" alt="Logo">
<p>© copyright 2018</p>
</div>
</aside>
CSS
.flex {
align-items: center;
display: flex;
}
aside {
background: url('../img/sidebar-image.jpg') no-repeat center/cover;
height: 20em;
width: 100vw;
float: left;
}
.inner_content {
justify-content: center;
flex-direction: column;
height: inherit;
width: inherit;
}
.inner_content p {
font-size: 14px;
margin-top: 2em;
color: #FFF;
}
flex-direction: column
The major problem (besides some bad syntax on background shorthand) is that the flex-direction was at default which is row (horizontal). The flex items (.logo and .copy) are stacked vertically thus the flex-direction should be column.
Demo
Details commented in demo
html,
body {
/* Always set the font on html */
font: 700 16px/1.5 Verdana;
width: 100%;
height: 100%;
}
.flex {
/*
shorthand for background goes in this order:
position (center) repeat (no-repeat) size (cover)
and there's no slash "/"
*//*
no-repeat is the only one kept
*/
background: url('https://i.imgur.com/5OLUUfp.png')no-repeat;
/*
The sidebar is always top to bottom
*/
min-height: 100%;
/*
The width was 100vw which is 100% of viewport which I'm assuming
is wrong since a sidebar should only cover a portion of the
viewport.
*/
width: 320px;
/*
By default flex-direction is row (horizontal flow)
*/
display: flex;
/*
The flex items (.logo and .copy) are vertical, so the flex-
direction should be column. flex-flow is a combination of
flex-direction and flex-wrap
*/
flex-flow: column nowrap;
justify-content: center;
align-items: center;
}
.logo {
/*
This pushes the footer.copy down to the bottom
*/
margin: auto;
}
img {
display: block;
width: 90%;
}
.copy {
font-size: 0.875rem;
color: #FFF;
/*
This property is given to individual tags that will break
away from vertical flow of align-items
*/
align-self: flex-end;
margin-right: 10px
}
<aside class="flex">
<figure class="logo">
<img src="https://i.imgur.com/cx6bov9.png">
</figure>
<footer class='copy'>© copyright 2018</footer>
</aside>
you can use position.
Add position:relative; to .inner_content
and position:absolute; and bottom:0; to .inner_content p
so your css looks like this
.flex {
align-items: center;
display: flex;
}
aside {
background: url('../img/sidebar-image.jpg') no-repeat center/cover;
height: 20em;
width: 100vw;
float: left;
}
.inner_content {
justify-content: center;
flex-direction: column;
height: inherit;
width: inherit;
position: relative;
}
.inner_content p {
font-size: 14px;
margin-top: 2em;
color: #FFF;
position: absolute;
bottom:0;
}
but you can do this in multiple ways
here is a link to a similar question explaining this in multiple ways:
Center and right align flexbox elements