How to Create an Image Grid that varies Between Four, Two or Full-width Images with a Click of a Button using Flexbox
Image Grid
How To, for Front End and Web Applications
By: Chrysanthus Date Published: 3 May 2025
An image grid is a rectangle of images, consisting of one or more columns, where the images in one column or across columns do not necessarily have the same height. This tutorial explains How to Create an Image Grid that varies Between Four, Two or Full-width Images, with a Click of a Button, using Flexbox. A flexbox is needed in order to have an image grid (see below).
For the project of this tutorial, there are 26 images. There are three buttons in a short horizontal row, above all the images. The buttons are labeled, 1, 2 and 4. When the webpage is loaded (for the first time), button 2 is highlighted, and the grid consists of two columns of all the images. The images are all of the same width but differing in height. When button 1 is clicked, button 1 becomes highlighted, and the grid consists of just one column. The images still differ in height, but are still of the same width, and the width of each image this time, is wider than for the case of two columns. When button 4 is clicked, button 4 becomes highlighted, and the grid consists of four columns. The images still differ in height, but are still of the same width; and the width of each image this time, is narrower than for the case of two columns.
The complete code for this project is given at the end of this tutorial. Copy all the code into a text editor. Save the file with any name, but with the extension, .html . Open the saved file in the browser. Click the three buttons and observed the change in each case. The images are in the broad-network.com website. So the reader has to be hooked on to the Internet. The reader is advised to do this, before continuing to read the rest of this tutorial.
The Webpage Skeleton Code
The skeleton code for the webpage, to which more useful code will be added is:
<!DOCTYPE html> <html> <head> <title>Image Grid</title> <link rel='icon' href='https://www.examplee.com/images/logo.jpg' type='image/x-icon'> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Description of the Web Page."> <style> </style> <script type="text/javascript"> </script> </head> <body> <script type="text/javascript"> </script> </body> </html>
Any responsible modern webpage should have at least the first four tags in the HTML Head element above. The HTML style element will have all the essential CSS rules. The HTML JavaScript element will have some code to respond to the button click. All divs with images are in the HTML body element. There is also a JavaScript in the body, to produce a second click effect, when a button is clicked.
The HTML body Element Content
The content of the body element is:
<!-- Header --> <div class="header" id="myHeader"> <h1>Image Grid</h1> <p>Click on the buttons to change the grid view.</p> <button class="btn" onclick="one()">1</button> <button class="btn active" onclick="two()">2</button> <button class="btn" onclick="four()">4</button> </div> <!-- Photo Grid --> <div class="row"> <div class="column"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/wedding.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/rocks.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/falls2.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/paris.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/nature.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/mist.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/paris.jpg" style="width:100%"> </div> <div class="column"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/underwater.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/ocean.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/wedding.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/mountainskies.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/rocks.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/underwater.jpg" style="width:100%"> </div> <!-- similar to the above --> <div class="column"> </div> <div class="column"> <!-- similar to the above --> </div> </div> <script type="text/javascript"> </script>
At the top of the code, is a div with class-name, "header" and ID="myHeader". This div has the three buttons. Buttons are by default, inline-level elements, and so they will naturally appear in a row, at the display.
After the div.header is another div, with class-name "row". This div.row has four inner divs. Each inner div has images (image tags). The four inner divs are for the four columns. The class-name for each of the inner divs is "column".
The width of each image is 100%. That is 100% relative to the inner div.
When button 4 is clicked, the four columns displayed, are the four inner divs. When button 2 is clicked, the last two columns on the right, go below the first two columns. When button 1 is clicked, the second, third and fourth columns go below the first column, in that order.
The HTML Style Element Content
Apart from the attribute, "style='width:100%' ", for the image tags, all the styles are in the CSS style-sheet (HTML style element).
At the top within the style element content, is the CSS rule:
* { box-sizing: border-box; }
This is called the box-sizing property. The asterisk, * in front of the rule, means that it is applied to all the containers, such as the div element. The box-sizing property means that the width of each element is measured from the left edge of the left border, to the right edge of the opposite border, instead of from the left edge of the element's content, to the right edge of the element's content. The box-sizing property also means that the height of each element is measured from the top edge of the top border, to the bottom edge of the opposite border, instead of from the top edge of the element's content, to the bottom edge of the element's content. The box-sizing property makes coding convenient for projects like this one.
Styling the body Element
The CSS rule for the body element is:
body { margin: 0; font-family: Arial, Helvetica, sans-serif; }
The gap for each of the four margins is 0. The font to be used by the body element and all its content, is Arial. If the browser does not have Arial, then it should use Helvetica. If the browser does not have Helvetica, then its should use a good sans-serif font, that it should have.
Styling the div with Buttons
The CSS rule for the div that has the buttons is:
div.header { padding: 32px; text-align: center; }
The content of the header div in the body element consists of an H1 Element, that extends from the left end of the div to the right end of the div; then a paragraph element that extends from the left end of the div to the right end of the div; and lastly three button elements, which are small inline elements, and would be in one horizontal line, close to one another, by default.
The padding all round (four sides) these three elements together, is 32px . "text-align: center;" means the text in the H1 element and in the paragraph element, are center aligned. Since the buttons are inline elements, they are also center aligned.
Styling the row div
There is only one row div. The CSS rule for the row div is:
div.row { display: flex; flex-wrap: wrap; padding: 0 4px; }
"display: flex;" means that the div.row is a flex-box. This implies that the inner divs (each of which has the images) can all be in a row or all be in a column. For this project, they will all be in one row (four flex items in one row), since row is the default (not column). "flex-wrap: wrap;" means that if the screen width is small, some inner divs on the right, will wrap to the next line with their images. "padding: 0 4px;" means that the the top and bottom padding of the row div is 0px, and the right and left padding of the row div, is 4px.
Styling the Inner column divs
The inner divs are the flex items. In the body element, each inner div has the class-name, "column". Do not forget that each inner div has a set of images. When there is wrapping of flex items, any inner div going to the next line below, will go with its images. The CSS rule for each flex item is:
div.column { flex: 50%; padding: 0 4px; }
"flex: 50%;" means that each inner div (flex item) will have 50% of the width of the parent div.row. Given that there are four inner divs (flex items), then the display will have two columns (two inner divs per row). This explains why when the webpage loads (for the first time) there are two columns. To have four columns, make the value of flex, 25%. To have one column, make the value of flex, 100%. To have two columns again, make the value of flex, 50% again.
"padding: 0 4px;" means that the top and bottom padding of each inner div is 0px, and the right and left padding of each inner div, is 4px.
Styling the Image Tags
The CSS rule for each image tag is:
div.column img { margin-top: 8px; }
It is the image tag that is styled here, and not the image. The margin-top of each image tag is 8px. This increases the gap between the image itself and the top of its tag; and hence increasing the gap between two images in a column (inner div).
It must be emphasized here, that each image is quite broad in width, and so there is no need to specify the widths (sizes) the images should have, in a column. Once they are in a div, since two of them cannot lie side-by-side (left-right), then they are forced to be in one column (one below the other). The image tag is an inline element.
Styling the Buttons
The CSS rule for each button is:
button.btn { border: none; padding: 10px 16px; font-size: 18px; background-color: #f1f1f1; cursor: pointer; }
No button has any border. The top and bottom padding of a button is 10px, and the right and left padding 16px. The font-size of any text in the button is 18px. The background color is #f1f1f1 (light gray). "cursor: pointer;" means that when the mouse pointer goes over a button, it should become a hand. It is fashionable to have it like that today, instead of allowing it as arrow-head.
Button On-hover
The CSS rule for button on hover is:
button.btn:hover { background-color: #ddd; }
When the mouse pointer goes over a button, its background color becomes #ddd (darker gray).
Active Button
The CSS rule for the active button is:
button.btn.active { background-color: #666; color: white; }
An active button is said to be the button, whose columns are displayed. When a button is active, its background color becomes #666 (very dark gray); the text color becomes white (for contrast).
In the body element, the second (center) button element has the attribute, "class='btn active' ". So when the webpage is loaded (for the first time), the second button is active at the browser. Any button can be made active with JavaScript (see below).
JavaScript
There are three buttons. When each button is clicked, its columns have to be displayed and the button itself has to be made, "active". The HTML code for the three buttons are retyped here, for easy access (reference) by the reader.
<div class="header" id="myHeader"> <h1>Image Grid</h1> <p>Click on the buttons to change the grid view.</p> <button class="btn" onclick="one()">1</button> <button class="btn active" onclick="two()">2</button> <button class="btn" onclick="four()">4</button> </div>
Each button has the onclick event. When the first button is clicked, the function one(), in the JavaScript in the head element is called. When the second button is clicked, the function two(), in the JavaScript in the head element is called. When the third button is clicked, the function four(), in the JavaScript in the head element is called. The JavaScript in the head element is:
<script type="text/javascript"> // Get the elements with class="column" var elements = document.getElementsByClassName("column"); // Full-width images function one() { for (var i = 0; i < elements.length; i++) { elements[i].style.flex = "100%"; } } // Two images side by side function two() { for (var i = 0; i < elements.length; i++) { elements[i].style.flex = "50%"; } } // Four images side by side function four() { for (var i = 0; i < elements.length; i++) { elements[i].style.flex = "25%"; } } </script>
In the script, first, an array of references for the column inner divs is obtained, and held in the variable, elements. In this array, index 0 corresponds to the first column inner div (with its images). Index 1 corresponds to the second column inner div (with its images). Index 2 corresponds to the third column inner div (with its images). Index 3 corresponds to the fourth column inner div (with its images).
When the function one() is called, it makes the value of the flex property, "100%". With that, only one div column for the first inner div will be at the screen. The rest of the inner div columns will wrap below; and the four columns will form one long column.
When the function two() is called, it makes the value of the flex property, "50%". With that, two div columns will be at the screen. The rest of the inner div columns will wrap below; and the four columns will form two columns.
When the function four() is called, it makes the value of the flex property, "25%". With that, all the four div columns will be at the screen. No inner div column will wrap below; and the four columns will form four rather short columns.
Again, when each button is clicked, its columns have to be displayed and the button itself has to be made, "active". So, each button actually needs two on-click events. The first on-click event calls a function in the JavaScript in the head element. The second on-click event has to be mimicked (imitated) for each button. The JavaScript for this is in the body element, below all the div elements. That JavaScript is:
<script type="text/javascript"> // Add active class to the current button (highlight it) var header = document.getElementById("myHeader"); var btns = header.getElementsByClassName("btn"); for (var i = 0; i < btns.length; i++) { btns[i].addEventListener("click", function() { var current = document.getElementsByClassName("active"); current[0].className = current[0].className.replace(" active", ""); this.className += " active"; }); } </script>
The references of the three buttons are obtained and held in the array, btns. For each of these buttons, the second but mimicked click event is added. This is done by adding the click event-listener. The adding of the click event-listener is done with the addEventListener() method. This method takes two arguments. The first argument is the string, "click". The second argument is a callback function.
The first statement of the callback function obtains the reference of the button that is "active". The second statement removes the active class-name from the reference (" active" becomes ""). The third statement gives the "active" class-name to the button that has just been clicked (which might still be the previous button clicked). The "this" reserved word in the third statement, refers to the HTML button element that has just been clicked.
The Complete Webpage Code
And there you have it. The complete webpage code is:
<!DOCTYPE html> <html> <head> <title>Image Grid</title> <link rel='icon' href='https://www.examplee.com/images/logo.jpg' type='image/x-icon'> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Description of the Web Page."> <style> * { box-sizing: border-box; } body { margin: 0; font-family: Arial, Helvetica, sans-serif; } div.header { padding: 32px; text-align: center; } div.row { display: flex; flex-wrap: wrap; padding: 0 4px; } /* Create two equal columns that sits next to each other */ div.column { flex: 50%; padding: 0 4px; } div.column img { margin-top: 8px; } /* Style the buttons */ button.btn { border: none; padding: 10px 16px; font-size: 18px; background-color: #f1f1f1; cursor: pointer; } button.btn:hover { background-color: #ddd; } button.btn.active { background-color: #666; color: white; } </style> <script type="text/javascript"> // Get the elements with class="column" var elements = document.getElementsByClassName("column"); // Full-width images function one() { for (var i = 0; i < elements.length; i++) { elements[i].style.flex = "100%"; } } // Two images side by side function two() { for (var i = 0; i < elements.length; i++) { elements[i].style.flex = "50%"; } } // Four images side by side function four() { for (var i = 0; i < elements.length; i++) { elements[i].style.flex = "25%"; } } </script> </head> <body> <!-- Header --> <div class="header" id="myHeader"> <h1>Image Grid</h1> <p>Click on the buttons to change the grid view.</p> <button class="btn" onclick="one()">1</button> <button class="btn active" onclick="two()">2</button> <button class="btn" onclick="four()">4</button> </div> <!-- Photo Grid --> <div class="row"> <div class="column"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/wedding.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/rocks.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/falls2.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/paris.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/nature.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/mist.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/paris.jpg" style="width:100%"> </div> <div class="column"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/underwater.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/ocean.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/wedding.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/mountainskies.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/rocks.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/underwater.jpg" style="width:100%"> </div> <div class="column"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/wedding.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/rocks.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/falls2.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/paris.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/nature.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/mist.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/paris.jpg" style="width:100%"> </div> <div class="column"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/underwater.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/ocean.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/wedding.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/mountainskies.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/rocks.jpg" style="width:100%"> <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/underwater.jpg" style="width:100%"> </div> </div> <script type="text/javascript"> // Add active class to the current button (highlight it) var header = document.getElementById("myHeader"); var btns = header.getElementsByClassName("btn"); for (var i = 0; i < btns.length; i++) { btns[i].addEventListener("click", function() { var current = document.getElementsByClassName("active"); current[0].className = current[0].className.replace(" active", ""); this.className += " active"; }); } </script> </body> </html>
Copy all the code into a text editor. Save the file with any name, but with the extension, .html . Open the saved file in the browser. Click the three buttons and observed the change in each case. The images are in the broad-network.com website. So the reader has to be hooked on to the Internet.
Chrys