portfolio

Create a Simple Image Grid Portfolio Site

Display your work by coding an online portfolio site from scratch

There are many different ways to share your work online. If you are a web designer with front-end web development skills looking to showcase your talent, one of the best ways is to custom design and code your own portfolio site from scratch.

See a Demo
https://laulima.hawaii.edu/access/content/group/21336a81-b8f0-4b8c-8059-ba1b1b192128/public/tests/portfolios/customportfolio1/

View on Github
https://github.com/kccnma/teachingmaterials/tree/master/customportfolio1

View on Codepen
https://codepen.io/kccnma/pen/bLKKqV

Download Starter Files
https://laulima.hawaii.edu/access/content/group/21336a81-b8f0-4b8c-8059-ba1b1b192128/public/data/img.zip

Let’s Code!

Get started by launching your favorite code editor (IDE)

Create a new HTML folder named “customportfolio”

Inside of your new directory, create a new index.html file and then download the provided portfolio images for this exercise.  Next, create another new folder named “css” and inside of it create a new file named style.css. These two files (index.html and style.css) are the initial files that we will be editing. Once you are all setup, your local folder setup should look something like this:
Code, Save, Refresh, Repeat!

Image Grid Version (2019)

Start with Markup (HTML), then add Styling (CSS), then Repeat.

Ideally, you should code line-by-line and write every line of html and css from the source code below by hand. To speed up the process (for those with neither the time or patience), please feel free to copy-and-paste large blocks of code, one-at-a-time, in order. After each iteration (code block), be sure to hit save then preview your changes in the browser (refresh) before moving on the the next code block.

HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My Portfolio</title>
<meta name="description" content="A minimal, simple portfolio site." />
<!-- VIEWPORT FOR MOBILE -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- MAIN CSS FILE -->
<link href="css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
</body>
</html>

…and also start with an empty style.css file with the following table of contents.

CSS
/* #CSS
---------------------------------
#GLOBAL RESET
#BODY
#TYPOGRAPHY
#HELPERS
#IMAGES
#BUTTONS
#SITE STRUCTURE
#HEADER
#SITE-BRANDING (LOGO)
#SITE NAVIGATION
#FOOTER
#SECTIONS
#HERO
#LAYOUT
#GRIDS
#EFFECTS (FADE-INS)
--------------------------------- */
view raw cp1-toc.css hosted with ❤ by GitHub

Then add the following body contents:

  • header
    • navigation
  • main
    • one section with a bunch of images
  • footer
    • navigation
HTML
<header class="site-header">
<div class="site-identity">
<h1>
<a href="index.html">John Doe</a>
</h1>
</div>
<nav class="site-navigation">
<ul>
<li class="selected">
<a href="index.html#work" class="selected">Work</a>
</li>
<li>
<a href="about.html">About</a>
</li>
<li>
<a href="contact.html">Contact</a>
</li>
</ul>
</nav>
</header>
<main class="site-main">
<section id="work" class="text-centered">
<ul class="thumbgrid">
<li><a href="#"><img src="img/placeholder-1x1-art1.jpg" alt="Placeholder" /></a></li>
<li><a href="#"><img src="img/placeholder-1x1-book1.jpg" alt="Placeholder" /></a></li>
<li><a href="#"><img src="img/placeholder-1x1-ipad.jpg" alt="Placeholder" /></a></li>
<li><a href="#"><img src="img/placeholder-1x1-iphone.jpg" alt="Placeholder" /></a></li>
<li><a href="#"><img src="img/placeholder-1x1-logo1.jpg" alt="Placeholder" /></a></li>
<li><a href="#"><img src="img/placeholder-1x1-poster1.jpg" alt="Placeholder" /></a></li>
<li><a href="#"><img src="img/placeholder-1x1-packaging-set.jpg" alt="Placeholder" /></a></li>
<li><a href="#"><img src="img/placeholder-1x1-stationaryset1.jpg" alt="Placeholder" /></a></li>
</ul>
</section>
</main>
<footer class="site-footer">
<nav class="site-navigation">
<ul>
<li>
<a href="index.html">Home</a>
</li>
<li>
<a href="index.html#work">Work</a>
</li>
<li>
<a href="about.html">About</a>
</li>
<li>
<a href="contact.html">Contact</a>
</li>
</ul>
</nav>
</footer>

Add in your HTML5 css (for IE8 and below) along with the least amount of main body and typography styling.

Notice how there is no css reset, nor a comprehensive typography setup. This minimal approach to custom (bespoke) development keeps your code lean by embracing browser defaults.

CSS
/* GLOBAL RESET */
* { box-sizing: border-box; }
/* #TYPOGRAPHY */
body {
font-family: Helvetica, Arial, sans-serif;
color: rgba(0,0,0,.7);
max-width: 1000px;
margin: 0 auto;
padding: 1em;
font-size: 87.5%;
line-height: 1.5em;
}
h1 {
font-size: 3em;
}
/* #LINKS */
a {
color: rgba(0,0,0,.4);
text-decoration: none;
}
a:hover {
color: rgba(0,0,0,.6);
}
/* HELPERS */
.text-centered {
text-align: center;
}
/* #IMAGES */
img {
max-width: 100%;
height: auto;
}

Next add your structural css for your site header, nav, and footer.

CSS
/* SITE-STRUCTURE */
.site-header,
.site-footer {
text-align: center;
padding: 3em 0 2em 0;
text-transform: uppercase;
letter-spacing: 0.15em;
}
.site-identity h1 {
font-size: 2em;
margin: 0;
font-weight: normal;
}
.site-navigation ul {
margin: 0;
padding: 2em 0;
}
.site-navigation li {
margin: 0 .5em;
padding: 0;
display: inline-block;
}
.site-navigation a {
display: block;
padding: 1em .5em;
color: rgba(0,0,0,.4);
}
.site-navigation a:hover,
.site-navigation a.selected {
color: rgba(0,0,0,.6);
border-bottom: 0.05em solid rgba(0,0,0,.2);
}
section {
padding: 0 0 3em 0;
}

Next, lets code a simple image grid from scratch, only instead of reverting to your safe go-to methods (e.g. inline-blocks or floated elements), you should try to be a little more flexible and use flex-box!

CSS
/* #LAYOUT: THUMB IMAGE GRID */
.thumbgrid {
padding: 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.thumbgrid li {
list-style: none;
width: 49.5%;
padding-bottom: 0.4%;
}
@media (min-width: 768px) {
.thumbgrid li {
width: 24.5%;
}
}
.thumbgrid a img {
filter: brightness(1.05);
transition: all ease-in-out 0.2s;
border: 1px solid rgba(255,255,255,0);
}
.thumbgrid a:hover img {
filter: brightness(1);
border: 1px solid rgba(0,0,0,.3);
}

Once the home page is stable, let’s create the two main sub pages:

  • about.html
  • contact.html

The header and footer are the same (except for the “selected” state (class) on the nav, so simply do a save-as from your index.html, update your title tag, move your selected state to the correct nav item, and lastly, add the body content alone.

HTML
<section class="text-centered">
<img src="img/johndoenma-avatar.png" alt="placeholder" class="circular" />
<h1>John Doe</h1>
<p>Consectetur adipiscing elit. Donec placerat, augue id tincidunt malesuada, nisl ipsum congue tortor,
eleifend cursus massa lectus ut odio. Vestibulum tortor orci, bibendum elementum commodo eu,
ultricies a lorem. Nunc congue leo sit amet ante euismod luctus quis et massa. Nulla posuere
scelerisque ullamcorper. Suspendisse iaculis ornare nibh sed tincidunt.</p>
<a class="button" href="contact.html">Contact Me</a>
</section>
<section class="text-centered">
<div id="wufoo-z1th6dkg1ip4896" class="mywufooform"></div>
<script type="text/javascript">var z1th6dkg1ip4896; (function (d, t) {
var s = d.createElement(t), options = {
'userName': 'johndoenma',
'formHash': 'z1th6dkg1ip4896',
'autoResize': true,
'height': '497',
'async': true,
'host': 'wufoo.com',
'header': 'show',
'ssl': true
};
s.src = ('https:' == d.location.protocol ? 'https://' : 'http://') + 'www.wufoo.com/scripts/embed/form.js';
s.onload = s.onreadystatechange = function () {
var rs = this.readyState; if (rs) if (rs != 'complete') if (rs != 'loaded') return;
try { z1th6dkg1ip4896 = new WufooForm(); z1th6dkg1ip4896.initialize(options); z1th6dkg1ip4896.display(); } catch (e) { }
};
var scr = d.getElementsByTagName(t)[0], par = scr.parentNode; par.insertBefore(s, scr);
})(document, 'script');</script>
</section>

Once the primary sub pages are set up and working OK, let’s create one portfolio entry sub page using the “web site” project as our working example content.

HTML
<section class="hero full-width">
<img src="img/placeholder-4x1-hero-web.jpg" alt="placeholder" class="scale-with-grid" />
</section>
<section>
<h1>Web Site</h1>
<h3 class="subheader">Short Description of the Project</h3>
<div class="row">
<div class="two-thirds column">
<p>Introduction and short summary of this project. This is a sample portfolio entry project page. This
can be as simple as a bunch of images stacked or as complex as a detailed case study.</p>
</div>
<div class="one-third column">
<p>
<strong>Client:</strong> Lorem Ipsum
<br />
<strong>Service:</strong> Web Design
<br />
<strong>Skills:</strong> UX, UI
</p>
</div>
</div>
</section>
<section>
<img src="img/placeholder-1x1-laptop.jpg" alt="placeholder" class="scale-with-grid" />
<img src="img/placeholder-1x1-cinema.jpg" alt="placeholder" class="scale-with-grid" />
<img src="img/placeholder-1x1-browser.jpg" alt="placeholder" class="scale-with-grid" />
<img src="img/placeholder-1x1-ipad.jpg" alt="placeholder" class="scale-with-grid" />
<img src="img/placeholder-1x1-iphone.jpg" alt="placeholder" class="scale-with-grid" />
</section>

For the sub pages, we’re going to need some css help for the hero section (to break out of our fixed-width and go full-width) and for our internal content layout, which we’ll use a traditional layout grid, only this time, let’s use flexbox!

CSS
/* FULL-WIDTH HELPER */
.full-width {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
.full-width img {
width: 100%;
}
/* HERO SECTIONS */
.hero {
padding: 4em 0;
background: #dedede;
margin-bottom: 6em;
}
/* #LAYOUT: FLEX GRID */
@media (min-width: 768px) {
.row {
display: flex;
justify-content: space-between;
margin-bottom: 1em;
}
.one-third.column {
width: 32%;
}
.two-thirds.column {
width: 60%;
}
}

Let’s Spice it Up!

Finally, lets add some simple (fake) page transitions that with a “fade-in” and “move-in” effect via css3 animation.

CSS
/* Page Fade-ins */
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
main,
fade-in {
opacity: 0;
animation: fade-in ease-in-out 1;
animation-fill-mode: forwards;
animation-duration: 0.5s;
}
@keyframes fade-and-move-in {
from {
transform: translate(0, -20px);
opacity: 0;
}
to {
transform: translate(0, 0);
opacity: 1;
}
}
.fade-and-move-in * {
opacity: 0;
animation: fade-and-move-in ease-out 1;
animation-fill-mode: forwards;
animation-duration: 0.5s;
}
.fade-and-move-in *:nth-child(1) {
animation-delay: 0.1s;
}
.fade-and-move-in *:nth-child(2) {
animation-delay: 0.2s;
}
.fade-and-move-in *:nth-child(3) {
animation-delay: 0.4s;
}
.fade-and-move-in *:nth-child(4) {
animation-delay: 0.7s;
}
.fade-and-move-in *:nth-child(5) {
animation-delay: 1s;
}
.fade-and-move-in *:nth-child(6) {
animation-delay: 1.2s;
}
.fade-and-move-in *:nth-child(7) {
animation-delay: 1.4s;
}
.fade-and-move-in *:nth-child(8) {
animation-delay: 1.6s;
}
.fade-and-move-in *:nth-child(9) {
animation-delay: 1.8s;
}

When you are done, the home page should look like this:

See the Pen Custom Portfolio Test #0.1 by kccnma (@kccnma) on CodePen.0

For the completed version with sub pages and additional css (e.g. circular image helper), see the demo and source code via the links below:

See a Demo
https://laulima.hawaii.edu/access/content/group/21336a81-b8f0-4b8c-8059-ba1b1b192128/public/tests/portfolios/customportfolio1/

View on Github Button
https://github.com/kccnma/teachingmaterials/tree/master/customportfolio1

View on Codepen
https://codepen.io/kccnma/pen/bLKKqV

Download Starter Files
https://laulima.hawaii.edu/access/content/group/21336a81-b8f0-4b8c-8059-ba1b1b192128/public/tests/portfolios/img.zip

Next Steps: Continue adding more pages with real content

After the home page is secure, along with at least one project/portfolio entry sub page, you can move on to add all pages with real content. As you add all sub pages and content, be sure to test on multiple devices and screen sizes and try designing-as-you-code. You might find it helpful (and easier at times) to design in the browser instead of in your usual design application.

Have fun!


Summary

Coding your online portfolio is never an easy task. There are so many ways to present your work, so which way is best? Unfortunately, there is no right or wrong answer—only you can make this decision. The good news is that you can use your online portfolio as a great excuse to practice writing custom hand-written code from scratch because the best way to become a stronger web designer and front-end web developer is to create web sites.  The more custom coded sites you make, the easier it will get as you develop your own best practices for writing code and solving code-related UX and UI problems.

Related Resources and Reading

Go Further

Author Notes

This was written specifically to help aspiring web designers as they aim to:

  • Synthesize the concepts and skills garnered as a designer and front-end web developer by showcasing a culmination of projects in a custom designed and coded bespoke interface that integrates conceptual thinking and aesthetic application.

1 thought on “Create a Simple Image Grid Portfolio Site”

  1. Pingback: 299: Custom Portfolio – APURIE

Comments are closed.