This question already has an answer here:
flex items ignoring width
(1 answer)
Closed 1 year ago.
I have a DIV with "display: flex;" that contains 2 child DIVs next to each other. The first one is just a DIV that contains some ordered list items and the second DIV contains some images. The second DIV has display: flex and flex-wrap: wrap applied to it.
For some reason, when I give the first DIV a width of 200px, it's not working... it doesn't get a width of 200px. But if instead I give it a min-width of 200px, then it works and gets a width of 200px. I need to understand why does width not work while min-width works...
/* Parent container that contains 2 child DIVs */
.parent_flex_container {
display: flex;
}
/* First child DIV */
#desktop_sidemenu {
width: 200px;
}
/* Second child DIV */
.flex_container {
display: flex;
flex-wrap: wrap;
}
/* Images of the second child DIV */
.Cac {
max-width: 50%;
height: 50%;
margin-bottom: 20px;
padding: 0 5px;
}
<div class="parent_flex_container">
<div id="desktop_sidemenu">
<nav>
<ul>
<li>Arabic</li>
<li>Green tea</li>
</ul>
</nav>
</div>
<div>
<div id="Featured_grid">
<div class="grid_title_holder">
<h2>Featured</h2>
</div>
<div class="flex_container">
<div class="Cac">
<img src="images/cover1.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover2.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover1.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover2.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover1.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover2.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover1.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
<div class="Cac">
<img src="images/cover2.jpg" alt="" title="" />
<p class="Artist_name_holder">Artist Name</p>
<p class="Song_title_holder">Song Title</p>
</div>
</div>
</div>
</div>
</div>
So let's start with this when you using flexbox each child items will have 3 different elements which are:
flex-basis
flex-grow
flex-shrink
Where each of them has a different responsibility.
flex-basis
Flex-basis controls the default size of an element before it is manipulated by other Flexbox properties. It could be used as a width or height property. Let's see the below example:
.flexbox {
display: flex;
}
.red {
background: red;
flex-basis: 100px;
}
.green {
background: green;
flex-basis: 100px;
}
.blue {
background: blue;
flex-basis: 100px;
}
<div class="flexbox">
<div class="red">1</div>
<div class="green">2</div>
<div class="blue">3</div>
</div>
flex-grow
Now, when it comes to the property called flex-grow, the default is 0. That means the squares are not allowed to grow to take up space in the container. You can see the example below for more resolution:
.flexbox {
display: flex;
}
.red {
background: red;
flex-grow: 0;
}
.green {
background: green;
flex-grow: 0;
}
.blue {
background: blue;
flex-grow: 0;
}
<div class="flexbox">
<div class="red">1</div>
<div class="green">2</div>
<div class="blue">3</div>
</div>
So whats make a difference here, Well, let’s try incrementing flex-grow to 1 for every square:
.flexbox {
display: flex;
}
.red {
background: red;
flex-grow: 1;
}
.green {
background: green;
flex-grow: 1;
}
.blue {
background: blue;
flex-grow: 1;
}
<div class="flexbox">
<div class="red">1</div>
<div class="green">2</div>
<div class="blue">3</div>
</div>
flex-shrink
Flex-shrink is the opposite of flex-grow, determining how much a square is allowed to shrink. ts main use is to specify which items you want to shrink, and which items you don’t. By default, every square has a flex-shrink of 1. To see how shrink works see the below snippet:
.flexbox {
display: flex;
}
.red {
background: red;
flex-grow: 0;
flex-basis: 100px;
flex-shrink: 1;
}
.green {
background: green;
flex-grow: 0;
flex-basis: 100px;
flex-shrink: 0;
}
.blue {
background: blue;
}
<div class="flexbox">
<div class="red">1</div>
<div class="green">2</div>
<div class="blue">3</div>
</div>
NOTE: you have to resize the browser to see the difference in the above squares.
Actual answer
So your problem lies here in the flex-shrink property, hence default value of flex-shrink is 1 so it will look like this:
#desktop_sidemenu {
width: 200px;
flex-shrink: 1; /* default setting of browser */
}
So that is why the width property alone does not do the work for you which means your first div will be shrinked in order to prevent the boxes get out of order, then all you have to do to make it work is to give it a min-width: 200px or flex-shrink: 0.
NOTE: there is a shorthand for these three property called flex which you can give these three properties as one with the following order:
flex: 0 0 200px; /* flex-grow flex-shrink flex-basis */
For more information about these kinds of stuff, you can follow the MDN here.
I need to understand why does width not work while min-width works...
Because flex items are set, by default, to flex-shrink: 1, which means that they can shrink in order to minimize overflow of the container.
Your actual code (what the browser sees) is this:
#desktop_sidemenu {
width: 200px; /* author defined */
flex-shrink: 1; /* default setting */
}
You need to disable flex-shrink:
#desktop_sidemenu {
width: 200px;
flex-shrink: 0;
}
Now, because the item can't shrink below 200px, it's equivalent to min-width: 200px.
For more details, see "The flex-shrink factor" in my answer here:
What are the differences between flex-basis and width?
Related
I have a flex div that contains two further elements. When viewed fullscreen on a desktop, one of the elements acts as a sidebar. On smaller screens, the elements collapse to be displayed one on top of the other.
This technique is explained on Every Layout.
I want to introduce a sticky element that will be used for navigation. On a wide screen, it works as expected. I can scroll the page and the sitcky element sticks to the top. However, in a narrower window, the element does not stick. It scrolls out of view – the same in both Safari and Firefox.
.with-sidebar {
display: flex;
flex-wrap: wrap;
}
.with-sidebar > :first-child {
flex-basis: 20rem;
flex-grow: 1;
background-color: green;
}
.with-sidebar > :last-child {
flex-grow: 999;
min-inline-size: 50%;
background-color: red;
}
.sticky {
position: sticky;
top: 1rem;
}
<div class="with-sidebar">
<div>
<h1>Sidebar</h1>
<div style="height:10rem">Spacer</div>
<div class="sticky">
<h1>Sticky Element</h1>
</div>
</div>
<div>
<h1>Not Sidebar</h1>
<div style="height:200rem">Spacer</div>
</div>
</div>
Among other things, I have tried wrapping the sticky inside another element, tried applying align-self: flex-start; to the sticky. I haven't yet found anything that works.
How can I ensure that the element is sticky when the sidebar and not-sidebar are stacked vertically as well as when they are alongside each other?
Update
I have experimented with placing .with-sidebar within a taller wrapper. Now it is clear what is happening. The element which is not the sidebar is pushing the sticky element off screen. This never happens when the elements are side by side. But, in a smaller window, the not-sidebar element is directly beneath the sticky element.
<div style="height: 400rem">
<div class="with-sidebar">
<div>
<h1>Sidebar</h1>
<div style="height:10rem">Spacer</div>
<div class="sticky">
<h1>Sticky Element</h1>
</div>
</div>
<div>
<h1>Not Sidebar</h1>
<div style="height:60rem">Spacer</div>
</div>
</div>
</div>
I think it's better to redo the markup (or design). See, for example, if you specify a height for a block, in which the "sticky element" is located, div:has(.sticky) { height: 500px; } then the element starts to "stick a little", or another example, change nesting
<body>
<div class="with-sidebar">
<div>
<h1>Sidebar</h1>
<div style="height: 10rem">Spacer</div>
<!-- <div class="sticky">
<h1>Sticky Element</h1>
</div> -->
</div>
<div class="sticky">
<h1>Sticky Element</h1>
</div>
<div>
<h1>Not Sidebar</h1>
<div style="height: 200rem">Spacer</div>
</div>
</div>
</body>
and add a property align-self for this element.
.sticky {
position: sticky;
top: 1rem;
align-self: flex-start;
}
But I don't think that's all for you. This is just an examples so you can see how the element works. The specification CSS Positioned Layout Module Level 3 very briefly describes the behavior of elements when positioned sticky.
Use media queries for top position if 10rem is not as you want...
.sticky {
position: fixed;
top: 10rem;
}
Update: I clarify my thoughts:
<div class="with-sidebar">
<div>
<h1>Sidebar</h1>
<div style="height:10rem">Spacer</div>
<div class="sticky_desktop">
<h1>Sticky Element</h1>
</div>
</div>
<div>
<div class="sticky_mobile">
<h1>Sticky Element</h1>
</div>
<h1>Not Sidebar</h1>
<div style="height:200rem">Spacer</div>
</div>
</div>
.with-sidebar {
display: flex;
flex-wrap: wrap;
}
.with-sidebar > :first-child {
flex-basis: 20rem;
flex-grow: 1;
background-color: green;
}
.with-sidebar > :last-child {
flex-grow: 999;
min-inline-size: 50%;
background-color: red;
}
.sticky_desktop {
position: sticky;
top: 1rem;
}
.sticky_mobile {
position: sticky;
top: 1rem;
color: violet;
}
.sticky_mobile>h1{
margin-block-start: 0;
margin-block-end: 0;
}
#media screen and (min-width : 656px ){
.sticky_mobile {
display:none;
}
}
#media screen and (max-width : 655px ){
.sticky_desktop {
display:none;
}
}
im trying to create a footer with a few social media icons...however, the method i've tried has resulted in the following problem :
expectation:
reality:
as you can see i'm failing in bringing the social media icons closer together... i tried setting the columns flex % to - however that pulls everything closer together towards the left of the screen...
here is my .row and .column as well as the social media icons..
.row {
display: flex;
}
.column {
flex: 30%;
padding: 00px;
}
.marginauto1 {
margin: 30px auto 20px;
display: block;
horizontal-align; middle;
vertical-align: middle;
}
<footer class= "marginauto1">
<center><div class="row">
<div class="column">
<center><a class= "pointer" href="twitter_url">
first time taking a stab at this on my own and I'm just really stuck here.. any help or tips would be appreciated!
If you want to put all your icons together in the middle:
img{
height:50px;
}
div{
display:flex;
justify-content: center;
background-color:blue;
}
<footer>
<div>
<img src="data:image/png;base64,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">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRyFcxKQYRAhR9esHvHVZokZGCYFNC1_rMHhw&usqp=CAU">
</div>
</footer>
<center> tag will not applicable if you are using flexbox. Instead flex-box itself has some properties that you can make use of. In your use-case you can go with justify-content: center
.row{
display: flex;
justify-content: center;
}
.item{
color: red;
background: lightblue;
margin-left: 20px;
}
<footer class= "marginauto1">
<div class="row">
<div class="item 1">
<h1>Telegram</h1>
</div>
<div class="item 2">
<h1>Facebook</h1>
</div>
<div class="item 3">
<h1>Twitter</h1>
</div>
</div>
</footer>
If you don't want any space in between of 2 or more items you can remove the margin.
Its working as expected. You have defined .column with flex: 30%; which intrun will split into 3
flex-grow: 1;
flex-shrink: 1;
flex-basis: 30%;
So what have you done is allowing the element to grow till the available width with a minimum of 30% relative to the container. This is because the flex-basis is defined. This will be 33% each.
For your soution to work remove flex: 30%; from .column. This will take the width depending on the content.
If you want some gap between the element, try adding some margin or padding, I have used margin for that. Or you can set the width of column element.
Inorder to align the items center in horizontal axis, use justify-content: center; for the flex element.
Working Fiddle
.row {
display: flex;
justify-content: center;
}
.column {
padding: 0px;
margin-right: 20px;
}
.marginauto1 {
margin: 30px auto 20px;
display: block;
}
.pointer img {
width: 50px;
}
<footer class="marginauto1">
<div class="row">
<div class="column">
<a class="pointer" href="">
<img src="https://cdn1.iconfinder.com/data/icons/logotypes/32/twitter-512.png" alt="">
</a>
</div>
<div class="column">
<a class="pointer" href="">
<img src="https://cdn1.iconfinder.com/data/icons/logotypes/32/twitter-512.png" alt="">
</a>
</div>
<div class="column">
<a class="pointer" href="">
<img src="https://cdn1.iconfinder.com/data/icons/logotypes/32/twitter-512.png" alt="">
</a>
</div>
</div>
</footer>
In this jsfiddle, I want the Author element to be aligned between the various card elements. I can't see how to stretch the element containing the details to match the variably sized elements in the same row.
The goal is to have the Author lines lining up horizontally across the rows.
.container {
display: flex;
flex-flow: row wrap;
margin: 10px;
}
.card {
width: 200px;
margin: 10px;
}
.product_detail {
display: flex;
flex-direction: column;
justify-content: space-between;
border: 1px solid pink;
}
.detail_item {
border: 1px solid blue;
flex: 1;
}
img {
width: 100%;
}
<div class='container'>
<div class="card">
<section>
<img src="https://c.booko.info/covers/34edd12eb5c21388/v/600.jpeg" itemprop="image" size="500x750">
</section>
<section class="product_detail">
<div itemprop="name" class='detail_item'>
A Book Title
</div>
<div class="detail_item">A Subtitle might be here</div>
<div itemprop="author" class='detail_item'>Author</div>
</section>
</div>
<div class="card">
<section>
<img src="https://c.booko.info/covers/34edd12eb5c21388/v/600.jpeg" itemprop="image" size="500x750">
</section>
<section class="product_detail">
<div itemprop="name" class='detail_item'>
A Book Title which is much longer and takes up a few lines
</div>
<div class="detail_item">A Subtitle might be here</div>
<div itemprop="author" class='detail_item'>Author</div>
</section>
</div>
<div class="card">
<section>
<img src="https://c.booko.info/covers/34edd12eb5c21388/v/600.jpeg" itemprop="image" size="500x750">
</section>
<section class="product_detail">
<div itemprop="name" class='detail_item'>
A Book Title
</div>
<div class="detail_item">A Subtitle might be here</div>
<div itemprop="author" class='detail_item'>Author</div>
</section>
</div>
</div>
As I understood it, you are trying to have the Author div anchored to the bottom of each card.
Assuming I understood correctly, you were pretty close. Here's what was missing:
the .card div needed to be a flex container
the .product_detail section needed to stretch to fill its available space
the Author div needed to be anchored to the bottom
Here's the CSS that changed:
.card {
display: flex;
flex-direction: column;
}
.product_detail {
flex: 1;
}
.detail_item[itemprop="author"] {
margin-top: auto;
}
Here's an updated Fiddle
Note: if you don't want the .detail_item divs to be vertically evenly distributed, you can just remove the flex: 1; property from .detail_item which would look like this.
Hope this helps. Good luck!
I am aware I can get five image across a page by setting each image as width 20% and using flex-wrap: wrap. But how do I evenly space the images?
I tried justify-content: space-around; but that looks ridiculous. Padding messes up the 20% width calculation. So what's a good tact? I don't want the images to look like they are stitched together. If there are six images, there will be a large gap to right of the 6th image. I think that's fine.
article {
display: flex;
flex-wrap: wrap;
}
img {
width: 20%;
padding: 1em;
/* I want five across with image spacing, how do I achieve this? */
}
<article>
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
</article>
I would wrap the images in a tag to manage element width and image width separately. Then apply the width and padding onto the containing element. Set the width of img to auto, and max-width to 100% to prevent the images from stacking.
In addition, you can alter the number of images that display at different screen sizes by changing the wrapper class properties.
When it comes to flexbox, I always reach for CSS-tricks!
.flexbox {
display: flex;
flex-flow: row wrap;
}
.flexbox .image {
width: 20%;
padding: 0.5em;
}
.flexbox img {
width: auto;
max-width: 100%;
}
* {
box-sizing: border-box;
}
<div class="flexbox">
<div class="image"><img src="https://qph.fs.quoracdn.net/main-qimg-0e316e1a1e2a600d0b922cddb3a5c6c2"></div>
<div class="image"><img src="https://qph.fs.quoracdn.net/main-qimg-0e316e1a1e2a600d0b922cddb3a5c6c2"></div>
<div class="image"><img src="https://qph.fs.quoracdn.net/main-qimg-0e316e1a1e2a600d0b922cddb3a5c6c2"></div>
<div class="image"><img src="https://qph.fs.quoracdn.net/main-qimg-0e316e1a1e2a600d0b922cddb3a5c6c2"></div>
<div class="image"><img src="https://qph.fs.quoracdn.net/main-qimg-0e316e1a1e2a600d0b922cddb3a5c6c2"></div>
<div class="image"><img src="https://qph.fs.quoracdn.net/main-qimg-0e316e1a1e2a600d0b922cddb3a5c6c2"></div>
<div class="image"><img src="https://qph.fs.quoracdn.net/main-qimg-0e316e1a1e2a600d0b922cddb3a5c6c2"></div>
</div>
If you want the borders of the images to be aligned with the borders of the container and not offset by the padding, I would opt for a solution that relies on one sided margin, but that does not apply to the last item of each row.
Considering a row count of 5 items, and an image to image margin of 1% of the container's width, with the following DOM structure:
<div class="flex-container">
<div>
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
</div>
<div>
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
</div>
<div>
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
</div>
<div>
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
</div>
<div>
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
</div>
<div>
<img src="http://res.cloudinary.com/unee-t-staging/image/upload/c_fill,g_auto,h_500,w_500/Unee-T%20inspection%20report%20-%20placeholder%20images/table_succulent.jpg">
</div>
</div>
Apply the following styles:
.flex-container {
display: flex;
flex-wrap: wrap;
}
.flex-container div {
max-width: 19.2%; /* (100 - ((items_per_row - 1) * 1) / (items_per_row)*/
margin-bottom: 15px;
}
.flex-container div img {
width: 100%;
height: 100%;
}
.flex-container div:not(:nth-child(5n)) { /* matches number of items per row */
margin-right: 1%;
}
Example on CodePen: https://codepen.io/anon/pen/wEKmdG
Disclaimer: I'm working with #hendry on the same project...
We are working on a picture gallery site and can't find a solution for following problem.
The picture wall contains several images. Some image (n Percent) should by highlighted and get displayed double sized on the wall.
The issue is, that I have no idea to fill the empty space left of the large picture, because its a new line.
Any ideas.
I created a fiddle for this sample here: Fiddle
<body>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size2">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
<div class="size1">
</div>
</body>
div {
background-color: #f00;
float: left;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}
Update:
The following browsers now natively support CSS Grid Layout.
Firefox v52
Chrome v57 for Linux, macOS, Windows, iOS, and Android
Safari v10.1
iOS Safari v10.3
Opera v44
This kind of layout requirement is what the CSS Grid Layout spec aims to address. The introduction to the spec reads:
Grid Layout is a new layout model for CSS that has powerful abilities to control the sizing and positioning of boxes and their contents. Unlike Flexible Box Layout, which is single-axis–oriented, Grid Layout is optimized for 2-dimensional layouts: those in which alignment of content is desired in both dimensions.
Native browser support for CSS Grid Layout is likely to start landing in major browsers soon (as shown here) and is currently featured behind a flag in some. For non-supporting browsers this JavaScript polyfill will be necessary.
As an example, CSS Grid Layout syntax is shown in the following CSS:
HTML
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box box--double">5</div>
<div class="box">7</div>
<div class="box">8</div>
...
</div>
</div>
CSS using the Grid layout model
.wrapper {
width: 600px;
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(7, 100px);
grid-template-rows: 100px 100px 100px;
grid-auto-flow: row;
}
.box {
background-color: #444;
color: #fff;
padding: 20px;
font-size: 150%;
margin: 5px;
}
.box--double {
background-color: red;
grid-column: 3 / span 2;
grid-row: 2 / span 2;
}
DEMO
Here is a fiddle which utilizes CSS Grid Layout syntax (inc. the polyfill) to provide a general gist.
Alternatively, Masonry may be able to achieve this, however long term this will always be dependent on JavaScript.
Responsive Web Design (RWD)
The CSS Grid Layout module includes several features to simplify the creation of responsive designs. Two pertinent features which address the issues raised in the comments are:
1 Flexible Lengths
The fr unit should be used instead of specifying the relative column width as a percentage. The main benefit of the fr unit is that it avoids having to manually recalculate the percentage when the number of columns change via a media query - (You simply change the value for the number of columns only):
/* Avoid using percentages like this */
.wrapper {
grid-template-columns: repeat(7, 14.286%);
...
}
/* Use the 'fr' unit instead */
.wrapper {
grid-template-columns: repeat(7, 1fr);
...
}
2 grid-auto-flow-dense
Three values that can be assigned to the grid-auto-flow property, namely row, column, and dense.
.wrapper {
grid-auto-flow: dense;
...
}
In some situations when row, or column values are used it can produce unwanted holes/gaps in the layout. When specifying dense an algorithm attempts to fill those holes/gaps in, however this can sometimes change the the order of the items. This feature is very similar to the way Masonry places items in a different position based on available vertical space.
DEMO FOR RWD
Here is a responsive fiddle that uses both the fr unit and the dense value to avoid any gaps/holes in the layout.
EDIT(5): Updated list of browsers supporting CSS Grid Layout.
EDIT(4): Added note regarding Chrome 57 implementing CSS Grid Layout spec.
EDIT(3): Added note regarding Firefox 52 implementing CSS Grid Layout spec.
EDIT(2): Add useful CSS Grid Layout features for achieving RWD
EDIT(1): Changed sample code to terse version and updated link to external fiddle
Here's a CSS only solution, fully responsive, based on CSS columns
.columns >div {
background-color: #f00;
float: left;
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}
.columns {
width: 660px;
margin: 0 auto;
-webkit-columns: 200px 3;
-moz-columns: 200px 3;
columns: 200px 3;
-webkit-column-gap: 0;
-moz-column-gap: 0;
column-gap: 0;
}
#media (max-width: 689px) {
.columns {
width: 440px;
margin: 0 auto;
-webkit-columns: 200px 2;
-moz-columns: 200px 2;
columns: 200px 2;
}
}
#media (max-width: 459px) {
.columns {
display: flex;
flex-wrap: wrap;
max-width: 220px;
}
.columns div {
flex: 1 0 auto;
}
.columns .size1 {
flex-basis: calc(50% - 10px)
}
.columns .size2 {
flex-basis: calc(100% - 10px)
}
}
body {
padding: 0;
text-align: center;
}
#media (min-width: 920px) { /* 4 columns */
.columns {
width: 880px;
-webkit-columns: 200px 4;
-moz-columns: 200px 4;
columns: 200px 4;
}
}
#media (min-width: 1140px) { /* 5 columns */
.columns {
width: 1100px;
-webkit-columns: 200px 5;
-moz-columns: 200px 5;
columns: 200px 5;
}
}
#media (min-width: 1360px) { /* 6 columns */
.columns {
width: 1320px;
-webkit-columns: 200px 6;
-moz-columns: 200px 6;
columns: 200px 6;
}
}
#media (min-width: 1580px) {
/* respect the principle above to add as many columns as you like */
}
<div class="columns">
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
</div>
For mobiles media query interval, I used flexbox, but it's just to show it's possible. You really don't have to, you can stick to box-model.
Note: You can define further media intervals. The basic idea is to have a multiple of 220px and limit it to widths that have sufficient room for all columns.
Here's the fiddle (I added it as, for some reason, SO won't allow me to resize the snippet window under ~480px, while jsFiddle does.)
fiddle here
This solution assumes you will always pair 2 small items together (so they occupy 1 row). If you want a solution where this condition doesn't have to be met by whoever adds content, and automatically tries to pair small items when they are single, you need javascript.
Timeline solution (based on comments info)
I'm guessing this is what you need? (If you decide to change classnames, you'll need to adjust both js and CSS).
$('.timeline .size2').each(function(){
//moving required number of small'uns so they fill the column
var prevIndex = $(this).prevAll('.size2,.wrap').eq(0).index(),
diff = $(this).index() - (prevIndex + 1),
toMove = (3 - (diff % 3)) %3;
if (toMove) {
for (var i = 1; i < toMove + 1; i++) {
$(this).nextAll('.size1').eq(0).addClass('moved').insertBefore($(this))
}
}
var wrap = $('<div />', {
class:'wrap'
})
//wrap 2 small'uns to make a row under a big'un
for (var i = 0; i < 2; i++) {
wrap.append($(this).nextAll('.size1').eq(0));
}
wrap.insertAfter($(this));
})
.timeline [class^="size"] {
background-color: red;
}
.size1{
width: 100px;
height: 100px;
margin: 5px;
}
.size2{
width: 210px;
height: 210px;
margin: 5px;
}
.timeline {
display: flex;
flex-direction: column;
align-content: flex-start;
height: 330px;
flex-wrap: wrap;
}
.timeline .wrap {
display: inline-flex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="timeline">
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size1"></div>
<div class="size2"></div>
<div class="size1"></div>
<div class="size1"></div>
</div>
I tried to shorten the fiddle from RobC and replaced the fixed width in pixels with relative width in percent. So it is a little more responsive. But still have some gaps which you may prevent with some rules, like "no 2 big boxes side by side" and so on.
The Html
<div class="wrapper">
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/600x400/f33/fff" class="box--double" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
<img src="https://dummyimage.com/300x200/333/fff" class="" />
</div>
The CSS
.wrapper {
width: 100%;
display: grid;
grid-template-columns: repeat(6, 16.666%);
grid-auto-flow: row;
}
#media screen and (max-width: 940px) {
.wrapper {
grid-template-columns: repeat(5, 20%);
}
}
#media screen and (max-width: 540px) {
.wrapper {
grid-template-columns: repeat(3, 33.333%);
}
}
.wrapper > img {
background-color: #444;
color: #fff;
border: solid 1px white;
}
.box::before {
content: ' ';
display: block;
padding-top: 100%;
}
.box--double {
background-color: red;
grid-column: auto / span 2;
grid-row: auto / span 2;
}
The fiddle