Place wrapping items in the center of the grid - html

I have a CSS Grid layout which looks like below:
This works perfectly for me, but when I lower the resolution of the screen, the grid's responsiveness makes the grid look like this:
Instead, I want the wrapping items to justify the left and right white spaces, and they should look like this:
How can I achieve the above? The items are dynamic in number. There can be even number of items which will make it look better as the left and right white spaces will be equally spaced. But if the items are odd in number the white spaces should still be equally distributed. I tried with grid-auto-flow and align-items, but they don't seem to be helping.
.accordioninnergrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.innerbox {
display: flex;
border: 1px solid black;
flex-direction: column;
align-items: center;
word-wrap: break-word;
width: auto;
}
.innerbox>p,
img {
margin: 1%;
}
<div class="accordioninnergrid">
<div class="innerbox">
<img src="some-image" width="50%" height="50%" />
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
<div class="innerbox">
<img src="some-image" width="50%" height="50%" />
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
<div class="innerbox">
<img src="some-image" width="50%" height="50%" />
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
<div class="innerbox">
<img src="some-image" width="50%" height="50%" />
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
<div class="innerbox">
<img src="some-image" width="50%" height="50%" />
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
</div>

This is a problematic layout with Grid or Flex. There's no simple solution with either.
With Grid, there's no way to automatically position items in the middle columns. How does the grid know it needs to place grid items in, let's say, columns 3, 4 and 5, so that they appear centered?
Worse, what if there were only four columns and one item to center? That item would have to span across columns 2 and 3.
There's no grid function that does this automatically. It must be author-defined.
With Flex, the problem above doesn't exist. But there's a trade-off. Flex has a problem that Grid doesn't have.
It stems from this section of the code:
.accordioninnergrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
The grid-template-columns rule is saying that each column can be a minimum width of 240px, and a maximum width of 1fr (i.e., all available space).
In flex, the property to use in place of the fr function would be flex-grow.
But, because there are no column tracks impeding movement across the line in a flex container, flex-grow is free to expand items across the entire line.
In short, flex-grow and centering cannot co-exist.
If flex-grow were removed, then you'd have no problem centering with flex. But, of course, there would be another trade-off: you would lose the consumption of free space feature:
.accordioninnergrid {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.innerbox {
flex: 1 0 140px; /* fg, fs, fb -- try fg: 0 */
display: flex;
border: 1px solid black;
flex-direction: column;
align-items: center;
word-wrap: break-word;
}
.innerbox > p,
img {
margin: 1%;
}
<div class="accordioninnergrid">
<div class="innerbox">
<img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
<div class="innerbox">
<img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
<div class="innerbox">
<img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
<div class="innerbox">
<img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
<div class="innerbox">
<img src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
<p>
This is the text
</p>
<p>
Small Tagline
</p>
</div>
</div>
More details here:
Aligning grid items across the entire row/column (like flex items can)
Targeting flex items on the last or specific row

Related

Put a text beneath an image

I am currently working on a website and what i want to do is I want four pictures in a square and I want a text underneath them.
I already managed to put the four images but once i try to put a text it goes everywhere but not underneath the images
HTML:
<section class="section-2">
<div class="item">
<img src="#">
<p>text</p>
</div>
<div class="item">
<img src="#">
<p>text</p>
</div>
<div class="item">
<img src="#">
<p>text</p>
</div>
<div class="item">
<img src="#">
<p>text</p>
</div>
</section>
CSS:
.section-2 {
margin: 200px 30px 30px 30px;
width:100%;
float:right;
min-height:1000px;
height:100%;
}
img {
float:left;
margin: 0px 100px 200px 150px;
width: 30%;
height: 30%;
The easiest and shortes way would be to simply align the cards in a grid. For that use display: grid;. To have 2 cards aligned horizontally you need to add: grid-template-columns: repeat(2, 1fr); you can change the number 2 with the numebr of cards you want to have aligned next to each other. To seperate the cards from each other, you can use grid-gap: with a value of the gap you want to have.
.section-2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 15px;
}
.section-2 div img {
width: 100%;
}
<section class="section-2">
<div>
<img src="https://www.tacoshy.de/Images/Yoshi/IMAG0735.jpg">
<p>I'm a Syrian Hamster</p>
</div>
<div>
<img src="https://www.tacoshy.de/Images/Yoshi/IMAG0736.jpg">
<p>I like to eat watermelons</p>
</div>
<div>
<img src="https://www.tacoshy.de/Images/Areno/IMAG0865.jpg">
<p>I love to burrow tunnels and caves</p>
</div>
<div>
<img src="https://www.tacoshy.de/Images/Areno/IMAG0863.jpg">
<p>And I really enjoy sleeping in my self digged caves</p>
</div>
</section>

How to make text in Flexbox, not defining width of flexbox?

I have this issue: I have flexbox with 3 photos in the center of the screen.
under these photos, I have some text like mobile number etc.
When I add this text into this boxes, this text is defining the width of my box, and it's moving boxes and they are not in the center anymore.
Final result should be: The box width should be the same but text should break and be centered.
Here you can see size of one box
Here you can see size od the other box
Snippet:
.ikony {
padding-top: 60px;
display: inline-flex;
justify-content: center;
width: 100%;
font-weight: 600;
font-size: 16px;
color: #020E46;
text-align: center;
font-family: Open Sans,Arial,sans-serif;}
.column {
padding: 90px 70px 0px 70px;}
<div class="ikony">
<div class="column prvy">
<img src="img/mobil-icon.png" alt="iconka-mobil" width="100px" height="100px">
<div class="txtpod">
<p>+421 918 000 000</p>
</div>
</div>
<div class="column">
<img src="img/pin-icon.png" alt="ikona pinu" width="100px" height="100px">
<div class="txtpod">
<p>address 273/14, Svit</p>
</div>
</div>
<div class="column">
<img src="img/email.png" alt="ikona pinu" width="100px" height="100px">
<div class="txtpod">
<p>myemail#gmail.com</p>
</div>
</div>
</div>
Thanks for any advice
Add flex-grow: 0 and width: 33% to the flex items (.column) to prevent them to get wider.
However, if you have something like an email address in one of the containers that forces it to be wider than 33% because it contains no spaces and therefore can't break into several lines (like in your snippet example), you should use a small font that lets it fit into the 33% width.

Specific columns

I've been doing some stuff with HTML and I need to have a few columns. I know how to make them and the basics of how they work. However, there is a certain problem that I have. I need to have 3 columns that have an image on top, then text on bottom. However, the text on bottom can't flow into the next column if the browser is resized - it just needs to go up or down. What I have so far:
body {
background-color: white;
font-family: times, serif;
color: black;
}
div {
display: flex;
margin: 50px;
flex-wrap: wrap;
}
<div>
<div class="first">
<img src="Images/australia_flag.jpg" alt="Australian Flag" title="Australian Flag" height="200" width="300"> text as well </div>
<div class="second">
<img src="Images/brazil_flag.jpg" alt="Brazilian Flag" title="Brazilian Flag"> even more text </div>
<div class="third">
<img src="Images/china_flag.jpg" alt="Chinese Flag" title="Chinese Flag" height="200" width="300"> text again
</div>
</div>
not entirely sure if you mean columns or rows? Based on your code, it looks like rows. If that's the case, I'm not sure what you mean by "flow into the next column"? You might check out the relative and absolute values for CSS position.
If, in fact, you do actually mean columns, I'd strongly advise using Bootstrap's Grid System. This is great for creating responsive columns.
Please take a look at this simple 3 column layout with a full width content area on top and bottom here: https://jsfiddle.net/7drfva0o/2/
.top, .bottom {
width:98%;
padding:1%;
background-color: red;
clear:both;
}
.cols {
width:31%;
padding:1%;
float:left;
background-color:blue;
border: 1px solid #FFF;
}
Is that what you're looking for?
First, you'll need to improve your markup: having images and texts as DOM node to be "flexed"
HTML markup improved
<div class="wrapper">
<div class="column">
<img src="..." />
<p>text</p>
</div>
<div class="column">
<img src="..." />
<p>text</p>
</div>
<div class="column">
<img src="..." />
<p>text</p>
</div>
</div>
Then, each of your div is going to have display: flex + flex-direction: column to allow the image going on top and the text going below. You will be able to adjust margin or whatever. At the minimum, I'd go like this:
CSS improved
.wrapper {
display: flex;
}
.column {
margin: 5px;
display: flex;
flex-direction: column;
}
Wrapped altogether, here is a snippet of what I think you're trying to achieve
Snippet
.wrapper {
display: flex;
}
.column {
margin: 5px;
display: flex;
flex-direction: column;
}
<div class="wrapper">
<div class="column">
<img src="http://fakeimg.pl/300x200" />
<p>text as well</p>
</div>
<div class="column">
<img src="http://fakeimg.pl/300x200" />
<p>text as well</p>
</div>
<div class="column">
<img src="http://fakeimg.pl/300x200" />
<p>text as well</p>
</div>
</div>
Then, feel free to play with flexbox properties to align, wrap, adjust alignments, etc. Great documentation on CSS-Tricks : https://css-tricks.com/snippets/css/a-guide-to-flexbox/

Center text with images in flexbox

I'm making a webpage and need to center-align 3 divs as promo content, like that:
In order to get this spacing and alignment, I added invisible images and made then hidden on mobile, so they get responsive, like that:
<div id="promocontent">
<img class="img-responsive" src="img/iconenope.png">
<img class="img-responsive hidden hide-on-med-and-down" src="img/iconehidden.png">
<img class="img-responsive" src="img/iconenope.png">
<img class="img-responsive hidden hide-on-med-and-down" src="img/iconehidden.png">
<img class="img-responsive" src="img/iconenope.png"><br><br>
</div>
CSS:
#promocontent {
display: flex; /* establish flex container */
flex-direction: row; /* default value; can be omitted */
flex-wrap: nowrap; /* default value; can be omitted */
justify-content: space-between; /* switched from default (flex-start, see below) */
padding: 5px;
}
Now, I need to add text on the center-bottom of these images, something like:
So, how can I do that (responsively working)? Align 2 lines of text (maybe 1, but 2 would be better).
Thank you.
#promocontent {
display: flex;
justify-content: space-between;
padding: 5px;
}
#promocontent > div {
display: flex;
flex-direction: column;
align-items: center; /* horizontally center child elements */
text-align: center; /* horizontally center text on narrow screens;
see http://stackoverflow.com/q/39678610/3597276 */
}
<div id="promocontent">
<div>
<img class="img-responsive" src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
<h2>header text</h2>
<span>text text text text text</span>
</div>
<div>
<img class="img-responsive" src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
<h2>header text</h2>
<span>text text text text text</span>
</div>
<div>
<img class="img-responsive" src="http://i.imgur.com/60PVLis.png" width="50" height="50" alt="">
<h2>header text</h2>
<span>text text text text text</span>
</div>
</div>
https://jsfiddle.net/x2rzj1cu/2/
I would avoid using an extra image for spacing and just rely on justify-content: space-between
Feel free to check out my codepen (basically the same as Michaels).
http://codepen.io/anon/pen/zKmaVJ

Why does these inline-block element produce extra width?

This is a follow up from this question: Autofit text under image with only css
Why does the inline-block divs in this code produce extra width on the right side of the elements?
.item {
display: inline-block;
background-color: red;
}
.image-container {
background-color: blue;
display: table;
width: 1%;
}
img {
height: 120px;
}
.text-wrapper {
overflow: hidden;
}
<div class="item">
<div class='image-container'>
<img src='http://i.imgur.com/nV2qBpe.jpg' class="image">
<div class='text-wrapper'>
<p class='text'>Some text that may need to wrap into multiple lines</p>
</div>
</div>
</div>
<div class="item">
<div class='image-container'>
<img src='http://i.imgur.com/nV2qBpe.jpg' class="image">
<div class='text-wrapper'>
<p class='text'>Some text that may need to wrap into multiple lines</p>
</div>
</div>
</div>
<div class="item">
<div class='image-container'>
<img src='http://i.imgur.com/nV2qBpe.jpg' class="image">
<div class='text-wrapper'>
<p class='text'>Some text that may need to wrap into multiple lines</p>
</div>
</div>
</div>
<div class="item">
<div class='image-container'>
<img src='http://i.imgur.com/nV2qBpe.jpg' class="image">
<div class='text-wrapper'>
<p class='text'>Some text that may need to wrap into multiple lines</p>
</div>
</div>
</div>
Edit: This is NOT a problem with whitespace, see this jsfiddle without any whitespace and notice that the div still takes up lots of extra space (the red area): https://jsfiddle.net/2Lzo9vfc/332/
Edit2: To clarify my requirements: I have N images with varying width that I wish to layout in a "dynamic table", i.e. the images should be inline so they will automatically wrap when running out of horizontal space in parent. Where this gets tricky is that I have some text that I wish to display under each image that should wrap with the image width as well (and as I said, the image width may vary).
The red portion of the item is an artifact of the browser not knowing how to correctly size the containers. It's using the length of the text to determine the width before the table layout is applied. If you know the width of the items, you can use this simpler approach:
.item {
display: inline-block;
background-color: blue;
width: 120px;
}
.image {
display: block;
height: 120px;
}
<div class="item">
<img src='http://i.imgur.com/nV2qBpe.jpg' class="image">
<p class='text'>Some text that may need to wrap into multiple lines</p>
</div>
<div class="item">
<img src='http://i.imgur.com/nV2qBpe.jpg' class="image">
<p class='text'>Some text that may need to wrap into multiple lines</p>
</div>
<div class="item">
<img src='http://i.imgur.com/nV2qBpe.jpg' class="image">
<p class='text'>Some text that may need to wrap into multiple lines</p>
</div>
<div class="item">
<img src='http://i.imgur.com/nV2qBpe.jpg' class="image">
<p class='text'>Some text that may need to wrap into multiple lines</p>
</div>
I don't know off hand of a way to make the elements shrink to the smallest possible width while still containing all child elements.
I modified #Brandon Gano's second answer. I used display: table-caption; on .text-wrapper.
Here's the CSS I modified from his jsfiddle:
.text-wrapper {
overflow: hidden;
display: table-caption;
caption-side: bottom;
height: 60px; /* You may have to modify the height */
background-color: blue;
}
And the updated jsfiddle.
You're seeing whitespace added between the inline-block elements. You can remove the horizontal space between these items by removing all whitespace between the elements. e.g.:
<div>
...
</div><div>
...
</div><div>
...
</div>
Note that the closing tag is immediately followed by the next opening tag.