CSS Flexbox: wrap item tile grid, specify items per row? - html

I have a div with 20 items:
<div class="brand-illustrations">
<img src="modules/foundation/assets/images/pb_brand_icons_01_Shipping.svg">
<img src="modules/foundation/assets/images/pb_brand_icons_02_Time_Savings.svg">
<img src="modules/foundation/assets/images/pb_brand_icons_03_Increase.svg">
<img src="modules/foundation/assets/images/pb_brand_icons_04_Decrease.svg">
<img src="modules/foundation/assets/images/pb_brand_icons_05_Money.svg">
<img src="modules/foundation/assets/images/pb_brand_icons_06_Money_Savings.svg">
<img src="modules/foundation/assets/images/pb_brand_icons_07_Accuracy.svg">
...etc...
</div>
And I made the enclosing div a flexbox:
.brand-illustrations {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
img {
display: block;
}
}
Which does as expected:
But I'd prefer to wrap to the next row after every 5th item. I know about n-th-child but am unsure the best way to use it with flex items.

You can't force flexbox to wrap as it has no grid function. At best you can fix the width of each flex-item to 20% with 'flex: 0 0 20%'..but I'd suggest wrapping each image in a div as they have unexpected results under flexbox.
Codepen Demo
.container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.box {
flex: 0 0 20%;
text-align: center;
margin-bottom: 1em;
}
img {
max-width: 100%;
min-width: 0;
height: auto;
}
<div class="container">
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
<div class="box">
<img src="http://placekitten.com/100/100" alt="" />
</div>
</div>

Related

How to centre-align a title above few image?

my relative html code now is like this. I haven't add the title in the below code yet. Please help. Thank you.
<div class="body">
<div class="intro">
<h1>Main.</h1>
<h3>type something</h2>
<section class="buttonone">
<button>Sign up</button>
</section>
</div>
<section class="container">
<figure>
<div class="random"><img src="drink.jpg" alt=""></div>
<figcaption>lemonade</figcaption>
</figure>
<figure>
<div class="random"><img src="toro.jpg" alt=""></div>
<figcaption>omakasa-Toro sushi</figcaption>
</figure>
<figure>
<div class="random"><img src="noodle.jpg" alt=""></div>
<figcaption>ramei</figcaption>
</figure>
<figure>
<div class="random"><img src="oyster.jpg" alt=""></div>
<figcaption>oyster sushi</figcaption>
</figure>
</section>
use flexbox
img {
width: 10vw;
}
.container {
display: flex;
justify-content: space-around;
}
#title{
text-align:center;
border:solid 1px black;
}
figure{
border:solid 1px black;
padding:6px;
}
<div id='title'>my Title</div>
<section class="container">
<figure>
<div class="random"><img src="https://via.placeholder.com/150" alt=""></div>
<figcaption>lemon</figcaption>
</figure>
<figure>
<div class="random"><img src="https://via.placeholder.com/150" alt=""></div>
<figcaption>omaka</figcaption>
</figure>
<figure>
<div class="random"><img src="https://via.placeholder.com/150" alt=""></div>
<figcaption>ramei</figcaption>
</figure>
<figure>
<div class="random"><img src="https://via.placeholder.com/150" alt=""></div>
<figcaption>oysteri</figcaption>
</figure>
</section>
you just need to add flexbox to your CSS code! with justify-content
I also used css grid for centering vertically easily using the new place-items css property
.container {
/* make items one near the other in the X axis */
display: flex;
justify-content: space-around;
}
img {
/* if the image is a lot bigger, it will be resized and be responsive */
max-width: 100%;
}
/* centering vertically */
.container>figure,
.intro {
display: grid;
place-items: center;
}
<div class="body">
<div class="intro">
<h1>Main.</h1>
<h3>type something</h2>
<section class="buttonone">
<button>Sign up</button>
</section>
</div>
<section class="container">
<!-- 1 -->
<figure>
<div class="random">
<img src="https://picsum.photos/200" alt="">
</div>
<figcaption>lemonade</figcaption>
</figure>
<!-- 2 -->
<figure>
<div class="random">
<img src="https://picsum.photos/200" alt="">
</div>
<figcaption>omakasa-Toro sushi</figcaption>
</figure>
<!-- 3 -->
<figure>
<div class="random">
<img src="https://picsum.photos/200" alt="">
</div>
<figcaption>ramei</figcaption>
</figure>
<!-- 4 -->
<figure>
<div class="random">
<img src="https://picsum.photos/200" alt="">
</div>
<figcaption>oyster sushi</figcaption>
</figure>
</section>
</div>
Make a parent container class=container and make two child containers class=text centre for center aligned text and class=img grid for the image grid.
Now your parent container class will be having display: flex property with flex-grow or width property now for text you'll be putting text-align: center and for grid class you'll be using justify-content: space-between
Simply you have to add css h1 {text-align: center;}
.container{
display:flex;
}
h1{
text-align: center;
}
img{
max-width: 100%;
}
<div class="body">
<div class="intro">
<h1>Title</h1>
</div>
<section class="container">
<figure>
<div class="random">
<img src="https://i.picsum.photos/id/1076/201/201.jpg?hmac=w0KXxl0av8l5EHqgJfjULxPosXBvFTV86-fnAGgZbnY" alt="">
</div>
</figure>
<figure>
<div class="random">
<img src="https://i.picsum.photos/id/1076/201/201.jpg?hmac=w0KXxl0av8l5EHqgJfjULxPosXBvFTV86-fnAGgZbnY" alt="">
</div>
</figure>
<figure>
<div class="random">
<img src="https://i.picsum.photos/id/1076/201/201.jpg?hmac=w0KXxl0av8l5EHqgJfjULxPosXBvFTV86-fnAGgZbnY" alt="">
</div>
</figure>
<figure>
<div class="random">
<img src="https://i.picsum.photos/id/1076/201/201.jpg?hmac=w0KXxl0av8l5EHqgJfjULxPosXBvFTV86-fnAGgZbnY" alt="">
</div>
</figure>
</section>
</div>
Use display: flex; justify-content: center; and make sure you have a width of a 100% and those CSS properties will work almost everywhere.
<div class="body">
<div class="intro">
<h1>Main.</h1>
<h3>type something</h2>
<section class="buttonone">
<button>Sign up</button>
</section>
</div>
<h1 class="title">Title</h1>
<section class="container">
<figure>
<div class="random">
<img src="./pexels-till-daling-12461880.jpg" alt="">
</div>
<figcaption>lemonade</figcaption>
</figure>
<figure>
<div class="random">
<img src="./pexels-till-daling-12461880.jpg" alt="">
</div>
<figcaption>omakasa-Toro sushi</figcaption>
</figure>
<figure>
<div class="random">
<img src="./pexels-till-daling-12461880.jpg" alt="">
</div>
<figcaption>ramei</figcaption>
</figure>
<figure>
<div class="random">
<img src="./pexels-till-daling-12461880.jpg" alt="">
</div>
<figcaption>oyster sushi</figcaption>
</figure>
</section>
</div>
.title {
width: 100%;
display: flex;
justify-content: center;
}
.container {
display: flex;
justify-content: center;
}
img {
width: 10rem;
height: 10rem;
}

Is it possible to adjust the heights of each individual item of a row in grid? [duplicate]

This question already has answers here:
CSS-only masonry layout
(4 answers)
Closed 1 year ago.
I am trying to make a gallery that is uneven and staggered by using images and colored divs that are not the same size. I have the columns set to a min of 352px and to auto-fit the screen. So the container with grid looks something like this:
display: grid;
grid-template-columns: repeat(auto-fit, minmax(352px, 1fr));
grid-gap: 20px;
The issue I am having is the tallest picture sets the height of the row and the divs that have the smaller images follow the same height. Is there a way to tell the items in the row to not all be the same size? Or rather just target certain items in each row and tell them to be a specific height?
.grey {
background: #D9D9D9;
}
.tan {
background: #DCCEC8;
}
.light-brown {
background: #DC997D;
}
.brown {
background: #814A3D;
}
.black {
background: #000;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(352px, 1fr));
grid-gap: 20px;
}
.grid > div {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
img {
max-width: 350px;
width: 350px;
}
.overlay {
position: absolute;
width: 350px;
height: 100%;
background: rgba(0, 0, 0, 0.05);
}
h4 {
text-transform: uppercase;
font-size: 26px;
color: #fff;
position: absolute;
z-index: 9;
}
h4:nth-child(2) {
bottom: 35px;
}
h4:nth-child(3) {
font-size: 18px;
margin: 5px 0;
bottom: 5px;
}
.fill {
max-width: 350px;
height: 100%;
width: 100%;
}
<div class='grid'>
<div>
<img class="thumbnail" src="https://picsum.photos/500/600" alt="person" />
<h4>Person One</h4>
<h4>#person1</h4>
<div class="overlay"></div>
</div>
<div><div class="tan fill"></div></div>
<div>
<img class="thumbnail" src="https://picsum.photos/300/220" alt="person" />
<h4>Person TWO</h4>
<h4>#person2</h4>
<div class="overlay"></div>
</div>
<div><div class="black fill"></div></div>
<div>
<img class="thumbnail" src="https://picsum.photos/700/700" alt="person" />
<h4>Person 3</h4>
<h4>#person3</h4>
<div class="overlay"></div>
</div>
<div>
<img class="thumbnail" src="https://picsum.photos/400/400" alt="person" />
<h4>Person four</h4>
<h4>#person4</h4>
<div class="overlay"></div>
</div>
<div>
<img class="thumbnail" src="https://picsum.photos/500/260" alt="person" />
<h4>Person Five</h4>
<h4>#pesron5</h4>
<div class="overlay"></div>
</div>
<div><div class="light-brown fill"></div></div>
<div><div class='brown fill'></div></div>
<div>
<img class="thumbnail" src="https://picsum.photos/600/220" alt="person" />
<h4>Person Six</h4>
<h4>#person6</h4>
<div class="overlay"></div>
</div>
<div><div class="black fill"></div></div>
<div>
<img class="thumbnail" src="https://picsum.photos/200/350" alt="person" />
<h4>Person Seven</h4>
<h4>#person7</h4>
<div class="overlay"></div>
</div>
<div>
<img class="thumbnail" src="https://picsum.photos/500/300" alt="person" />
<h4>Person Eight</h4>
<h4>#person8</h4>
<div class="overlay"></div>
</div>
<div><div class="tan fill"></div></div>
<div>
<img class="thumbnail" src="https://picsum.photos/250/250" alt="person" />
<h4>Person Nine</h4>
<h4>#Person9</h4>
<div class="overlay"></div>
</div>
<div>
<img class="thumbnail" src="https://picsum.photos/300/220" alt="person" />
<h4>Person Ten</h4>
<h4>#person10</h4>
<div class="overlay"></div>
</div>
</div>
Use height on the grid items. Moreover, the headings should be wrapped in a container and their default margins should be overwritten so that headings fit in container with image's height < 150px.
.grey {
background: #d9d9d9;
}
.tan {
background: #dccec8;
}
.light-brown {
background: #dc997d;
}
.brown {
background: #814a3d;
}
.black {
background: #000;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(352px, 1fr));
grid-gap: 20px;
}
.grid>div {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
img {
max-width: 350px;
width: 350px;
}
.overlay {
position: absolute;
width: 350px;
height: fit-content;
background: rgba(0, 0, 0, 0.05);
bottom: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
}
h4 {
text-transform: uppercase;
font-size: 26px;
color: #fff;
z-index: 9;
text-align: center;
margin: 0;
margin-bottom: 10px;
}
.fill {
max-width: 350px;
height: 100%;
width: 100%;
}
.grid-item {
height: fit-content;
height: -moz-fit-content;
}
<div class="grid">
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/500/1000" alt="person" />
<div class="overlay">
<h4>Person One</h4>
<h4>#person1</h4>
</div>
</div>
<div>
<div class="tan fill"></div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/1500/2000" alt="person" />
<div class="overlay">
<h4>Person TWO</h4>
<h4>#person2</h4>
</div>
</div>
<div>
<div class="black fill"></div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/700/1500" alt="person" />
<div class="overlay">
<h4>Person 3</h4>
<h4>#person3</h4>
</div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/400/100" alt="person" />
<div class="overlay">
<h4>Person four</h4>
<h4>#person4</h4>
</div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/500/200" alt="person" />
<div class="overlay">
<h4>Person Five</h4>
<h4>#pesron5</h4>
</div>
</div>
<div>
<div class="light-brown fill"></div>
</div>
<div>
<div class="brown fill"></div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/600/220" alt="person" />
<div class="overlay">
<h4>Person Six</h4>
<h4>#person6</h4>
</div>
</div>
<div>
<div class="black fill"></div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/200/150" alt="person" />
<div class="overlay">
<h4>Person Seven</h4>
<h4>#person7</h4>
</div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/500/300" alt="person" />
<div class="overlay">
<h4>Person Eight</h4>
<h4>#person8</h4>
</div>
</div>
<div>
<div class="tan fill"></div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/250/250" alt="person" />
<div class="overlay">
<h4>Person Nine</h4>
<h4>#Person9</h4>
</div>
</div>
<div class="grid-item">
<img class="thumbnail" src="https://picsum.photos/300/220" alt="person" />
<div class="overlay">
<h4>Person Ten</h4>
<h4>#person10</h4>
</div>
</div>
</div>

How do I create a grid-styled layout without grid or flexbox?

I want to create a grid styled layout without using grid or flexbox. I am assuming I need float for this. One of the issues is that the images aren't' filling the entire space. Any advice on how to do this?
.container {
max-width: 90%;
margin: 0 auto;
}
.grid-item {
width: 25%;
float: left;
}
.grid-item img {
object-fit: cover;
width: 100%;
height: auto;
}
<div class="container">
<div class="grid">
<div class="grid-item phone">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
</div>
</div>
I suggest using the columns rule, specifying the number of columns and a width of 1/4 of the total width for responsiveness:
columns: 4 25vh;
Thus, the template with the image is now responsive without media queries.
.container {
max-width: 90%;
margin: 0 auto;
}
.grid {
columns: 4 25vh;
}
.grid-item {
/*width: 25%;
float: left;*/
}
.grid-item img {
object-fit: cover;
width: 100%;
height: auto;
}
<div class="container">
<div class="grid">
<div class="grid-item phone">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
<div class="grid-item camera">
<img src="https://picsum.photos/400/200" alt="" />
</div>
<div class="grid-item watch">
<img src="https://picsum.photos/500/300" alt="" />
</div>
</div>
</div>

How to make div height to be always proportional of its width (without hacks)?

I have a Flexbox div with 12 images within. I want width of every image to be 25% of that div. That image must have height = 133,33% of width. And in case image has dimensions that not equal to my 3*4, image has to be scaled to fit my 3*4. So how can I achieve that? I think I need a tool like calc(width*4/3).
My css and html:
.image-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
width: 100%;
}
.image-grid .image-wrapper {
width: 25%;
height: 133.3333%; // nothing happens if I delete this line. Flexbox?
}
.image-grid .image {
display: block;
width: 100%;
object-fit: cover;
}
<div class="image-grid">
<div class="image-wrapper"><img src="assets/img/portfolio-1.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-2.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-3.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-4.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-5.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-6.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-7.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-8.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-9.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-10.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-11.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="assets/img/portfolio-12.jpg" alt="" class="image"></div>
</div>
My code works perfect with images that are exactly 3*4, but if an image has other dimensions, I get that:
Ok, the solution is found. Just set wrapper's padding as 133.33% instead of height (and set my img's position as absolute). This is what I'd call a "trick" or "hack", but it solves my problem rather clearly. More details here: description
you can maintain a 3:4 aspect-ratio on the wrapper by putting padding-top: 133.33%on it.
So instead of setting the height, you can set the padding.
Also you need to set position: relative to the wrapper and position: absolute to the child, so the positioning of the child ignores the padding.
there's an example in the following snippet:
.row {
display: flex;
flex-wrap: wrap;
}
.column {
width: 25%;
}
.wrapper {
padding-top: 133.33%;
border: 1px solid red;
position: relative;
}
.wrapper img {
position: absolute;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
bottom: 0;
right: 0;
object-fit: cover;
}
<div class="row">
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
<div class="column">
<div class="wrapper">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREb_QCChITKrV0oIljZeP1irlF4UT74fQbJYNiawkZ9efEgREQoA">
</div>
</div>
</div>
Try this:
.image-grid {
display: flex;
flex-wrap: wrap;
}
.image-grid .image-wrapper {
position: relative;
width: 25%;
height: 0;
padding-bottom: 33.3333%;
}
.image-grid .image {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="image-grid">
<div class="image-wrapper"><img src="https://picsum.photos/200/300?1.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/300/200?2.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/200/200?3.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/300/300?4.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/300/400?5.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/200/200?6.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/200/200?7.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/200/400?8.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/400/200?9.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/200/200?1.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/200/200?2.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="https://picsum.photos/200/200?4.jpg" alt="" class="image"></div>
</div>
Here's an idea that should work if the container spans the complete width of the window:
Make the image container 25% wide and 25vw*4/3 high (there you have your calc...). Also use overflow: hidden on the container to keep the fixed ratio.
Make the images 100% high and set their width to auto. This will make them fill the container vertically. Then center them by appliying transform: translate-x(-50%), position: relative and left: 50%;.
This only works for images whose height is less than 4/3 of the width, but from what I understood, that's the situation you have?
* {
margin: 0;
}
.image-grid {
display: flex;
flex-wrap: wrap;
}
.image-grid .image-wrapper {
flex-shrink: 1;
flex-grow: 0;
width: 25%;
height: calc(25vw*4/3);
overflow: hidden;
}
.image-grid .image {
height: 100%;
width: auto;
display: block;
position: relative;
left: 50%;
transform: translateX(-50%);
}
<div class="image-grid">
<div class="image-wrapper"><img src="http://lorempixel.com/output/city-h-c-300-400-1.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/transport-h-c-300-400-5.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/cats-h-c-300-360-6.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/nature-h-c-300-335-10.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/transport-h-c-300-400-5.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/cats-h-c-300-360-6.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/nature-h-c-300-335-10.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/city-h-c-300-400-1.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/cats-h-c-300-360-6.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/city-h-c-300-400-1.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/transport-h-c-300-400-5.jpg" alt="" class="image"></div>
<div class="image-wrapper"><img src="http://lorempixel.com/output/nature-h-c-300-335-10.jpg" alt="" class="image"></div>
</div>

Bootstrap 4 - How to keep a sidebar same height as responsive square?

I have the following setup:
I have an image box as a responsive square using a pseudo element :after and padding-bottom: 100%;
The issue:
I want to have a sidebar next to my box, which can contain any number of small thumbnail images. However, in default Bootstrap behavior, the smaller of the boxes gets adjusted to the bigger one. Instead, I am trying to get the sidebar to always be the same height as the main images. If it is bigger, the content should scroll vertically instead.
I have tried to achieve this using a wrapper around my sidebar, however the box still grows to its size instead.
My question:
How can I ensure the sidebar only gets the maximum height of my square box next to it?
https://jsfiddle.net/Sirence/rzx6t8ey/
.row {
margin-top: 20px;
}
.row>div {
border: solid 1px #6c757d;
padding: 10px;
}
img {
display: block;
border: 1px solid red;
}
.sidebar>div:not(:last-child) img {
margin-bottom: 10px;
}
.main img {
width: 100%;
height: 100%;
object-fit: cover;
}
.main .wrapper {
border: 1px solid green;
position: relative;
}
.main .wrapper:after {
content: "\00a0";
display: block;
padding-bottom: 100%;
line-height: 0;
}
.main .holder {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
}
.sidebar-wrapper .sidebar {
height: 100%;
overflow-y: scroll;
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="row">
<div class="col-1 sidebar">
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
</div>
<div class="col-2 main">
<div class="wrapper">
<div class="holder">
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-1 sidebar">
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
</div>
<div class="col-2 main">
<div class="wrapper">
<div class="holder">
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-1 sidebar-wrapper">
<div class="sidebar">
<div class="thumbnail">
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
<div>
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
</div>
</div>
<div class="col-2 main">
<div class="wrapper">
<div class="holder">
<img class="thumbnail" src="http://via.placeholder.com/20x20" class="img-fluid" />
</div>
</div>
</div>
</div>
</div>
This is definitely possible with only pure CSS. Alright, the premise of this is simple. You want for your row to always take the height of the responsive image and not the long list of thumbnails as you mentioned.
We need to tell the browser to only look at the height of the image and ignore the thumbnail list, and to do that we remove the thumbnail list from the document flow with position absolute.
I replicated your bootstrap layout, albeit more simply, and implemented what I just mentioned. I set the sidebar positioning to relative with vertical overflow to scroll. I styled it with a fixed flex width with no grow or shrink and then placed another absolute positioned container div to house the thumbnails.
I then added a second column where the main image will be. All that was left was to add the img-fluid bootstrap style to make the image responsive and voila!
Working fiddle here: Click Here
And this is the code:
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
<style>
.container-overrides {
background: #ccc;
margin: 20px auto;
max-width: 500px !important;
}
.sidebar {
position: relative;
overflow-y: scroll;
flex: 0 0 50px;
}
.sidebar .image-container {
position: absolute;
left: 0;
right: 0;
top: 10px;
bottom: 10px;
}
.sidebar img {
display: block;
margin: 0 auto 10px;
}
.sidebar img:last-of-type {
margin: 0 auto;
}
.main{
background:#ccc;
}
.main img {
height: auto;
border: 1px solid red;
}
</style>
<div class="container p-0 container-overrides">
<div class="row no-gutters">
<!-- Responsive Sidebar -->
<div class="sidebar bg-dark p-2">
<div class="image-container">
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
<img src="http://via.placeholder.com/20x20" />
</div>
</div>
<!-- Main Image Container -->
<div class="col p-2 main">
<img src="https://ih1.redbubble.net/image.393347411.1344/flat,800x800,070,f.jpg" class="img-fluid" />
</div>
</div>
</div>