Broad Network


How to Create a Responsive Portfolio Gallery Grid with CSS Only

Image Gallery

How To, for Front End and Web Applications

By: Chrysanthus Date Published: 29 Apr 2025

A portfolio is a set of samples of work. This tutorial explains How to Create a Responsive Portfolio Gallery Grid with CSS Only. For this project, there are five images. Four are in one horizontal row, with each with its own work description. The fifth image with its work description, is below the horizontal row of the four images. All the images are of the same size, except the fifth. And that is for the wide screen.

The webpage is responsive, in the sense that, when its width is less than or equal to 600px, the four images are in one column. The fifth image is under the fourth, in the one column. As the width of the webpage increases beyond 600px, the four images are in two columns (4 images in two rows). The fifth is under the two rows, taking all the content width. As the width increases beyond 900px, the four images are in four columns (four images in one row). The fifth is under the one row, again taking all the content width. Each image moves with its work description.

Explaining Responsiveness from Wide Screen down to Narrow Screen: When the webpage is at a wide screen, the four images are in one row, which means four columns. The fifth image is under the one row, and occupies all the content width. As the width of the screen is reducing, all the five images are becoming smaller and smaller. As soon as the width goes below 900px, the four images are in two columns, with larger sizes (but not as large as for the very wide screen). The fifth image is still under the one row, and occupies all the new smaller content width. As the width of the screen decreases further, the size of the images are decreasing, and still in two columns. As soon as the width goes below 600px, the four images are in one column, with larger sizes (almost as with the wide screen). The fifth image is still under the one row, and occupies all the new smallest content width (which in this case, is the same as the other four widths). Do not forget that each image moves with its work description.

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. Reduce the width of the webpage continuously, until the one row becomes two columns. Continue to reduce it until the two columns become one column. 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>Portfolio Gallery</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>

    </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 be left empty. The images and their work descriptions are in div elements, which are in the body element.

The HTML body Element Content

The content of the body element is:

        <!-- MAIN (Center website) -->
        <div class="main">

            <h1>myLogo.com</h1>
            <hr>

            <h2>Portfolio</h2>
            <p>Resize the browser window to see the responsive effect.</p>

            <!-- Portfolio Gallery Grid -->
            <div class="row">
                <div class="cell">
                    <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/mountains.jpg" alt="Mountains" style="width:100%">
                    <h3>My Work 1</h3>
                    <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                </div>
                <div class="cell">
                    <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/lights.jpg" alt="Lights" style="width:100%">
                    <h3>My Work 2</h3>
                    <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                </div>
                <div class="cell">
                    <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/nature.jpg" alt="Nature" style="width:100%">
                    <h3>My Work 3</h3>
                    <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                </div>
                <div class="cell">
                    <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/img_forest.jpg" alt="Forest" style="width:100%">
                    <h3>My Work 4</h3>
                    <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                </div>
                <!-- End Grid -->
            </div>

            <div class="content">
                <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/p3.jpg" alt="Bear" style="width:100%">
                <h3>Some Other Work</h3>
                <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
            </div>

            <!-- END MAIN -->
        </div>

All the content (five images with their work descriptions) is in one div, with class-name, "main". For the four row images, there is a div with class-name, "row". This div has four inner divs, each of the class-name, "cell". Each cell div has three elements: first, the image tag with the URL of the image; next, an H3 element with the title of the work; and then, a paragraph element with the description of the work. The image tag is an inline element. The H3 element is a block-level element. The paragraph element is a block-level element. So all three elements are in a vertical column within its container div.cell.

After the row.div in the code, is the div for the fifth image. This div has no inner div. This div is for an extra work or optional work. Its class-name is "content". It has the same contents like the cell divs, with the exception that there are two paragraphs, instead of one.

Each image tag has the style attribute, "style='width:100%' " . The 100% is in relation to the containing div: cell div or content div.

The HTML Style Element Content

Apart from the attribute, "style='width:100%' ", 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 {
                background-color: #f1f1f1;
                padding: 20px;
                font-family: Arial;
            }

The background color of the whole webpage is #f1f1f1 (light gray). The padding (gap between content and border) for the four sides is 20px. The font to be used by all the elements in the body, including the body itself, is Arial.

Styling the Overall Container

If the reader had tested the complete code at a wide screen, he/she would have noticed that the document is centered horizontally. That is, there is quite a gap from the left edge of the page to the left edge of the document; and the same gap exists from the right edge of the document, to the right edge of the page. The CSS rule for the overall container div is:

            div.main {
                max-width: 1000px;
                margin: auto;
            }

The maximum width is 1000px, not enough to cover the width of a wide screen. "margin: auto;" means that the browser chooses the size of the four margins.

Styling the H1 Element

The CSS rule for the H1 element is:

            h1 {
                font-size: 50px;
                word-break: break-all;
            }

The font size is 50px. With "word-break: break-all;", any word that is longer than the width of the H1 element, is broken at the right end and wrapped to the next line.

Styling row div

The row div has the four inner divs for the images. Its CSS rule is:

            div.row {
                margin: 8px -8px;
            }

The top and bottom margin is 8px and the left and right margin is -8px (minus eight pixels). If the 8px is absent, then there will be no separation between the row div and the content div below it, with the body background color. The -8px actually takes the row div margin outwards, and also takes the row div content outwards. Remember that the box-sizing property is applicable here (the whole webpage). In this way, the left and right edges of the row div content align approximately well with the left and right edges of the content div content below; also the left and right edges of the row div margins align approximately well with the left and right edges of the content div margins below.

Row and Cell Padding

The cell divs in the row are indirectly separated horizontally with padding, instead of margin (or space) in order to avoid the background color for separation. The row div is also given a padding value. The CSS rule for those is:

            div.row, div.row > div.cell {
                padding: 8px;
            }

The padding values for cell divs and row div have been chosen such that there is alignment of the vertical edges of the row div and content div below.

Styling the cell divs

The CSS rule for the cell divs in the row is:

            div.cell {
                float: left;
                width: 25%;
                background-color: white;
            }

They are all floated left, to form a row at the wide screen. This floating effect has to be stopped, otherwise, there will be serious issues at the display (browser). Since there are four divs, each with its own inner div and image, the width of each div is 25% of the width of the row div (100% divided by 4 equals 25%). The background color is white.

Stopping the Floating Effect of the cell divs

In order to stop the floating effect, one feature is needed: A somewhat fifth row div (just after the fourth) is needed. This is a pseudo element with the name, "after". The pseudo element is of a CSS rule (within the start and end tags of the HTML style element); it is:

            div.row::after {
                content: "";
                display: table;
                clear: both;
            }

Note how the selector has been expressed, which includes the class-name, "row". "content: ''; " as CSS property in the pseudo element, gives the pseudo element, no content. "display: table;" as CSS property in the pseudo element, turns the pseudo element, into an empty table. A table by default, is a block-level element, meaning that it will be displayed on the next line, below the mimicked row. "clear: both;" as CSS property in the pseudo element stops both left and right floating of the pseudo element.

Styling the content div

The content div is a one cell (column) div under the row div. It is for the optional or extra work. Its CSS rule is:

            div.content {
                background-color: white;
                padding: 10px;
            }

Its background color is white, and there is a padding of 10px for the four sides.

Responsiveness

The webpage is responsive, in the sense that, when its width is less than 600px, the four images are in one column. The fifth is right under, all forming one column. As the width of the webpage increases beyond 600px, the four images are in two columns (4 images in two rows). The fifth is right under, but occupying the total width of their parent div. As the width increases beyond 900px, the four images are in four columns (four images in one row). The fifth is still right under, but occupying the total width of their parent div.

Explaining Responsiveness from Wide Screen down to Narrow Screen: When the webpage is at a wide screen, the four images are in one row, which means four columns. The fifth image is under the one row, and occupies all the content width. As the width of the screen is reducing, all the five images are becoming smaller and smaller. As soon as the width goes below 900px, the four images are in two columns, with larger sizes (but not as large as for the very wide screen). The fifth image is still under the one row, and occupies all the new smaller content width. As the width of the screen decreases further, the size of the images are decreasing, and still in two columns. As soon as the width goes below 600px, the four images are in one column, with larger sizes (almost as with the wide screen). The fifth image is still under the one row, and occupies all the new smallest content width (which in this case, is the same as the other four widths). Do not forget that each image moves with its work description.

There are two media screen queries for this. They are:

            @media screen and (max-width: 900px) {
                    div.cell {
                    width: 50%;
                }
            }

            @media screen and (max-width: 600px) {
                    div.cell {
                    width: 100%;
                }
            }

Each of the queries is applied to the cell divs. The first query has to be typed before the second query. For the first query, the width of the cell div is 50% (half) of the parent div, leading to two columns. For the second query, the width is 100% of the parent div, leading to a single column. Read through the code again.

The Complete Webpage Code

And there you have it. The complete webpage code is:

    <!DOCTYPE html>
    <html>
    <head>
        <title>Portfolio Gallery</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 {
                background-color: #f1f1f1;
                padding: 20px;
                font-family: Arial;
            }

            /* Center website */
            div.main {
                max-width: 1000px;
                margin: auto;
            }

            h1 {
                font-size: 50px;
                word-break: break-all;
            }
            
            div.row {
                margin: 8px -8px;
            }

            /* Add padding BETWEEN each cell */
            div.row, div.row > div.cell {
                padding: 8px;
            }

            /* Create four equal cells that floats next to each other */
            div.cell {
                float: left;
                width: 25%;
                background-color: white;
            }

            /* Clear floats after rows */ 
            div.row::after {
                content: "";
                display: table;
                clear: both;
            }

            /* Content */
            div.content {
                background-color: white;
                padding: 10px;
            }

            /* Responsive layout - makes a two cell-layout instead of four cells */
            @media screen and (max-width: 900px) {
                    div.cell {
                    width: 50%;
                }
            }

            /* Responsive layout - makes the two cells stack on top of each other instead of next to each other */
            @media screen and (max-width: 600px) {
                    div.cell {
                    width: 100%;
                }
            }
        </style>
  
        <script type="text/javascript">
        </script>
    </head>
    <body>
        <!-- MAIN (Center website) -->
        <div class="main">

            <h1>myLogo.com</h1>
            <hr>

            <h2>Portfolio</h2>
            <p>Resize the browser window to see the responsive effect.</p>

            <!-- Portfolio Gallery Grid -->
            <div class="row">
                <div class="cell">
                    <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/mountains.jpg" alt="Mountains" style="width:100%">
                    <h3>My Work 1</h3>
                    <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                </div>
                <div class="cell">
                    <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/lights.jpg" alt="Lights" style="width:100%">
                    <h3>My Work 2</h3>
                    <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                </div>
                <div class="cell">
                    <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/nature.jpg" alt="Nature" style="width:100%">
                    <h3>My Work 3</h3>
                    <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                </div>
                <div class="cell">
                    <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/img_forest.jpg" alt="Forest" style="width:100%">
                    <h3>My Work 4</h3>
                    <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                </div>
                <!-- End Grid -->
            </div>

            <div class="content">
                <img src="https://www.broad-network.com/Internet/articles/_general/dir0/images/p3.jpg" alt="Bear" style="width:100%">
                <h3>Some Other Work</h3>
                <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
                <p>Lorem ipsum dolor sit amet, tempor prodesset eos no. Temporibus necessitatibus sea ei, at tantas oporteat nam. Lorem ipsum dolor sit amet, tempor prodesset eos no.</p>
            </div>

            <!-- END MAIN -->
        </div>
    </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. Reduce the width of the webpage continuously, until the one row becomes two columns. Continue to reduce it until the two columns become one column. The images are in the broad-network.com website. So the reader has to be hooked on to the Internet.

Chrys





Related Links

More Related Links

Cousins

BACK NEXT

Comments