Scroll in a deeply nested flex container - min-height not working - html

I have the following flex layout. I need overflow to occur in div.stretchy. I would like div.stretchy to reach the boundary of the page and then overflow it's content. Per this stackoverflow post, I have tried many combinations of min-height: 0 and overflow: hidden, but div.stretchy will not shrink.
body {
margin: 0;
}
.page-wrapper {
display: flex;
height: 100vh;
width: 100vw;
overflow: hidden;
}
.sidebar {
background: blue;
flex: 0 0 40px;
}
.main {
background: green;
display: flex;
flex-direction: column;
flex: 1;
min-width: 0;
}
.topbar {
display: flex;
flex: 0 0 40px;
background-color: red;
}
.content {
display: flex;
overflow: auto;
}
.row {
display: flex;
}
.column {
display: flex;
flex-direction: column;
}
.grow {
flex-grow: 1;
}
.card {
height: 300px;
border: solid 1px;
min-width: 600px;
}
.card .row {
justify-content: space-between;
}
.wrapper {
padding: 16px;
height: fit-content;
}
.stats {
padding: 8px;
background-color: pink;
}
.overflow-hidden {
overflow: hidden;
}
.body .column {
background-color: indigo;
}
.wide-content {
background-color: yellow;
height: 50px;
width: 800px;
}
.block {
flex: none;
width: 300px;
height: 200px;
&:nth-of-type(odd) {
background: darken(green, 10%);
}
}
<div class="page-wrapper">
<div class="sidebar">sidebar</div>
<div class="main">
<div class="topbar">topbar</div>
<div class="content">
<div class="wrapper">
<div class="card column grow">
<div class="stats row">
<span>12345</span>
<span>12345</span>
<span>12345</span>
</div>
<div class="body row grow">
<div class="column">
<span>Dynamic Width Content</span>
</div>
<div class="stretchy column grow overflow-hidden">
<div class="wide-content grow"></div>
</div>
<div class="column">
<span>Dynamic Width Content</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

This is a tough battle. The enemy is cunning, deceitful and ruthless. I say we launch a massive carpet bombing campaign, showering the whole area with min size overrides. That should clear out 80% of the problem. Then we send in the ground troops to finish the job :-)
* {
min-width: 0 !important;
min-height: 0 !important;
}
.page-wrapper {
display: flex;
height: 100vh;
/* width: 100vw; */
/* overflow: hidden; */
}
.sidebar {
background: cornflowerblue;
/* flex: 0 0 40px; */
flex: 0 0 100px; /* changed for demo purposes */
}
.main {
background: lightgreen;
display: flex;
flex-direction: column;
flex: 1;
}
.topbar {
display: flex;
flex: 0 0 40px;
background-color: orangered;
}
.content {
display: flex;
/* overflow: auto; */
flex: 1; /* added */
}
.row {
display: flex;
}
.column {
display: flex;
flex-direction: column;
}
.grow {
flex-grow: 1;
}
.card {
/* height: 300px; */
border: solid 1px;
min-width: 600px;
}
.stretchy {
overflow: auto;
}
.card .row {
justify-content: space-between;
}
.wrapper {
padding: 16px;
/* height: fit-content; */
display: flex; /* added */
}
.stats {
padding: 8px;
background-color: pink;
}
.overflow-hidden {
/* overflow: hidden; */
}
.body .column {
background-color: violet;
}
.wide-content {
background-color: yellow;
height: 50px;
width: 800px;
}
body {
margin: 0;
}
/*
.block {
flex: none;
width: 300px;
height: 200px;
&:nth-of-type(odd) {
background: darken(green, 10%);
}
}
*/
<div class="page-wrapper">
<div class="sidebar">sidebar</div>
<div class="main">
<div class="topbar">topbar</div>
<div class="content">
<div class="wrapper">
<div class="card column grow">
<div class="stats row">
<span>12345</span>
<span>12345</span>
<span>12345</span>
</div>
<div class="body row grow">
<div class="column">
<span>Dynamic Width Content</span>
</div>
<div class="stretchy column grow overflow-hidden">
<div class="wide-content grow">test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br>test<br></div>
</div>
<div class="column">
<span>Dynamic Width Content</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
jsFiddle demo

Related

Add responsive image to a website split into 4 responsive boxes

I want to make a website that would consist of 4 boxes each 50% height and width. I found code that does that, but now I struggle to add images into each box. I want each of the four divs to have a different image, and they should scale according to window size. Any help is appreciated.
Here's my codepen: https://codepen.io/alanvkarlik/pen/OJRdyRR
Here's what I would like to achieve: https://i.imgur.com/7CR7sW8.jpg
HTML:
<div class="container">
<div class="column"><img src="https://f4.bcbits.com/img/a0846297992_16.jpg"></div>
<div class="column">IMG 2</div>
<div class="column">IMG 3</div>
<div class="column">IMG 4</div>
</div>
CSS:
html, body {
height: 100%;
margin: 0;
}
.container {
height: 100%;
}
.column {
height: 25%;
display: flex;
justify-content: center;
align-items: center;
}
#media screen and (min-width: 600px) {
.container {
display: flex;
flex-wrap: wrap;
}
.column {
flex-basis: 50%;
height: 50%;
}
}
/* general styles */
body {
font-family: 'Lato', sans-serif;
font-size: 1.3em;
color: #ccc;
background: #000;
/*margin-bottom: 70px;*/
}
.column {
padding: 15px;
/*border: 1px solid #666;*/
box-sizing: border-box;
}
.column:nth-child(1) {
background: #5c9;
}
.column:nth-child(2) {
background: #fb0;
}
.column:nth-child(3) {
background: #39f;
}
.column:nth-child(4) {
background: #f33;
}
main {
max-width: 1200px;
margin: 0 auto;
}
h1,
h2 {
text-align: center;
}
Not sure if this is what you're trying to achieve but I'd do it with by setting object-fit: contain on images. I also changed a bit the way (css) you're defining the divs.
body {
margin: 0;
}
.container {
display: flex;
flex-wrap: wrap;
}
.column {
height: 50vh;
width: 50vw;
display: flex;
justify-content: center;
align-items: center;
padding: 15px;
box-sizing: border-box;
}
.column img {
height: 100%;
width: 100%;
object-fit: contain;
}
.column:nth-child(1) {
background: #5c9;
}
.column:nth-child(2) {
background: #fb0;
}
.column:nth-child(3) {
background: #39f;
}
.column:nth-child(4) {
background: #f33;
}
<div class="container">
<div class="column"><img src="https://f4.bcbits.com/img/a0846297992_16.jpg"></div>
<div class="column">IMG 2</div>
<div class="column">IMG 3</div>
<div class="column">IMG 4</div>
</div>
I think this is what you are looking for.
Your column img class is set to 100% width and height. I set the height to 50% and the width to auto so it detects the image size and displays it noramlly.
And i simply removed the "object-fit: cover;".
If you change your .colum img {} to the following it should be exactly what you want.
.column img {
height: 50%;
width: auto;
}
I added a snippet so you can see it working.
body {
margin: 0;
}
.container {
display: flex;
flex-wrap: wrap;
}
.column {
height: 50vh;
width: 50vw;
display: flex;
justify-content: center;
align-items: center;
padding: 15px;
box-sizing: border-box;
}
.column img {
height: 50%;
width: auto;
}
.column:nth-child(1) {
background: #5c9;
}
.column:nth-child(2) {
background: #fb0;
}
.column:nth-child(3) {
background: #39f;
}
.column:nth-child(4) {
background: #f33;
}
<div class="container">
<div class="column"><img src="https://f4.bcbits.com/img/a0846297992_16.jpg"></div>
<div class="column">IMG 2</div>
<div class="column">IMG 3</div>
<div class="column">IMG 4</div>
</div>

How to make nested flex child scrollable

I have a list of messages (which is a flex child) in a container with unknown height and want to make them scrollable. But I cannot find a proper combination of flex-grow: 1, min-height: 0 and other flex tricks to make it working - message list is still bigger than its parent.
When I add overflow-y: auto to its parent - it works but this parent besides messages list includes some content which should not scroll.
Here's my example for this case: https://jsfiddle.net/ecbtrn58/2/
<div class="page">
<div class="messages-section">
<div class="header">Your messages</div>
<div class="content">
<img src="https://http.cat/100" width="70" height="50"/>
<div class="messages-list">
<div class="message">Hi.</div>
<div class="message">Hello.</div>
<div class="message">Good morning.</div>
<div class="message">Yo!</div>
</div>
</div>
</div>
</div>
.page {
background-color: #ddd;
width: 300px;
height: 300px;
.messages-section {
display: flex;
flex-direction: column;
width: 50%;
height: 100%;
background-color: #ccc;
.header {
background: #bbb;
padding: 5px;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
padding: 5px;
.messages-list {
display: flex;
flex-direction: column;
overflow-y: auto;
/* What to add here to make it scrollable? */
.message {
height: 50px;
margin: 10px;
padding: 10px;
background: #1dc497;
}
}
}
}
}
How can I make messages list to scroll?
You have to set the height of .content to 100% and make it scrollable:
.page {
background-color: #ddd;
width: 300px;
height: 300px;
}
.page .messages-section {
display: flex;
flex-direction: column;
width: 50%;
height: 100%;
background-color: #ccc;
}
.page .messages-section .header {
background: #bbb;
padding: 5px;
}
.page .messages-section .content {
display: flex;
flex-direction: column;
align-items: center;
padding: 5px;
height: 100%;
overflow-x: scroll;
}
.page .messages-section .content .messages-list {
display: flex;
flex-direction: column;
overflow-y: auto;
/* What to add here to make it scrollable? */
}
.page .messages-section .content .messages-list .message {
height: 50px;
margin: 10px;
padding: 10px;
background: #1dc497;
}
<div class="page">
<div class="messages-section">
<div class="header">Your messages</div>
<div class="content">
<img src="https://http.cat/100" width="70" height="50" />
<div class="messages-list">
<div class="message">Hi.</div>
<div class="message">Hello.</div>
<div class="message">Good morning.</div>
<div class="message">Yo!</div>
</div>
</div>
</div>
</div>

Prevent Flexbox from growing in size, truncate text [duplicate]

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Closed 3 years ago.
Hoping some one can help me, I'm trying to create a split view display, with the left half of the screen been full height and the right hand side been split into quarters.
In the Left column there will be rows of text split into columns, each column should have the content truncated if exceeds width of column, the same effect should be in the 4 quarters on the right hand side. Whatever I seem to do the quarters grow in width if the content overflows. here is my primitive code...
<!DOCTYPE html>
<html>
<head>
<title>"Active Work</title>
<style>
* {
box-sizing: border-box;
}
body {
display: flex;
min-height: 100vh;
flex-direction: row;
margin: 0;
}
.container {
width: 100%;
background: #D7E8D4;
display: flex;
min-height: 100vh;
flex-direction: row;
margin: 0;
}
.colLeft {
width: 50%;
background: blue;
min-height: 100vh;
}
.colRight {
width: 50%;
background: green;
min-height: 100vh;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.grid {
height: 50vh;
flex: 0 0 50%;
}
.rowFlex {
display: flex;
flex-direction: row;
line-height: 36px;
}
.btn1 {
padding: 5px;
background-color: #00796b;
border-radius: 5px;
max-height: 30px;
margin: 0px 5px;
}
.gridHeader {
width: 100%;
}
.truncate {
overflow: hidden;
white-space: nowrap;
flex-wrap: nowrap;
flex: 0 0 50%;
background-color: yellow;
text-overflow: ellipsis;
}
.spanDiv {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
</style>
</head>
<body>
<div class="container">
<div class="colLeft">
<div class="rowFlex">
<div>Some Text</div>
<div class="btn1">G1</div>
<div class="btn1">G2</div>
<div class="btn1">G3</div>
<div class="btn1">G4</div>
</div>
</div>
<div class="colRight">
<div class="grid" style="background-color:#ff8a80;">
<div class="rowFlex">
<div class="gridHeader">GROUP1</div>
</div>
<div class="rowFlex">
<div class="truncate">LCT-56477</div>
<div class="truncate"><span class="spanDiv">LCT-5647 cvvfvdfgdfgdfgdfgfdvhjghjghjghfvfvfv7-</span></div>
</div>
</div>
<div class="grid" style="background-color:#7b1fa2;">2</div>
<div class="grid" style="background-color:#64b5f6;">3</div>
<div class="grid" style="background-color:#80cbc4;">4</div>
</div>
</div>
</body>
</html>
Just add min-width:0 to your .grid class.
* {
box-sizing: border-box;
}
body {
display: flex;
min-height: 100vh;
flex-direction: row;
margin: 0;
}
.container {
width: 100%;
background: #D7E8D4;
display: flex;
min-height: 100vh;
flex-direction: row;
margin: 0;
}
.colLeft {
width: 50%;
background: blue;
min-height: 100vh;
}
.colRight {
width: 50%;
background: green;
min-height: 100vh;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.grid {
height: 50vh;
flex: 0 0 50%;
min-width: 0;
}
.rowFlex {
display: flex;
flex-direction: row;
line-height: 36px;
}
.btn1 {
padding: 5px;
background-color: #00796b;
border-radius: 5px;
max-height: 30px;
margin: 0px 5px;
}
.gridHeader {
width: 100%;
}
.truncate {
overflow: hidden;
white-space: nowrap;
flex-wrap: nowrap;
flex: 0 0 50%;
background-color: yellow;
text-overflow: ellipsis;
}
.spanDiv {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
<div class="container">
<div class="colLeft">
<div class="rowFlex">
<div>Some Text</div>
<div class="btn1">G1</div>
<div class="btn1">G2</div>
<div class="btn1">G3</div>
<div class="btn1">G4</div>
</div>
</div>
<div class="colRight">
<div class="grid" style="background-color:#ff8a80;">
<div class="rowFlex">
<div class="gridHeader">GROUP1</div>
</div>
<div class="rowFlex">
<div class="truncate">LCT-56477</div>
<div class="truncate"><span class="spanDiv">LCT-5647 cvvfvdfgdfgdfgdfgfdvhjghjghjghfvfvfv7-</span></div>
</div>
</div>
<div class="grid" style="background-color:#7b1fa2;">2</div>
<div class="grid" style="background-color:#64b5f6;">3</div>
<div class="grid" style="background-color:#80cbc4;">4</div>
</div>
</div>

How to correctly center-align the contents of two adjacent box split in a 2:1 ratio

My use case is the following:
I've got a center-aligned layout with a max-width of say 360px.
Part of that layout is a container with two adjacent boxes. The right one contains an image that fills 33% width of the window. Left to it should be a text container. This text container should be aligned with the left border of the remaining center-aligned layout.
Here's a sketch of it:
body {
display: flex;
flex-direction: column;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.items-center {
align-items: center;
}
.items-end {
align-items: flex-end;
}
.items-start {
align-items: flex-start;
}
.top {
max-width: 360px;
width: 100%;
height: 50px;
background: tomato
}
.width-2-3 {
width: 66.666%;
}
.width-1-3 {
width: 33.3333%
}
.left-content,
.right-content {
width: 100%;
height: 50px;
}
.left-content {
max-width: 240px;
background: rebeccapurple;
color: white;
}
.right-content {
background: pink;
}
<div class="col items-center">
<div class="top"></div>
</div>
<div class="row">
<div class="width-2-3 col items-end">
<div class="left-content">text</div>
</div>
<div class="width-1-3 col items-start">
<div class="right-content">[img]</div>
</div>
</div>
So basically my goal is to left align those two rows, no matter how big the window width. But after trying for some time I just can't get the math right! So any help would be greatly appreciated :)
You can consider negative margin left:
body {
display: flex;
flex-direction: column;
margin:0;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.items-center {
align-items: center;
}
.top {
max-width: 360px;
width: 100%;
height: 50px;
background: tomato
}
.width-2-3 {
width: 66.666%;
}
.width-1-3 {
width: 33.3333%
}
.left-content,
.right-content {
width: 100%;
height: 50px;
}
.left-content {
max-width: 240px;
background: rebeccapurple;
color: white;
}
.right-content {
background: pink;
}
#media (min-width:360px) {
.left-content {
margin-left:calc((150% - 360px)/2); /* 150 is 3/2*100% since the width is 2/3*/
}
.right-content {
margin-left:calc(240px + ((200% - 360px)/2) - 150%); /*200% is equal to 150% of the left element */
}
}
<div class="col items-center">
<div class="top"></div>
</div>
<div class="row">
<div class="width-2-3 col">
<div class="left-content">text</div>
</div>
<div class="width-1-3 col">
<div class="right-content">[img]</div>
</div>
</div>
Thanks to #temani-afif I came up with a solution that required only one line to change
- max-width: calc(240px);
+ max-width: calc(180px + 25%);
This way the text container is always left aligned to the top container while taking all the available space until the 33% window-width image container starts. And this works for all window sizes. Thanks for your help everyone! :)
body {
display: flex;
flex-direction: column;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.items-center {
align-items: center;
}
.items-end {
align-items: flex-end;
}
.items-start {
align-items: flex-start;
}
.top {
max-width: 360px;
width: 100%;
height: 50px;
background: tomato
}
.width-2-3 {
width: 66.666%;
}
.width-1-3 {
width: 33.3333%
}
.left-content,
.right-content {
width: 100%;
height: 50px;
}
.left-content {
max-width: calc(180px + 25%);
background: rebeccapurple;
color: white;
}
.right-content {
background: pink;
}
<div class="col items-center">
<div class="top"></div>
</div>
<div class="row">
<div class="width-2-3 col items-end">
<div class="left-content">text</div>
</div>
<div class="width-1-3 col items-start">
<div class="right-content">[img]</div>
</div>
</div>
Why dont you get rid of .item-end and .item-start divs so you can easily control the content.
body {
display: flex;
flex-direction: column;
}
.container {
position:relative;
max-width:360px;
width:100%;
display:flex;
justify-content:center;
}
.different-width {
max-width:450px;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.items-center {
align-items: center;
}
.content-center {
justify-content:center;
}
.top {
max-width: 360px;
width: 100%;
height: 50px;
background: tomato
}
.left-content,
.right-content {
width: 100%;
height: 50px;
}
.width-2-3 {
width: 66.666%;
}
.width-1-3 {
width: 33.3333%
}
.left-content {
max-width: 240px;
background: rebeccapurple;
color: white;
}
.right-content {
background: pink;
}
<div class="col items-center">
<div class="container">
<div class="top"></div>
</div>
</div>
<div class="row content-center">
<div class="container different-width">
<div class="left-content width-1-3">text</div>
<div class="right-content width-2-3">[img]</div>
</div>
</div>
If you need to have more control over the left-content and right-content width, consider using flex-grow and flex-basis.
If you want to control the width of the second container, make another class with a different max-width value.

Accomplishing this grid with css

Can I accomplish this grid layout with flexbox? To have the first element take up 2 rows height and then continue after it?
Check image.
You can achive it by dividing this layout in 2 columns while the 2nd column will have a nested flexbox layout as well.
HTML Structure:
<div class="container">
<div class="col box1">1</div>
<div class="col col2">
<div class="box2">2</div>
<div class="box3">3</div>
<div class="box4">4</div>
<div class="box5">5</div>
</div>
</div>
Necessary Styles:
.container {
min-height: 100vh;
display: flex;
}
.col {
flex-grow: 1;
color: #fff;
}
.col2 {
flex-wrap: wrap;
display: flex;
}
.col2 > div {
flex-basis: 50%;
flex-grow: 1;
}
.box1 {
display: flex;
}
* {box-sizing: border-box;}
body {
margin: 0;
}
.container {
min-height: 100vh;
display: flex;
}
.col {
flex-grow: 1;
color: #fff;
}
.col2 {
flex-wrap: wrap;
display: flex;
}
.col2 > div {
flex-basis: 50%;
padding: 10px;
flex-grow: 1;
}
.box1 {
background: brown;
padding: 10px;
display: flex;
}
.box2 {
background: pink;
}
.box3 {
background: black;
}
.box4 {
background: yellow;
}
.box5 {
background: royalblue;
}
<div class="container">
<div class="col box1">1</div>
<div class="col col2">
<div class="box2">2</div>
<div class="box3">3</div>
<div class="box4">4</div>
<div class="box5">5</div>
</div>
</div>
You can use this HTML structure but you need to set fixed height on parent div. Then you just use flex-direction: column and flex-wrap: wrap.
* {
box-sizing: border-box;
}
.content {
height: 100vh;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
div div:first-child {
flex: 0 0 100%;
width: 50%;
background: #880015;
}
div div:not(:first-child) {
width: 25%;
flex: 0 0 50%;
border: 1px solid black;
}
<div class="content">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
</div>