Flexbox: Multiple containers, containers on flex items? - css

Is it bad practice to use multiple flex containers, actually flex containers on flex items ?
I have one main div which is assigned display:flex and then I have two div's and I have a flex-grow: 1 assigned so that they fill up exactly 50% each.
Now in each DIV I have more DIVs with content inside but I wish to align that content vertically, so could I apply a display:flex on this too ?
Maybe I am being over paranoid about flexbox ?
I discovered flexbox lately and for me it seems to fix a lot of issues of css, so I am using it a lot.

You can use it below is example
.main {
display: flex;
}
.child {
flex:1;
border:1px solid tomato;
}
.content {
display: flex;
justify-content: flex-start;
align-items: center;
flex-flow: column nowrap;
}
.content-child{
padding: 5px;
}
<div class="main">
<div class="child">
<div class="content">
<div class="content-child">
<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 class="content-child">
<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>
<div class="child"></div>
</div>

Related

Aligning a doubly wrapped nested flex

I am trying to build a responsive gallery with images and accompanying text descriptions. Images and their text should sit side-by-side on the same row, unless the width is too small and everything is collapsed to a single column. My only issue is that in the single column mode, I would like the images to be aligned on their left to the wider text. Everything else is perfectly aligned and centered as I want.
I understand that flex is not supposed to do what I want, and I tried replacing the inner flex with a grid, but could not make it work. I would be happy to learn both about the easiest way to fix this (preferably without media queries), and more generally, what would be the correct approach to this. Most importantly, I would not like to be required to introduce new arbitrary numbers, other than the width of the image, and of the text element, and the given gaps. I would have guessed that such a design would be a common enough use case, but apparently lacking the correct terminology, I could not find reference implementations.
https://jsfiddle.net/tj13y7sc
Edit: The most promising directions seem to me:
For an easy fix: Giving the image the same width as the text, and using a negative(?) margin to fix the horizontal gap when they are on the same row.
For the right way to do it: Replacing the inner flex with a grid - but i could not got it to not collapse all the time.
4 columns - good:
2 columns - good:
1 column - misaligned:
.flex_container {
display:flex;
flex-wrap:wrap;
justify-content:center;
gap:64px 128px;
}
.flex_container_item {
display:flex;
flex-wrap:wrap;
justify-content:center;
gap:64px;
}
.text {width:360px;}
<div class="flex_container">
<div class="flex_container_item">
<img src="https://via.placeholder.com/250" width=256>
<div class="text">
<h1>description1</h1>
<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 class="flex_container_item">
<img src="https://via.placeholder.com/250" width=256>
<div class="text">
<h1>description2</h1>
<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 class="flex_container_item">
<img src="https://via.placeholder.com/250" width=256>
<div class="text">
<h1>description3</h1>
<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 class="flex_container_item">
<img src="https://via.placeholder.com/250" width=256>
<div class="text">
<h1>description4</h1>
<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>
Just change the second class justify-content to "left" as:
.flex_container_item {
display:flex;
flex-wrap:wrap;
justify-content:left;
gap:64px;
}
Here's what it looks like (not allowed to upload images here yet..)
Your width of img and div container of text are different, try keeping it same and it will be properly align.
Or if you want that specific width of text container.
Then use media query and change flex-direction to column for smaller screens.
Seems like adding the next condition might do the trick -
.flex_container_item img {
border: 1px solid blue; /* just for test */
margin-left: 0;
margin-right: auto;
}
see here: https://codepen.io/elicohenator/pen/MWjpgze
Now I just wanting to know you that I bind <img> in a <div class="image"> </div> and then make some CSS changes, and also add a media query for the responsiveness.
I also add comments in CSS file what I have make change.
The following is the code snippet that you want.
.flex_container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 64px 128px;
}
.flex_container_item {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 64px;
}
.text {
width: 100%;
/*value change*/
max-width: 360px;
/*new property add*/
}
/*new code added*/
/*use 720px media width because we have to fix .image class width same as we have already set for .text class so that they align at the same edge. so now total width for both the blocks is 360px + 360px = 720px.*/
#media(max-width: 720px) {
.image {
width: 100%;
max-width: 360px;
}
}
<div class="flex_container">
<div class="flex_container_item">
<div class="image">
<img src="https://via.placeholder.com/250" width=256>
</div>
<div class="text">
<h1>description1</h1>
<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 class="flex_container_item">
<div class="image">
<img src="https://via.placeholder.com/250" width=256>
</div>
<div class="text">
<h1>description2</h1>
<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 class="flex_container_item">
<div class="image">
<img src="https://via.placeholder.com/250" width=256>
</div>
<div class="text">
<h1>description3</h1>
<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 class="flex_container_item">
<div class="image">
<img src="https://via.placeholder.com/250" width=256>
</div>
<div class="text">
<h1>description4</h1>
<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>
surround the <img> tag with a div as such:
<div class="flex_container">
<div class="flex_container_item">
<div class="image">
<img src="https://via.placeholder.com/250" width=256>
</div>
<div class="text">
.
.
.
and add to the css:
.image {
width:360px
}
like this:
https://jsfiddle.net/860c4tfj/
Solved by me!
Wrap the img with a div named "image".
Set div "image" width to 360px (same as text) - this will fix single column mode, but now the gutter is too large by 360-256=104px.
To fix this we add to both image and text divs: margin: 0 -52px; - this will fix the gutter by -52*2=-104, while keeping everything symmetric.
Finally we add margin: 0 52px; to .flex_container_item, to cancel out the effect the previous step on the outer margins.
https://jsfiddle.net/yt0pfnje/
Takeaways:
Never give up. Never surrender. I am ashamed to admit how many hours I've put into this. But hey, now I know how to use flex, grid and margins.
This would have been so much easier if gap could take negative values. Can anybody help suggest this to the spec?
I still could not make it work with grid. I believe it is not possible due to the way auto-fill works
CSS is broken. It should not be so difficult. It should not take so long to solve. The other attempted answers were suggested by first-class web experts who could still not get it right. I now believe there is no simpler way. But there should be.

Specify min-width in a flexbox layout

I have the following layout which is based on Bootstrap's Flexbox:
<div class="d-flex flex-row">
<section class="left"></section>
<section class="center"></section>
<section class="right"></section>
</div>
And the CSS of this:
.left {
flex: 0 0 360px;
}
.right {
flex: 0 0 400px;
}
.center {
flex: 1;
}
So, with this layout I have 2 left and right columns which have fixed width and a fluid center column. I'm wondering if there's a way to specify a min-width to the center container so it gets a horizontal scrollbar when the the min-width is reached because of small browser width.
Thanks!
You can use min-width in a flex item to define the minimum width flex-shrink will apply. With overflow-x you define how is their behavior when a child node overflows its content width.
EDIT #1
As stated by Michael_B, you can use a built-in flexbox solution making min-width unnecessary. The solution is to set flex-grow: 1;, flex-shrink: 0; and flex-basis: 100px; /* Or any value you want */. The short hand for this 3 properties is flex: 1 0 100px;.
section {
border: 1px solid black;
}
.left {
flex: 0 0 360px;
}
.right {
flex: 0 0 400px;
}
.center {
flex: 1 0 100px;
white-space: nowrap;
overflow-x: auto;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="d-flex flex-row">
<section class="left">
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.
</section>
<section class="center">
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.
</section>
<section class="right">
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.
</section>
</div>
Just add the following style properties to the .center element:
.center {
flex: 1 1 auto;
min-width: 100px; /* Set value to whatever you want */
overflow: auto;
}
Stackblitz Example

Flexbox: Attempting to get H1 elements above paragraph element

What I want is relatively simple. I wanted to know how I get get the H1 elements on this page centered ABOVE the paragraph elements in the middle. I'm having a ton of trouble here and need some assistance with how I can work this out in flexbox.
Thanks, here's my code
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" type="text/css" href="flex.css">
</head>
<body>
</div>
<div class="parent">
<div class="col1">
<h1>Heading 1</h1>
<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 class="col2">
<h1>Heading 2</h1>
<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>
</body>
</html>
Here's my CSS
.parent, .col1, .col2 {
display: flex;
flex-flow row wrap;
}
h1 {
align-self:center;
}
You dont have to use flex property in .col1, .col2 making them flex you expect the item inside eg h1 and p to also align as flex items. So remove the display:flex form .col1, .col2 and set text-align in h1
.parent {
display: flex;
flex-flow row wrap;
}
h1 {
text-align:center;
}
<body>
</div>
<div class="parent">
<div class="col1">
<h1>Heading 1</h1>
<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 class="col2">
<h1>Heading 2</h1>
<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>
</body>
Add justify-content: center; to col1 and col2 divs
Just a small adjustment that you need to make, instead of using the align-self: center styling, use the text-align: center property since that aligns the text to be centered instead of the box itself. Also in flexbox only the parent needs to have the display: flex; property, not the columns. Replace the styling you provided in your question with this one and it should work as expected. Please let me know if that answered your question. You also had an extra tag below the opening body tag which did not have an opening div tag and should be removed.
https://codepen.io/Katercode/pen/BxOWvw
.parent {
display: flex;
flex-flow: row wrap;
}
h1 {
text-align: center;
}

How can I give a CSS grid row a height so that the height of one of the divs in the row will be equal to the height of the text inside of it?

I have a 3-column, 1-row grid. The left and right columns have their height set to 600px. The middle column has some text inside of it (and the text is less than 600px tall).
I want the middle column to be as tall as the text inside of it, but column-template-rows: auto makes its height the same as the two divs around it, which is 600px.
Any help will be appreciated. Thank you.
Here's the HTML:
<div id='grid-container'>
<div class='side-grid-item'>First column</div>
<div id='grid-item'>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='side-grid-item'>Third column</div>
</div>
Here's the CSS:
#grid-container {
display: grid;
grid-template-columns: 384px 512px 384px;
grid-template-rows: auto auto auto; /* The second auto is where my problem is*/
}
.side-grid-item {
height: 600px;
}
Here you need to consider alignment:
#grid-container {
display: grid;
grid-template-columns: 384px 512px 384px;
align-items:start; /*added this*/
}
#grid-container > div {
background:pink;
}
.side-grid-item {
height: 600px;
}
<div id='grid-container'>
<div class='side-grid-item'>First column</div>
<div id='grid-item'>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='side-grid-item'>Third column</div>
</div>

css: column-count 3, image floating spanning 2, chrome not playing. why?

I need layout with 3 columns with an image spanning across 2 in top right corner. Found several solutions, best one here:
Advanced CSS tricks: How to span an image over multiple columns in a CSS3 site layout?
But: Both don't work with Chrome. The negative top-margin makes the text disappear behind a non discoverable something.
I used the solution with the absolute positioning of the floater, as in the other solution the left margin of the floater would be a reason why the text becomes invisible...
I used div#floater to represent the image, has same effect.
HTML:
<div id="outer">
<div id="floater">
</div>
<div id="inner">
<h1>Title1</h1>
<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>
<h1>Title2</h1>
<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>
<h1>Title3</h1>
<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>
And the CSS code:
#outer{
position: relative;
font-size: 10pt;
width: 100vw;
min-height: 88vh;
column-count: 3;
column-gap: 1vw;
padding-top: 54vw;
background-color: red;
}
#outer #floater{
position: absolute;
right: 0;
top: 0;
width: 66vw;
height: 50vw;
margin-bottom: 2vw;
display: block;
border: 2px solid blue;
}
#outer #inner{
max-width: 100vw;
background-color: green;
margin-top: -11vw;
}
I made a fiddle, in Chrome 'Title 1' diappears, in Safari and Firefox no problem. Any suggestions?
https://jsfiddle.net/20drzb3k/5/
You can give a try to backface-visibilty to cure that visual bug.
#outer #inner > *{
backface-visibility:hidden;
}
https://jsfiddle.net/20drzb3k/7/
For infos, Here is another example with a different approach (a pseudo element is pulling up first col content. https://codepen.io/gc-nomade/pen/boZaVJ

Resources