Aligning a doubly wrapped nested flex - css

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.

Related

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>

Flexbox: Multiple containers, containers on flex items?

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>

Vertically aligning content in a row, relative to entire row in twitter bootstrap 3

I'm trying to center a icon next to a given text blurb vertically. As a simple example, this is what the structure looks like (http://bootply.com/98109):
<div class="row">
<div class="col-xs-2 text-center">icon</div>
<div class="col-xs-10">
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.
</div>
</div>
The more complex variation is that I also want to nest two of these rows in a row while still vertically aligning both the icons to the same vertical position.
I've created a (non-working) example of this structure here:
http://bootply.com/98111
Any idea how to achieve this?
check this solution
The trick is using display table and table-cell
.table{
display: table;
vertical-align: middle;
}
.table-cell{
display: table-cell;
vertical-align: middle;
float: none;
}

Two column layout, navigation div on the right, solution from previous thread didn't seem to work

I tried the solution from this thread, but I must be missing something because it doesn't work:
<div style="float:left;margin-right:200px">
<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 style="float:right;width:200px">
<p>navigation</p>
</div>
It works when the text in the content div (the left one) is short, but when it's long then the div takes up the whole width of the browser and the margin is there, but the right div is pushed below the first one nevertheless.
What am I missing?
Edit: The goal is to have a fix sized navigation column on the right of the browser window and the left div should get all the space left by the right navigation column (liquid layout).
What ever you want to float: right; you need to place above the div that needs to be on the left. Now this way you have your width:200px for navigation on the right and your dynamical changing content on the right.
<div style="float:right; width:200px">
<p>navigation</p>
</div>
<div style="margin-right: 200px;">
<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>
Hey... floating both left. I don't know if I exactly get the gist of what you're trying to do, but from the way you're explaining the problem, I think floating both left will help you achieve your goal. Let me know...
EDIT: Also, you need to define a width for both DIV containers if you want a two column layout to be reliazed. So, in sum... float both LEFT and define widths for each that will stay inside a parent container or viewport (factoring for margins and padding if used)
-Rob
Does this work?
<div id="nav">
<p>navigation</p>
</div>
<div id="main">
<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>
#nav {
width:200px;
float:right;
}
#main {
float:right;
}
Try this:
<div style="width: 1000px; position: relative;">
<div style="position: relative; margin-right: 210px;">
Left column
</div>
<div style="width: 200px; margin: 0px; position: absolute; right: 0px; top: 0px;">
Right column
</div>
</div>

Resources