Ricky Kresslein

Create A Photo Portfolio Website From Scratch

2022-12-22

This guide will walk you through how I built ricky.pictures step-by-step. We will build a site you can host essentially anywhere and it will allow you to avoid paying the expensive, ever increasing fees of Squarespace.

First, a quick explanation of what we will be making. I created a portfolio that contains a mosaic grid of my photos, aligned in columns. You can click on the images to view them in a Lightbox. Resizing the browser also resizes the mosaic, eventually reducing it to two columns, then one, so it can be viewed comfortably on a phone or tablet. And that's basically it. I wanted a simple and sleek portfolio. If you want to see it in action just go to ricky.pictures.

Create a Photography Portfolio Website

Create a file named index.php. You can also name it index.html if you wish to avoid the automation we are going to use at the end to make it easy to maintain.

I will not be going over creating the header of your website or the footer in this tutorial. We will only be creating the image portfolio mosaic itself. The following instructions are adapted from this page.

In the body of the page you created, add the following HTML:

<div class="row">
  <div class="column">
    <img src="wedding.jpg">
    <img src="rocks.jpg">
    <img src="falls2.jpg">
    <img src="paris.jpg">
    <img src="nature.jpg">
    <img src="mist.jpg">
    <img src="paris.jpg">
  </div>
  <div class="column">
    <img src="underwater.jpg">
    <img src="ocean.jpg">
    <img src="wedding.jpg">
    <img src="mountainskies.jpg">
    <img src="rocks.jpg">
    <img src="underwater.jpg">
  </div>
  <div class="column">
    <img src="wedding.jpg">
    <img src="rocks.jpg">
    <img src="falls2.jpg">
    <img src="paris.jpg">
    <img src="nature.jpg">
    <img src="mist.jpg">
    <img src="paris.jpg">
  </div>
</div>

That is modified from the original to show only 3 columns instead of 4, but if you want 4 go ahead and add another. Change the img src="THIS_PART" to point to the images you want to add, and do that for every image. You don't need 6 image tags in each column, you can have as few as 1 or 2 in each column.

Now, create a style.css file if you don't already have one and paste the following code in it:

.row {
  display: flex;
  flex-wrap: wrap;
  padding: 0 4px;
  margin-bottom: 2em;
}

/* Create four equal columns that sits next to each other */
.column {
  flex: 32%;
  max-width: 33.33%;
  padding: 0 4px;
}

.column img {
  margin-top: 8px;
  vertical-align: middle;
  width: 100%;
}

/* Responsive layout - makes a two column-layout instead of four columns */
@media screen and (min-width: 600px) and (max-width: 800px) {
  .column {
    flex: 48%;
    max-width: 50%;
  }
}

/* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 600px) {
  .column {
    flex: 100%;
    max-width: 100%;
  }
}

That CSS is also modified from the original to account for 3 columns instead of 4. Also, I realized when using the code straight from the website that doing an exact percentage, such as 25% when using 4 columns, causes it to misbehave and push the last column down and leave a gap where it should be. I believe this is due to the gap between the columns. Therefore, I reduced the number to 32% instead of 33.333% in flex: 32%;. When using 4 columns, I recommend bringing it down to 24% from 25%.

Make sure you link to the style.css file in the <head> section of your page.

<link href="style.css" rel="stylesheet" />

That is basically it for the image layout. Everything should be looking good. Now we need to make the images expand into a Lightbox display when they are clicked on, and then we can automate everything to make it easier to add photos in the future.

To add our Lightbox feature, download the latest Lightbox release ZIP from their GitHub page. Extract the CSS and JS files from the /dist folder and upload them to whatever directory you want on your server (I tend to keep a /js folder and a /css folder to keep everything organized).

You will also need to take the images from the /dist/images folder and upload them to your server if you want the next and close buttons to show up in your Lightbox. Put them in the /images folder of your server to make things easy. If you put them elsewhere you will need to edit the code in the Lightbox CSS file.

Lightbox depends on JQuery, so we also need to download JQuery. I recommend getting the compressed, production version, which is smaller and faster than the uncompressed. Upload that to the same place you put the Lightbox JS file on your server.

Include the CSS at the top of your page in your <head> tag:

<link href="path/to/lightbox.css" rel="stylesheet" />

Then include the Javascript at the bottom of your page before the closing </body> tag:

<script src="path/to/jquery-3.6.0.min.js"></script>
<script src="path/to/lightbox.js"></script>

*Make sure you change "path/to/" to wherever you put the files. Also be sure your filenames are correct, as they may differ from mine.

Now we need to go back and change our original HTML so all the images link to the Lightbox display. Change your original HTML to the following:

<div class="row">
  <div class="column">
    <a href="wedding.jpg" data-lightbox="portfolio"><img src="wedding.jpg"></a>
    <a href="rocks.jpg" data-lightbox="portfolio"><img src="rocks.jpg"></a>
    <a href="falls.jpg" data-lightbox="portfolio"><img src="falls.jpg"></a>
    <a href="paris.jpg" data-lightbox="portfolio"><img src="paris.jpg"></a>
    <a href="nature.jpg" data-lightbox="portfolio"><img src="nature.jpg"></a>
    <a href="mist.jpg" data-lightbox="portfolio"><img src="mist.jpg"></a>
    <a href="underwater.jpg" data-lightbox="portfolio"><img src="underwater.jpg"></a>
  </div>
  <div class="column">
    <a href="wedding.jpg" data-lightbox="portfolio"><img src="wedding.jpg"></a>
    <a href="rocks.jpg" data-lightbox="portfolio"><img src="rocks.jpg"></a>
    <a href="falls.jpg" data-lightbox="portfolio"><img src="falls.jpg"></a>
    <a href="paris.jpg" data-lightbox="portfolio"><img src="paris.jpg"></a>
    <a href="nature.jpg" data-lightbox="portfolio"><img src="nature.jpg"></a>
    <a href="mist.jpg" data-lightbox="portfolio"><img src="mist.jpg"></a>
    <a href="underwater.jpg" data-lightbox="portfolio"><img src="underwater.jpg"></a>
  </div>
  <div class="column">
    <a href="wedding.jpg" data-lightbox="portfolio"><img src="wedding.jpg"></a>
    <a href="rocks.jpg" data-lightbox="portfolio"><img src="rocks.jpg"></a>
    <a href="falls.jpg" data-lightbox="portfolio"><img src="falls.jpg"></a>
    <a href="paris.jpg" data-lightbox="portfolio"><img src="paris.jpg"></a>
    <a href="nature.jpg" data-lightbox="portfolio"><img src="nature.jpg"></a>
    <a href="mist.jpg" data-lightbox="portfolio"><img src="mist.jpg"></a>
    <a href="underwater.jpg" data-lightbox="portfolio"><img src="underwater.jpg"></a>
  </div>
</div>

Of course, change the filenames again with your own images, both in href="" and src="".

The data-lightbox="portfolio" part of the a tag tells Lightbox to group them all together, so the viewer can just push > in the Lightbox to view the next image. If you prefer them to close the Lightbox before they can view the next image, just change portfolio in data-lightbox="" to something different for each one.

That's it! You should now have a working portfolio that displays your images in beautiful, automatically resizing columns. You should also be able to click on each image to open the Lightbox view and scroll through them.

Now for the interesting part. Automation. I didn't want to have to type out the image URL for each image every time I add new photos to my portfolio. With a little PHP I was able to modify the code so all I need to do is upload an image to the proper folder on my server and it will appear in my portfolio automatically.

To do this, we need to change the HTML we added to the index.php page. For this to work, the filename of the page must end in .php. Replace the code from above with the following:

<?php
  $photos = array();
  foreach(glob('images/wildlife/*.*') as $file) {
    array_push($photos, '<a href="' . $file . '" data-lightbox="portfolio"><img src="' . $file . '" /></a>');
  }
  shuffle($photos)
?>
<div class="row">
  <div class="column">
    <?php
      $x = 1;
      $left = count($photos);
      while($x <= ceil($left/3)) {
        echo array_pop($photos);
        $x++;
      }
    ?>
  </div>
  <div class="column">
    <?php
      $x = 1;
      $left = count($photos);
      while($x <= ($left/2)) {
        echo array_pop($photos);
        $x++;
      }
    ?>
  </div>
  <div class="column">
    <?php
      foreach($photos as $n) {
        echo array_pop($photos);
      }
    ?>
  </div>
</div>

If you don't know PHP that probably looks a bit confusing so I will break it down. The first bit of PHP creates an array called photos. I won't go into it much here, but an array is a variable that holds many chunks of information. We are using it to hold the code to display every image in a certain folder on a server.

The foreach bit creates a loop that takes the filename of every image we have in said folder and inputs it into the href and src bits of our HTML tags.

Next, shuffle($photos) shuffles the stack of HTML like a deck of cards, randomizing the order. You can delete this line if you want your photos to always be in the same order when someone visits your page.

The PHP after the first <div class="column"> tag creates a random value named X and makes its value 1. Then we create another variable named left (as in how many are left) and set it to the number of items in the photos array we created above. Then we loop through the stack of images using a while loop. Every time the loop executes, it "pops" off an image from the array, which means it prints out the last image in the stack and then removes it from the array. This while loop is set to run through a third of the photos in your images folder, i.e. the number of items in the array divided by three (rounded up).

This process repeats for the next two columns with one slight change each time. In the second column we take the number of photos left in the array and divide it by two (rounded down), then "pop" that many items off the array. In the third and final column we just print out every remaining item of the array, which should now be the final third.

The reason I round up in the first column and down in the second is so if there are an odd number of photos the second (or second and third) column will contain the lowest number. I thought it looked best when the middle column had the fewest images, rather than either of the sides. This is a personal preference, so feel free to change it.

Now, you never need to edit this code again. Every time you want to add a photo to your portfolio just upload it to the folder you chose on your server and it will automatically show up on your website.