Auto column widths with images inside - html

I am currently trying to achieve the following type of grid/column but I am not able to.
Some images have bigger width than others so they need to take up more space.
I will have around 30ish images that I will loop through so i can't just put a set width to each column.
I am not sure how to tackle this problem.
I have the following and I want to have 3 per row it is giving me somewhat okey results but not exactly.
https://codepen.io/BlooDyBG/pen/OJVxYEj
<div class="flex-container">
<div class="flex-item">
<a href="https://ibb.co/CBBLGnp"><img src="https://i.ibb.co/WnnCJcN/Image-2.png" alt="Image-2"
border="0"></a>
</div>
<div class="flex-item">
<a href="https://imgbb.com/"><img src="https://i.ibb.co/HqdrqQB/Image-3.png" alt="Image-3" border="0">
</a>
</div>
<div class="flex-item">
<img src="https://i.ibb.co/r0YZVVw/Image-4.png" alt="Image-4" border="0">
</div>
<div class="flex-item">
<img src="https://i.ibb.co/7pSqfZn/Image-5.png" alt="Image-5" border="0">
</div>
<div class="flex-item">
<img src="https://i.ibb.co/R6Vd1WH/Image-6.png" alt="Image-6" border="0">
</div>
<div class="flex-item">
<img src="https://i.ibb.co/HqdrqQB/Image-3.png" alt="Image-3" border="0">
</div>
</div>
CSS
.flex-container {
display : flex;
flex-wrap: wrap;
padding : 20px;
}
.flex-item {
flex: 1 1 auto;
padding : 20px;
}
img {
width : 100%;
height : 100%;
}

The third part of the flex shorthand is flex-basis, which informs the browser how to treat sizing of the flexible items. In this case, you've set it to auto which instructs the browser to use the width of the content to determine the size.
Instead, you should use something like flex: 1 1 30% to ensure that all of the items have a consistent size.
Alternately, you can create this type of layout with CSS Grid. That would look something like this:
.flex-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}

Related

grid-template-columns CSS displaying vertically and not horizontally

I am a student working on a website. I have the below CSS/HTML script that should be displaying cards in order horizontally, however when I view it on a website its showing up vertically instead.
Goal:
[pic1] [pic2] [pic3]
[pic4] [pic5] [pic6]
Current Output:
[pic1]
[pic2]
[pic3]
[...]
[pic6]
Current Code:
I have only included code that should be relevant to my question, please let me know if I should include additional code for guidance.
.cards {
margin: 0 auto;
max-width: 1000px;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: auto;
gap: 20px;
font-family: Arial;
padding-top: 30px;
}
<div class="cards">
<div class="card">
<img src="image.jpg" alt="image" class="card__image">
<div class="card__content">
<p2>Image</p2>
</div>
<div class="card__info">
<div>
BOUNTY
</div>
</div>
</div>
</div>
<div class="cards">
<div class="card">
<img src="image2.jpg" alt="image" class="card__image">
<div class="card__content">
<p2>Image2</p2>
</div>
<div class="card__info">
<div>
BOUNTY
</div>
</div>
</div>
</div>
I would really do that with display: flex ... why? because it is easier and not that complex to work with grid and give your flex-children a flex-basis of 30% to have three children in one row.
Nevertheless, you have div class="cards" openend twice. you will probably have this div only once and div class="card__*" several times.
grid is more compatible with older versions of browsers, like IE11, but also only with the prefix, but that's just my personal thought.

How to achieve equal height image columns that shrinks

I want to achieve a grid-like layout where every column in a row has the same height. Each column contains a picture so it must also keep the proportions of the image.
The current solution is to set the flex-grow property to the ratio of the image. This works but can result in very large images which is not desired in my case.
I would like the images to shrink to fit on one row in the case of negative space left.
The flex-shrink property works similar to the flow-grow property. The negative space will be distributed between the items based on the flex-shrink property.
However there is a caveat in the flex-shrink behaviour: the item will never shrink to a size less than the content of it. In my case that means the column will never shrink to a size less than the images it contains.
I can work around the problem by setting the flex-basis property to a smaller value. I've played around with this but either messed up the wrapping or the equal heights.
What I would like to happen:
Consider the following markup:
.container {
display: flex;
flex-wrap: wrap;
width: 600px;
}
.img-container {
padding: 5px;
box-sizing: border-box;
flex-basis: auto;
}
.img {
width: 100%;
height: auto;
}
<div class="container">
<div style="flex-grow: 1; flex-shrink: 1;" class="img-container">
<img class="img" src="https://via.placeholder.com/200x200/" alt="">
</div>
<div style="flex-grow: 1; flex-shrink: 1;" class="img-container">
<img class="img" src="https://via.placeholder.com/200x200/" alt="">
</div>
<div style="flex-grow: 2; flex-shrink: 2;" class="img-container">
<img class="img" src="https://via.placeholder.com/400x200/" alt="">
</div>
</div>
The sum of the width is 200+200+400=800px which means there is 800-600=200px negative space. The flex-shrink values dictates that item one and two gets 1 part of the negative space and that item three gets 2 parts.
Calculating this gives us:
Width to remove from item one: 1/4*200=50
Width to remove from item two: 1/4*200=50
Width to remove from item three: 2/4*200=100
These widths are correct and would keep the correct ratios but as I mentioned earlier this cannot be achieved since the flex-basis is the natural width of the image elements.
Do you guys have any suggestions on how to solve this problem?
If you set the width of your .container and the height of your .img-container it should work.
Now you only have to decide how you want to space your images. .container { justify-content: space-evenly/space-between/space-around}
.container {
display: flex;
flex-wrap: wrap;
width: 600px;
justify-content: space-evenly;
}
.img-container {
padding: 5px;
box-sizing: border-box;
flex-basis: auto;
height: 150px;
}
.img {
width: auto;
height: 100%;
}
<div class="container">
<div class="img-container">
<img class="img" src="https://via.placeholder.com/200x200/" alt="">
</div>
<div class="img-container">
<img class="img" src="https://via.placeholder.com/200x200/" alt="">
</div>
<div class="img-container">
<img class="img" src="https://via.placeholder.com/400x200/" alt="">
</div>
<div class="img-container">
<img class="img" src="https://via.placeholder.com/400x200/" alt="">
</div>
<div class="img-container">
<img class="img" src="https://via.placeholder.com/400x200/" alt="">
</div>
<div class="img-container">
<img class="img" src="https://via.placeholder.com/200x200/" alt="">
</div>
<div class="img-container">
<img class="img" src="https://via.placeholder.com/200x200/" alt="">
</div>
<div class="img-container">
<img class="img" src="https://via.placeholder.com/200x200/" alt="">
</div>
<div class="img-container">
<img class="img" src="https://via.placeholder.com/200x200/" alt="">
</div>
</div>

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/

CSS - Keep image aspect ration flexbox

I have a small photo gallery with some photo's.
It looks good on pc (full size), but when I resize it (for phone), it does not keep it's aspect ratio and it only streches the with.
This is what it looks like right now: https://gyazo.com/a1f605bb410865579025644b0a267adf
Also, as you can see it goes to 1 image, and at a certain point it goes back to 2 images for a split second and it stays on 1 image after. How do I fix that too?
This is my CSS:
#images{
display: flex;
flex-wrap: wrap;
}
.image{
display: flex;
flex: 1;
margin: 5px;
min-width: 250px;
min-height: 187.5px;
object-fit: contain;
}
.image > img{
flex: 1;
}
This is my HTML:
<div id="images">
<div class="image">
<img src="f1.jpg">
</div>
<div class="image">
<img src="f2.jpg">
</div>
<div class="image">
<img src="f3.jpg">
</div>
<div class="image">
<img src="f1.jpg">
</div>
//it just goes on and on like this
//it's all temporary now, I will eventualy replace
//this with a simple loop.
</div>
Unless you have very specific requirements, I suggest Masonry:
a JavaScript grid layout library. It works by placing elements in
optimal position based on available vertical space, sort of like a
mason fitting stones in a wall. You’ve probably seen it in use all
over the Internet.
in combination with imagesLoaded For a versatile lightweight solution.
There are many ways to implement Masonry.
The following is my personal favorite.
All my comments are inside the snippet below
body {
background: #131418;
}
/* Step 1: start with resetting some defaults */
* {
margin: 0 auto;
padding: 0;
max-width: 100%;
}
/* Step 2: center things inside the grid and clear some space around it by setting a device based max-width and margin*/
.grid {
text-align: center;
max-width: 95vw;
margin: 2.5vw auto;
}
/* Step 3: how big should the gap be between grid items? remember that the total gap between two items would be double what you set here since both would have that amount set as their individual padding. Also add box-sizing:border-box to make sure the padding doesn't affect the total widh of the item */
.grid-item {
padding: 5px;
box-sizing: border-box;
}
/* Step 4: Add media queries (subjective) to make the whole grid resposive. */
#media (min-width: 500px) {
.grid-item {
width: 50%;
}
}
#media (min-width: 1000px) {
.grid-item {
width: 33.333%;
}
}
#media (min-width: 1700px) {
.grid-item {
width: 25%;
}
}
#media (min-width: 2100px) {
.grid-item {
width: 20%;
}
}
<!-- Made possible by the great work of David DeSandro # https://masonry.desandro.com -->
<!-- Part 1: Add the scripts -->
<!-- Step 1: Let's start by loading jQuery. jQuery is not required for masonary to function but makes things easier -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Step 2: Then load imagesloaded. imagesloaded makes sure the images are not displayed until they are fully loaded -->
<script src="https://unpkg.com/imagesloaded#4/imagesloaded.pkgd.min.js"></script>
<!-- Step 3: we load masonry -->
<script src="https://unpkg.com/masonry-layout#4/dist/masonry.pkgd.min.js"></script>
<!-- Part 2: Create the grid -->
<!-- Step 1: Start with a the main grid wrapper-->
<div class="grid">
<!-- Step 2: Add grid items--->
<div class="grid-item">
<img src="https://s-media-cache-ak0.pinimg.com/736x/00/37/03/0037037f1590875493f413c1fdbd52b1--cool-beards-inspiring-photography.jpg" />
</div>
<div class="grid-item">
<img src="https://s-media-cache-ak0.pinimg.com/736x/cd/90/d9/cd90d9de63fa2c8e5c5e7117e27b5c18--gritty-portrait-photography-studio-photography.jpg">
</div>
<!-- Step 3: repeat...--->
<div class="grid-item">
<img src="https://1.bp.blogspot.com/-9QM7ciGXRkQ/V1hsB-wNLBI/AAAAAAAAMoA/eYbSHs00PTAjrI4QAmvYAIGCUe1AuRAnwCLcB/s1600/bryan_cranston_0095.jpg">
</div>
<div class="grid-item">
<img src="http://webneel.com/sites/default/files/images/project/best-portrait-photography-regina-pagles%20(10).jpg" />
</div>
<div class="grid-item">
<img src="https://s-media-cache-ak0.pinimg.com/736x/dd/45/96/dd4596b601062eb491ea9bb8e3a78062--two-faces-baby-faces.jpg" />
</div>
<div class="grid-item">
<img src="http://www.marklobo.com.au/news/wp-content/uploads/2013/03/Melbourne_Portrait_Photographer_Mark_Lobo-Cowboy.jpg" />
</div>
<div class="grid-item">
<img src="https://format-com-cld-res.cloudinary.com/image/private/s--PcYqe7Zw--/c_limit,g_center,h_65535,w_960/a_auto,fl_keep_iptc.progressive,q_95/145054-8576001-Rob-Green-by-Zuzana-Breznanikova_7725_b_w.jpg" />
</div>
<div class="grid-item">
<img src="http://www.iefimerida.gr/sites/default/files/janbanning11.jpg" />
</div>
<div class="grid-item">
<img src="https://s-media-cache-ak0.pinimg.com/736x/66/bb/e7/66bbe7acc0d64da627afef440a29714b--portrait-photos-female-portrait.jpg" />
</div>
<div class="grid-item">
<img src="https://s-media-cache-ak0.pinimg.com/736x/25/34/b6/2534b6c18c659546463f13b2dc62d4ce--natural-portraits-female-portraits.jpg" />
</div>
<div class="grid-item">
<img src="https://s-media-cache-ak0.pinimg.com/originals/8d/67/12/8d671230ced871df8428b571ed6ec192.jpg" />
</div>
</div>
<!-- Part 3: the script call -->
<!-- Now that everything is loaded we create a script to trigger masonary on $grid. Note that this simply says: "if the images are fully loaded, trigger masnory on $grid. -->
<script>
$(".grid").imagesLoaded(function() {
$(".grid").masonry({
itemSelector: ".grid-item"
});
});
</script>
Recently, I discover the CSS property : object-fit
She's contain multiple options :
contain
fill
cover
none
scale-down
It's very easy, and keeps a good ratio of the image
Documentation : HERE
UPDATE - I've added an example.
#images {
display: flex;
flex-wrap: wrap;
}
.image {
flex: 1;
}
.image img {
width: 100%;
height: auto;
}
<div id="images">
<div class="image">
<img src="https://i.guim.co.uk/img/media/4f48e55216fe5c09963e6cac4ec2530cc08a4e36/0_0_600_600/master/600.jpg?w=300&q=55&auto=format&usm=12&fit=max&s=add90ae66a8a0c9b35606346845539f9">
</div>
<div class="image">
<img src="https://i.guim.co.uk/img/media/4f48e55216fe5c09963e6cac4ec2530cc08a4e36/0_0_600_600/master/600.jpg?w=300&q=55&auto=format&usm=12&fit=max&s=add90ae66a8a0c9b35606346845539f9">
</div>
<div class="image">
<img src="https://i.guim.co.uk/img/media/4f48e55216fe5c09963e6cac4ec2530cc08a4e36/0_0_600_600/master/600.jpg?w=300&q=55&auto=format&usm=12&fit=max&s=add90ae66a8a0c9b35606346845539f9">
</div>
<div class="image">
<img src="https://i.guim.co.uk/img/media/4f48e55216fe5c09963e6cac4ec2530cc08a4e36/0_0_600_600/master/600.jpg?w=300&q=55&auto=format&usm=12&fit=max&s=add90ae66a8a0c9b35606346845539f9">
</div>
</div>
For keeping image aspect ratio, you can define width:100% and height:auto.
It will adjust the image to the width of the container with keeping the aspect ratio.

Why is flexbox creating unused space below my content?

I have some slides where I'm trying to equally space content using display: flex but it's adding a large empty area below my content and above the navigation.
When the screen shrinks to the mobile size the empty area becomes much more apparent.
I have no idea why it's doing this, or why switching display: flex to display:table messes things up even more.
After spending two days I've come for some guidance.
Here's a test link to what I have. Click on 1 - 4 to get to a screen using flex.
<div class="slide" id="slide-one" data-slide="1">
<p class="deck">You don’t have to wait until bad weather is imminent to prepare for a power outage. Take some time to get organized with these tips.</p>
<div class="row">
<div class="section" id="emergency-kit">
<div class="rollover center">
<div class="button-container">
<div class="button"></div>
</div>
<div class="text">Create an Emergency Kit</div>
</div>
<div class="container">
<img src="img/emergency-kit.png" alt="" />
</div>
</div>
<div class="section" id="food-prep">
<div class="rollover center">
<div class="button-container">
<div class="button"></div>
</div>
<div class="text">Prep Your Food</div>
</div>
<div class="container">
<img src="img/fridge.png" alt="" />
</div>
</div>
</div>
</div>
.row {
display: flex;
width:100%;
flex-direction: row;
margin-top: 20px;
}
#emergency-kit {
width:40%;
display: inline-block;
.container {
max-width: 263px;
}
}
#food-prep {
width:40%;
display: inline-block;
.container {
max-width: 167px;
}
}
Also, using flexslider for the slideshow animations.
The source of the gap has nothing to do with flexbox. Your flex container (.row) is nested within a larger container.
div.row
... is a descendant of div.flex-viewport
... which takes up all the height to the bottom navbar.
On the smaller screen, div.row isn't even a flex container anymore. It's switched to a block element:
Possible options for closing the gap:
Reduce the height of one of the containers
Define heights for all container elements between .flex-viewport and .row
Apply display: flex to all containers, so children can expand the full height of their parent