flexboxでCSSのwidthプロパティにcalcを利用します。以下のhtml構造でテストします。デモページではクラス名boxのdivタグは12個並べています。全てのdivタグの間に10pxの余白があります。
<div class="container">
<div class="box">
<img src="images/photo01.jpg" alt="">
<h3>タイトル01</h3>
<p>ダミーテキストダミーテキスト</p>
</div>
<div class="box">
<img src="images/photo02.jpg" alt="">
<h3>タイトル02</h3>
<p>ダミーテキストダミーテキスト</p>
</div>
<div class="box">
<img src="images/photo03.jpg" alt="">
<h3>タイトル03</h3>
<p>ダミーテキストダミーテキスト</p>
</div>
<div class="box">
<img src="images/photo04.jpg" alt="">
<h3>タイトル04</h3>
<p>ダミーテキストダミーテキスト</p>
</div>
</div>
ブラウザ幅769px以上で4カラム・768px以下で3カラムにする場合です。
まずクラス名boxのdivタグにwidth: calc(25% - 30px / 4);を指定します。全ての余白の合計30pxを4カラムで割って、1つのdivタグの横幅25%から差し引きます。また、.box:nth-child(4n)で4の倍数のdivタグの右マージンを0にします。
次にメディアクエリで768px以下の設定をします。クラス名boxのdivタグにwidth: calc(100% / 3 - 20px / 3);を指定します。全ての余白の合計20pxを3カラムで割って、1つのdivタグの横幅100% / 3から差し引きます。また、.box:nth-child(3n)で3の倍数のdivタグの右マージンを0にして、4の倍数のdivタグの右マージンは元に戻します。ただしこの指定のままでは12番目のdivタグの右マージンに4の倍数のdivタグの右マージンが設定されてしまうため、.box:nth-child(12)で12番目のdivタグの右マージンを0にします。
.container {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.box {
width: calc(25% - 30px / 4);
margin: 0 10px 10px 0;
border: 1px solid #ddd;
background: #fff;
}
.box:nth-child(4n) {
margin: 0 0 10px 0;
}
@media screen and (max-width: 768px) {
.box {
width: calc(100% / 3 - 20px / 3);
}
.box:nth-child(3n) {
margin: 0 0 10px 0;
}
.box:nth-child(4n) {
margin: 0 10px 10px 0;
}
.box:nth-child(12) {
margin: 0 0 10px 0;
}
}
なお、カラム数が変更になってもこの方法を利用して横幅と余白を設定すれば、カラム落ちすることなく対応できます。
769px以上:3カラム・768px以下:2カラム
769px以上:2カラム・768px以下:1カラム
769px以上:5カラム・768px以下:3カラム





