Automatically take the biggest height CSS stylus - css

simple problem, sometime i have more content in card (make it bigger), and i want the one that is smaller to take automatically the height of the bigger one.
You can see explicitly what i mean on the picture attached.
I'm using quasar (vuejs framework) and stylus
Here is my code for the css of the box :
<style lang="stylus" scoped>
.q-card {
margin: 10px;
width : auto;
img {
height : 150px;
}
}
</style>
UPDATE
And the html concerned :
<ais-results :stack="true" class="row">
<template slot-scope="{ result }">
<div class="col-md-3 col-xs-6">
<q-card>
<q-card-media>
<img :src="result.picture">
</q-card-media>
<q-card-title>
{{result.name_event}}
<q-rating slot="subtitle" :max="5" />
<div slot="right" class="row items-center">
<q-icon name="place" /> 250 ft
</div>
</q-card-title>
<q-card-main>
<p v-if="result.place.location" style="color:#48C8B8">
<q-icon name="place" />{{result.place.name}}, {{result.place.location.city}}
</p>
<p class="text-faded">{{result.start_time}}</p>
</q-card-main>
<q-card-separator />
<q-card-actions>
<q-btn flat round dense icon="event" />
<q-btn flat color="primary" label="Reserve" />
</q-card-actions>
</q-card>
</div>
</template>
</ais-results>
Thanks in advance to the community !

Just use a simple CSS grid:
.grid-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-row-gap: 10px;
grid-column-gap: 10px;
}
.q-card {
background-color: #f8f8f8;
box-shadow: 0 0 3px #666;
text-align: center;
}
.q-card img {
max-width: 100%;
}
<div class="grid-container">
<div class="q-card">1 <br />1.1<br />1.1.1</div>
<div class="q-card">2</div>
<div class="q-card">3
<img src="https://lorempixel.com/420/320/abstract/1/Sample" alt="" />
3.1
</div>
<div class="q-card">4</div>
</div>
All grid items will automatically have equal height on a per-row basis, which seems to be exactly what you are looking for.
If you need fixed-width columns, there you go:
grid-template-columns: repeat(2, 500px);

Related

CSS Image grid spacing issue

Im trying to add a image grid to a section in my page.
I've used this code:
<div class="champ-container">
<img src="image" />
<img src="image" />
<img src="image" />
<img src="image" />
<img src="image" />
</div>
CSS:
#champ-container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(3, max-content);
}
#champ-container img {
width: 100%;
}
here is what it currently doing:
There is a large space between each image, and I can't figure out why. I want maybe a 10px gap between the images. For this grid, I'm looking for three across and the rest wrapping to the next row. I dont understand how the third image ended up as its own row. all images are the same size: 288x164.
#champ-container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(3, max-content);
}
#champ-container img {
width: 100%;
}
<div id="champ-container">
<img src="image" />
<img src="image" />
<img src="image" />
<img src="image" />
<img src="image" />
</div>
You have used champ-container class in html but you have used it as an id. Change your css to this
Correct CSS:
.champ-container {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(3, max-content);
}
.champ-container img {
width: 100%;
}

Can bootstrap grid system use the width of the parent "container-fluid" as its media with?

In bootstrap 5.2, the breakpoints of the grid system is the width of the screen #media. This works great for the most parts. But when nesting grids it becomes tricky to deal with.
In my project, I am using reusable components to generate the HTML. When these components are used to create a nested fields, the outcome isn't as desired. For example, I have a component names TextInput, this component will generate something like this
<div class="row mb-3">
<label for="Example1" class="col-form-label col-lg-2 col-xl-3 text-lg-end">Example1</label>
<div class="col-lg-10 col-xl-9">
<input type="email" class="form-control" id="Example1" placeholder="name#example.com">
</div>
</div>
My TextInput component could be called from another component which generated nesting.
Here is an example of nesting, I am trying to change the position of the labels based on the size of the container "not the screen". When the screen is large, we place the label on the same row as the input. When the screen is less than large, the label appears above the input making it responsive while utilizing the with of the screen more efficiently.
If you look at the nested container "red color below", you'll see that its width is much smaller that the main container "blue color below" since it's nested inside of it.
I can add logic inside of each component I have and manually change the bootstrap classes. But this would require lots of code changes and lots of conditions to consider. I am hoping for a solution using css/js that I can use.
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8" crossorigin="anonymous"></script>
<div class="container-fluid bg-info pb-3">
<form>
<div class="row mb-3">
<label for="Example1" class="col-form-label col-lg-2 col-xl-3 text-lg-end">Example1</label>
<div class="col-lg-10 col-xl-9">
<input type="email" class="form-control" id="Example1" placeholder="name#example.com">
<div class="container-fluid bg-danger pb-3 nested-fields-container">
<div class="row mb-3">
<label for="Nested1" class="col-form-label col-lg-2 col-xl-3 text-lg-end">Nested1</label>
<div class="col-lg-10 col-xl-9">
<input type="email" class="form-control" id="Nested1" placeholder="name#example.com">
</div>
</div>
</div>
</div>
</div>
</form>
</div>
Question
Is there a way to change the grid system to use the width of the parent container-fluid as its breakpoints instead of using the #media (size of the screen) to define the breakpoints for all of the nested grids?
If this is something that isn't possible in the grid system, is there a way to do it using Flex system,
Probably not. I think there are some proposals for CSS Container Queries (not widely supported) and some libraries that allow container wise media queries.
Here's a polyfill for Container Queries! https://www.npmjs.com/package/container-query-polyfill and a demo
Not sure if this fits your requirements exactly, but hopefully it might help you. You can use CSS grid to change column widths without breakpoints. I don't know of a fully supported way to target parent elements in CSS (probably for good reason).
<!DOCTYPE html>
<html lang="en">
<head>
<style type="text/css">
* {
box-sizing: border-box;
}
body {
margin: 0 auto;
width: 100%;
height: 100%;
}
/* Example responsive grid layout */
.c-1 {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
grid-auto-rows: 200px;
margin: 0 auto;
overflow: hidden;
width: 100%;
}
.c-2 {
background-color: #ddd;
padding: 1em;
margin: 0 auto;
border: 1px solid red;
width: 100%;
grid-column: 1/3;
}
.c-3 {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
margin: 0 auto;
border: 1px solid green;
width: 100%;
}
.c-4 {
padding: 1em;
}
.c-4:first-child > .c-4 {
border: 1px solid blue;
}
.c-4 input, .c-4 label {
width: 90%;
}
</style>
</head>
<body>
<div class=c-1>
<div class=c-2>
Grid Column 1/3
<div class=c-3>
<div class=c-4>
<label>Label 1</label>
<input type=text size=10>
<div class=c-4>
<label>Label 2</label>
<input type=text size=10>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Fiddle Demo:
https://jsfiddle.net/pz2gsd58/
CSS Grid:
https://css-tricks.com/look-ma-no-media-queries-responsive-layouts-using-css-grid/

pushing icons closer together in footer gone wrong?

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>

How to properly use media query to achieve this result?

I want to build a responsive webpage using Angular 6.I tried to do so using bootstrap but failed miserably.So ultimately I decided to go with media query.
This is my code:
.width {
width: 300px;
height: 300px;
display: inline-block;
border: 1px solid blue;
}
.width1 {
width: 800px;
height: 300px;
border: 1px solid blue;
display: inline-block;
}
#media only screen and (max-width: 600px) {
.width {
background-color: black;
width: 200px;
height: 100px;
}
.width1 {
width: 500px;
}
}
<div class="container-fluid ">
<div class="row">
<div class="badge width col-md-offset-1 col-lg-offset-1 col-xl-offset-1">
Hello I am in component 1.
</div>
<div class="badge width col-md-offset-1 col-lg-offset-1 col-xl-offset-1">
Hello I am in component2.
</div>
<div class="badge width col-md-offset-1 col-lg-offset-1 col-xl-offset-1">
Hello I am in component3.
</div>
</div>
<br>
<br>
<br>
<div class="row">
<div class="badge width col-md-offset-1 col-lg-offset-1 col-xl-offset-1">
Hello I am in component 4.
</div>
<div class="badge width1 col-md-offset-1 col-lg-offset-1 col-xl-offset-1">
Hello I am in component 5.
</div>
</div>
</div>
The result that I am getting for a medium screen is given below and this is the result that I want:
However the problem arises , when I try to increase my browser resolution using 'CTRL +' . The orientation of the boxes gets jumbled up.But I want my result to look the same as it did in the medium settings.
The following is a screenshot of the result on larger screens.
How do I fix this?
I think what you need to do is better achieved using CSS Grid, it will allow you to build the layout with few rules and basically no media queries (if you intend the layout to be exactly the same all the time)... look at this:
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(200px, auto);
grid-gap: 20px;
}
.grid-item {
border: 1px solid;
}
.item5 {
grid-column: span 2;
}
section {
background-color: blue;
height: 100%;
color: #FFF;
}
<div class="grid-container">
<div class="grid-item item1">
<section>
Inner Section
</section>
</div>
<div class="grid-item item2">Item 2</div>
<div class="grid-item item3">Item 3</div>
<div class="grid-item item4">Item 4</div>
<div class="grid-item item5">Item 5</div>
</div>
I think the problem you're running into is using Ctrl + in the hopes of increasing your browser width. Ctrl + is just meant to enlarge text for accessibility reasons.
To effectively manage browser/viewport width in Chrome, right click your page, select Inspect. With the Inspect pane open, your browser window will now have the width x height in the top right of the page.
As for your code, I'm not able to reproduce the result in the first image you sent (it has obviously different CSS than in the provided snippet).
To make this work as you are wanting, I would suggest looking into Flexbox, it's relatively new and pretty powerful so definitely worth learning.

Photowall with double sized highlight pictures

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

Resources