Keep flex items inside parent container - html

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
}

Related

How to show overflow content as full in a div

So I have this middle container (div) which consists of 2 smaller div.
Here's the code for the div that wraps both div:
.midContainer{
width: 100%;
height: 30vh;
max-height: 700px;
display: flex;
flex-wrap: wrap;
overflow: auto;
justify-content: space-between;
margin-bottom: 15px;
}
Here's the code for left div:
.tokenInfoBox{
width: 60%;
height: 100%;
max-height: 700px;
// padding: 20px 30px ;
background-color: #1b1b1c;
border-radius: 10px 0 0 10px;
}
Here's the code for right div:
.ticketBox{
width: 40%;
height : 100%;
background-color: #0e0304;
box-sizing: border-box;
border-radius: 0 10px 10px 0;
display: flex;
flex-direction: column;
}
Have this added as well:
#media only screen and (max-width: 1060px) {
.tokenInfoBox, .ticketBox {
width: 100%;
}
}
So the content for the left div and right div (both div) display normally in big screen but overflow and overlap div below them in small screen. How do I wrap all the overflow content inside the div?
Here's the image in bigger screen and here's the image in smaller screen where I have to scroll to see all content.
CSS:
.midContainer {
width: 100%;
height: 30vh;
display: flex;
flex-wrap: wrap;
}
.tokenInfoBox {
flex: 1 1 25rem;
height: 100%;
background-color: #1b1b1c;
border-radius: 10px 0 0 10px;
}
.ticketBox {
flex: 1 1 8rem;
height: 100%;
background-color: #0e0304;
border-radius: 0 10px 10px 0;
}
you can use flex in this case when applying flex-wrap.
If i understood well, the problem is because you have set the height of the .midContainer, try something like this:
.midContainer {
display: flex;
width: 100%;
align-self: flex-start;
}
.tokenInfoBox {
width: 60%;
flex-grow: 1;
display: flex;
flex-direction: column;
background: #1b1b1c;
}
.ticketBox {
flex-grow: 1;
display: flex;
flex-direction: column;
background: #0e0304;
width: 40%;
}
this will grow you div to fit the amount of height needed.
Also think about the use of media queries, small devices would be difficult to read 2 divs side by side, maybe should be better one over another
#media (max-width: 768px) {
.midContainer {
flex-direction: column;
}
.tokenInfoBox {
width: 100%;
}
.ticketBox {
width: 100%;
}
}
also I strongly recommend to use tailwind

Center text vertically in a full height child div [duplicate]

This question already has answers here:
Fill remaining vertical space with CSS using display:flex
(6 answers)
Make a div fill the height of the remaining screen space
(42 answers)
Closed 1 year ago.
I am trying to vertically center text inside a child div that is full height, but when I do that it has extra spacing at the bottom. How can I do this without the extra spacing? I'd like to have a nav along with some vertically centered text, but without the extra spacing.
html {
height: 100%;
}
body {
margin: 0;
min-height: 100vh;
}
h1 {
margin: 0;
padding: 0;
}
.landing {
background: url(bg.svg);
height: 100vh;
}
.landing-content {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.landing-content h1 {
color: white;
margin: 0;
}
.app {
background-color: black;
height: 100vh;
color: white;
}
<div class="app">
<div class="logo">
<h1>logo</h1>
</div>
<div class="landing">
<div class="landing-content">
<h1>hi, i'm jordan</h1>
</div>
</div>
</div>
The use of height: 100vh was not suitable, what it does is recognize the view-width as its height and that limit limits the height and recreate a small crack at the bottom. You can try using height: 100% instead
html {
height: 100%;
}
body {
margin: 0;
min-height: 100vh;
}
h1 {
margin: 0;
padding: 0;
}
.landing {
background: url(bg.svg);
height: 100vh;
}
.landing-content {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.landing-content h1 {
color: white;
margin: 0;
}
.app {
background-color: black;
height: 100%;
color: white;
}
<div class="app">
<div class="logo">
<h1>logo</h1>
</div>
<div class="landing">
<div class="landing-content">
<h1>hi, i'm jordan</h1>
</div>
</div>
</div>
Remove landing class height and add landing-content class height to 100%. When you add landing class height to 100vh, It covers 100vh height. But logo class already covers some height. so it overflows.
.landing {
background: url(bg.svg);
}
.landing-content {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
working fiddle - https://jsfiddle.net/alimurrazi/36svho08/1/
Since .app has the default display: block, .logo takes up however much space it needs, then .landing goes underneath, taking up an additional 100vh, so that you need to scroll to view its full content.
The solution here is either to simply add overflow-y: hidden to .app, but that still leaves your text off center by a bit. Another solution would be to give .app display: flex, and using flexbox to distribute the space as needed.
html {
height: 100%;
}
body {
margin: 0;
min-height: 100vh;
}
h1 {
margin: 0;
padding: 0;
}
.landing {
background: url(bg.svg);
flex-grow: 1;
}
.landing-content {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.landing-content h1 {
color: white;
margin: 0;
}
.app {
background-color: black;
height: 100vh;
color: white;
display: flex;
flex-direction: column;
}
<div class="app">
<div class="logo">
<h1>logo</h1>
</div>
<div class="landing">
<div class="landing-content">
<h1>hi, i'm jordan</h1>
</div>
</div>
</div>
Change the .app class as follow.
.app {
background-color: black;
height: auto;
color: white;
}

How to enable scrollbar with non-fixed height in a window-centered div?

I am creating a div which is centered to the window. It's content can grow, and if it grows passed the size of the window, the content div should have it's scrollbar account for the overflow. But instead, the div just grows off the screen and gets clipped. If I set an explicit height on the content, everything works, but since I don't know the explicit height of the environment I cannot do that. What is the correct way to do this?
JSFiddle: https://jsfiddle.net/CodeVirtue/cjhz31xq
Here is the template:
<div class="fullscreen-overlay">
<div class="fullscreen-container">
<div class="window-with-titlebar">
<div class="titlebar">
<div class="titlebar-left">
Left
</div>
<div class="titlebar-right">
Right
</div>
</div>
<div class="content">
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40
</div>
</div>
</div>
</div>
And all the CSS:
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.fullscreen-overlay {
background-color: red;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
padding: 12px 12px;
}
.fullscreen-container {
background-color: orange;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
overflow: hidden;
}
.window-with-titlebar {
background-color: yellow;
max-width: 100%;
max-height: 100%;
}
.titlebar {
background-color: green;
display: flex;
align-items: center;
justify-content: space-between;
height: 30px;
}
.titlebar-left {
background-color: darkgreen;
}
.titlebar-right {
background-color: lightgreen;
}
.content {
background-color: blue;
overflow-y: scroll;
max-width: 100%;
max-height: 100%;
}
I believe I was able to achieve what you are looking for by making the parent container use flexbox:
.window-with-titlebar {
background-color: yellow;
max-width: 100%;
max-height: 100%;
display: flex;
flex-direction: column;
}

Content overflowing flex item despite overflow property

I have a pretty simple page setup in the following manner using flexboxes:
The blue div is supposed to make up 25% in height and the violet div 75%. In case there are too many lines in the blue div, it should stay the same size an show a scrollbar. This works for a few lines, but breaks at some point and the blue div overflows and grows into the violet one. I'm new to flexboxes, so I don't really understand why this is happening. Would I be better off not using flexboxes? Thankful for any hints or pointer at this point.
This is the code I use (run in full page):
function lines(noLines) {
var text = "line</br>".repeat(noLines);
document.getElementById("lower").innerHTML = text;
}
* {
box-sizing: border-box;
}
.body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
#static1 {
height: 30px;
width: 100%;
background-color: red;
}
#static2 {
height: 40px;
width: 100%;
background-color: orange;
}
#content {
display: flex;
flex: 1;
}
#left {
width: 40%;
background-color: yellow;
}
#right {
width: 60%;
display: flex;
flex-direction: column;
}
#upper {
flex: 3 0;
background-color: violet;
}
#lower {
flex: 1;
background-color: blue;
overflow: auto;
}
<div class="body">
<div id="static1">Some static div</div>
<div id="static2">Another static div. Flexbox below fills rest of remaining screen.</div>
<div id="content">
<div id="left">
Left part, fixed width in percentage.</br>
Click to enter lines into the bottom right:</br>
<button onclick=lines(20)>Few Lines</button>
<button onclick=lines(200)>Many Lines</button>
</div>
<div id="right">
<div id="upper">Flexbox with flex=3.</div>
<div id="lower">Flexbox with flex=1.</div>
</div>
</div>
</div>
For the overflow property to work properly, the container needs an actual height or max-height. Flex heights (you have flex: 1 on .content) won't cut it.
In order for overflow to have an effect, the block-level container
must have either a set height (height or max-height) or
white-space set to nowrap. ~ MDN
Since you already know the height of the primary container (100vh) and the first two rows (30px and 40px), the rest is simple using the calc() function.
function lines(noLines) {
var text = "line</br>".repeat(noLines);
document.getElementById("lower").innerHTML = text;
}
.body {
display: flex;
flex-direction: column;
height: 100vh; /* adjustment */
}
#static1 {
flex-shrink: 0; /* disable shrinking */
height: 30px;
/* width: 100%; */
background-color: red;
}
#static2 {
flex-shrink: 0; /* disable shrinking */
height: 40px;
/* width: 100%; */
background-color: orange;
}
#content {
height: calc(100vh - 70px); /* new */
display: flex;
/* flex: 1; */ /* may work in some browsers, but not reliable */
}
#left {
width: 40%;
background-color: yellow;
}
#right {
width: 60%;
display: flex;
flex-direction: column;
}
#upper {
flex: 3 0;
background-color: violet;
}
#lower {
flex: 1;
background-color: aqua; /* adjusted for illustration */
overflow: auto;
}
body {
margin: 0; /* new; override browser default */
}
* {
box-sizing: border-box;
}
<div class="body">
<div id="static1">Some static div</div>
<div id="static2">Another static div. Flexbox below fills rest of remaining screen.</div>
<div id="content">
<div id="left">
Left part, fixed width in percentage.<br> Click to enter lines into the bottom right:<br>
<button onclick=lines(20)>Few Lines</button>
<button onclick=lines(200)>Many Lines</button>
</div>
<div id="right">
<div id="upper">Flexbox with flex=3.</div>
<div id="lower">Flexbox with flex=1.</div>
</div>
</div>
</div>
jsFiddle demo
I hope this is what you mean, but If I'm wrong, apologies. The problem I can see lies in the way you are using flex: 1 & flex: 3 to define the proportions of the right column, without specifying to what height their parent container has, i.e. #right has no height, so the box can always expand as it gets more filled with content.
Please try this, I hope this works and if I can answer anything else, just ask please.
The only thing I changed was your CSS and added max-height: calc(100vh - 70px); to the #right div. And changed overflow: auto; to overflow-y: scroll;
* {
box-sizing: border-box;
}
.body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
#static1 {
height: 30px;
width: 100%;
background-color: red;
}
#static2 {
height: 40px;
width: 100%;
background-color: orange;
}
#content {
display: flex;
flex: 1;
}
#left {
width: 40%;
background-color: yellow;
}
#right {
width: 60%;
display: flex;
flex-direction: column;
max-height: calc(100vh - 70px);
}
#upper {
flex: 3;
height: 75%;
background-color: violet;
}
#lower {
flex: 1;
height: 25%;
background-color: blue;
overflow-y: scroll;
}
Change the top part of CSS to this:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

Element styled with CSS Flex box appears outside parent element and doesn't vertically align with parent

I have a <section> element with a title, that contains a <div> which holds some text. I need the <div> to appear in the middle of the <section> tag, and the <section> should take up the rest of the space under the header. To the user, the <div> should appear in the centre of the space under the header.
My following code does that to some degree, but it appears off-centre. I think thats's because I applied height: 100vh to the <section>, which makes that element longer than the rest of the page.
How do I achieve this? I'm trying to create a generic set of styles for the div.message so that I can drop it in when needed and it will appear in the centre of the area below the header.
header {}
.content {
height: 100vh;
}
.message {
height: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
align-content: stretch;
align-items: center;
}
.message .text {
font-size: 20px;
order: 0;
flex: 0 1 auto;
align-self: auto;
}
<header>
<h1>Header area</h1>
</header>
<section class="content">
<h2>This is a section</h2>
<div class="message">
<p class="text">This section is empty</p>
</div>
</section>
JSFiddle
Here is how I recommend you do, and get a good responsive layout:
Add a wrapper, the container (could also use the body)
Make the container a flex column container so the header and content will stack vertically
Set flex-grow: 1 on content so if take the remaining space of its parent
Make the content a flex column container
Set flex-grow: 1 on message so if take the remaining space of its parent
Make the message a flex row container (the default)
Set justify-content: center; align-items: center; on message so its content centers
Finally, we need to take the h2 out of flow or else the message won't fill its entire parent's height, and if not, the message won't center vertically in the section
Note, as the h2 is positioned absolute the content could also be set as a flex row container, though I choose to use "column" to make it move obvious compared with the markup structure
Updated fiddle
Stack snippet
html, body {
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
header {}
.content {
position: relative;
flex-grow: 1;
display: flex;
flex-direction: column;
}
.content h2 {
position: absolute;
top: 0;
left: 0;
width: 100%;
text-align: center;
}
.message {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
}
.message .text {
font-size: 20px;
}
/* styles for this demo */
html, body {
margin: 0;
}
.container {
}
header {
border: 1px dotted red;
}
.content {
border: 1px dotted red;
}
.message,
.message .text {
border: 1px dotted red;
}
<div class="container">
<header>
<h1>Header area</h1>
</header>
<section class="content">
<h2>This is a section</h2>
<div class="message">
<p class="text">This section is empty</p>
</div>
</section>
</div>
Based on how you intend to use message, you could also set the justify-content: center; align-items: center; to the content (and drop the flex properties on the message)
Fiddle demo 2
Stack snippet
html, body {
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
header {}
.content {
position: relative;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.content h2 {
position: absolute;
top: 0;
left: 0;
width: 100%;
text-align: center;
}
.message {
}
.message .text {
font-size: 20px;
}
/* styles for this demo */
html, body {
margin: 0;
}
.container {
}
header {
border: 1px dotted red;
}
.content {
border: 1px dotted red;
}
.message,
.text {
border: 1px dotted red;
}
<div class="container">
<header>
<h1>Header area</h1>
</header>
<section class="content">
<h2>This is a section</h2>
<div class="message">
<p class="text">This section is empty</p>
</div>
</section>
</div>
If the message is only a wrapper for the p, you could drop it all together.
Fiddle demo 3
If I understood you well, this is what you're looking for :
header {
}
.content {
align-content: center;
align-items: center;
top: 50%;
left: 50%;
height: 100%;
width: 100%;
}
.message {
display: inline-block;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 200px;
height: 100px;
margin: auto;
}
.message .text {
font-size: 20px;
order: 0;
flex: 0 1 auto;
align-self: auto;
}
The JSFiddle link
You have two main ways of solving this:
1) If you assign a fixed height to the header, you can then give the section the remaining height with calc:
.header {
height: 50px;
}
.content {
height: calc(100vh - 50px);
}
You will need to make sure it works even with smaller windows (you might need to add some media queries)
2) If you instead don't want to assign a fixed height to the header, you can wrap header and section into a common parent that is using a flexbox, and allow the section to grow. I wrote this solution here: https://jsfiddle.net/annc8w4j/1/