Learn React by Practice and Create Stunning Image Gallery

One of the best ways to learn React is by practice. Nothing can help you learn like trial and error. When you get your hands dirty your brain is like sponge. Your ability to absorb new knowledge is incredible. In addition, learning by practice is also more fun. For this reason, I decided to write this short tutorial on React. I hope it will help you learn React and improve your skills. As always, I included links to demo on CodePen and repository n GitHub.

Table of Contents:

Quick introduction

Putting together the resources

HTML and laying out the foundation

Sass and some variables to start with

Covering the basics

Styling the gallery container

Taking care about gallery cards

Styling card icons

Finishing with overlay

JavaScript and getting our hands dirty

Creating necessary components

Live demo on CodePen

Source code on GitHub

Quick introduction

It’s been a while since we practiced coding on some tutorial. In a fact, the last tutorial appeared on this blog on September 30. Also, it is a coincidence that the last tutorial was about React. Today, I’m going to help you learn React and practice your skills even more. In this tutorial, we will create stunning image gallery. In addition, this gallery will also contain modal dialog for previewing bigger version of images. This gallery will require a number of resources. Enjoy this tutorial.

Putting together the resources

The first thing we have to do to build the gallery and learn React is to gather necessary resources. Let’s start with external CSS stylesheets. In this tutorial we are are going to use three CSS stylesheets. These are normalize, bootstrap 3 and font awesome. The goal of normalize stylesheet is to stick to CSS best practices. In short, different browsers render various elements in a different way. We want to reduce these browser inconsistencies. As a result, we will create consistent cross-browser experience.

Stylesheet from Bootstrap framework will provide this tutorial with grid system. We will use it to distribute the images in our gallery. Although, we could write some simple grid system. However, that would cost us some time we can use more wisely. What is the reason for implementing the last stylesheet Font awesome? Well, I want to use two icons in this tutorial. We will use the first icon as a label for opening the modal window. This will be “expand” icon. Then, we will use “times” icon as a label to close the modal. This is all for CSS.

What about JavaScript? We will need two libraries to make this tutorial on how to learn React by practice work. These two libraries are React and ReactDOM. That’s all. We will not use jQuery or any other library. One thing about JavaScript. I’m going to use ES6 syntax. Therefore, it is high likely that you will need some compiler to convert the code into older syntax of JavaScript. Otherwise, it will probably not work in older browser. In this tutorial, I used babel.

Quick note: Bootstrap framework already contains normalize stylesheet. However, it contains much older version. This is why I used external version as well. I don’t want to wait until Bootstrap implement newest version. Also, it I think that it will do no harm if we use two normalize stylesheets. In the worst case, we can always remove the secondary stylesheet and use the one in Bootstrap. In other words, we have nothing to worry about.

HTML and laying out the foundation

Okay, we have all necessary resources. That was the first step on our journey to learn react by practice. The second step is creating HTML document and adding the structure for this tutorial. Since the majority of code will be in JavaScript (React), this step will be very fast. First, we have to add the three CSS stylesheets mentioned above into head section of the document. Then, we have to add two React libraries into body section. Also, we will create a container for our gallery.

This container will be a section element with class “gallery-container”. Why do we need this container? React needs some place where it will render its components. This section will be this place. This is everything we will need in the terms of HTML.

HTML:

<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>How to Learn React and Create Stunning Image Gallery</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

<!-- Normalize stylesheet -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">

<!-- Bootstrap 3 -->
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css'>

<!-- Font Libre Franklin -->
<link rel='stylesheet prefetch' href='https://fonts.googleapis.com/css?family=Libre+Franklin:300,400,700'>

<!-- Main stylesheet-->
<link rel="stylesheet" href="css/style.css">
</head>

<body>
<section class="gallery-container"></section>

<!-- Scripts -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js'></script>

<script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js'></script>

<script src="js/index.js"></script>
</body>
</html>

Sass and some variables to start with

Let’s proceed to the third step on our journey to learn react by practice. We want the gallery not only to work. We also want to make it look great. Therefore, we are going to create some styles. In order to make the styling easier, we are going to create a number of re-usable variables. The first variable will be for black color (#111). The second one will be for border-radius (4px). The last variable will be for transition (all .25s ease-in-out).

Sass:

// Variables
$black: #111;
$radius: 4px;
$transition: all .25s ease-in-out;

Covering the basics

The next step is to make some style correction for html and body elements. The goals of this learn React by practice tutorial is creating image gallery. Since will will use modal with overlay, we should make sure we will have enough real estate. In other words, let’s make the gallery full-height. This will require set height and min-height properties of html and body to “100%”. We will also change the settings for typography. In other words, we will set “16px” as font-size for html. Next, we will set “100%” as font-size for body. This will change the default setting of Bootstrap.

Sass:

html,
body {
min-height: 100%;
height: 100%;
}

html {
font-size: 16px;
}

body {
position: relative;
font-size: 100%;
}

Styling the gallery container

You probably noticed that we also set position of the body element to “relative”. This will be handy later to position overlay for modal. Now, we will deal with styles for the main part of this learn React by practice tutorial. We will add some spacing between the content of the gallery and container. We can do this by adding some padding-top, say .9375rem.

Sass:

.gallery-container {
padding-top: .9375rem;
}

Taking care about gallery cards

Next, we will take care about gallery cards. We will set position of all cards to “relative” value. Do you remember the icon for opening modal window? Well, this icon will be positioned absolutely. Therefore, we need some container set positioned relatively first. Otherwise, the icon would be positioned relative to the browser window. This something we want to avoid. Then, we will set overflow to “hidden”. This is probably not necessary. It is just to be sure. Lastly, we will add margin-bottom. This will create some space between cards.

Sass:

.gallery-card {
position: relative;
overflow: hidden;
margin-bottom: 1.875rem;
}

The styles for gallery (card) thumbnails will be very easy. We will need to set max-width to “100%”. This will help us prevent images overlapping the cards. Also, to keep the ratio of images intact, we will set height to auto. Lastly, let’s make the corners slightly rounded by setting border-radius to our $radius variable.

Sass:

.gallery-thumbnail {
max-width: 100%;
height: auto;
border-radius: $radius;
}

Styling card icons

Next thing on the line in this learn React by practice tutorial is card icon. This icon will allow users to open modal dialog. As I mentioned we will use “expand” icon from Font Awesome. I decided to position the icon right in the middle of the thumbnail. You can either follow me steps or place it anywhere you want. To do that, we will use combo of position, top, left, and transform properties. Then, we will increase its font-size, set its color to white (#fff) and change cursor to pointer.

Also, let’s set display to “block” and opacity to “0”. As a result, the icon will be initially hidden. When user hovers over the card, the icon will show itself. We will do this by changing opacity to “1”. In order to make this change smoother, we will use transition and $transition variable. Also, when user hovers over the icon it will change its color to black.

Sass:

.card-icon-open {
display: block;
position: absolute;
top: 50%;
left: 50%;
font-size: 2rem;
color: #fff;
cursor: pointer;
opacity: 0;
transform: translate(-50%, -50%);
transition: $transition;

&:focus,
&:hover {
color: $black;
}
}

.gallery-thumbnail:focus ~ .card-icon-open,
.gallery-thumbnail:hover ~ .card-icon-open,
.gallery-thumbnail ~ .card-icon-open:focus,
.gallery-thumbnail ~ .card-icon-open:hover {
opacity: 1;
}

Finishing with overlay

It is time for the last piece of the Sass part of this learn React by practice tutorial. This means styling the modal overlay and modal dialog. First, we will set the position of overlay to “absolute”. Then, we will set top and left properties to “0” to make sure the overlay will start in top-left corner. Setting width and height to “100%” will help us cover the whole screen. Z-index set to “10” will move overlay into forefront. Lastly, let’s set the background to semi-transparent light black.

Sass:

.modal-overlay {
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
background: rgba(21,21,21,.75);
}

In case of modal-body, we will use the same combo we used to position the “expand” icon. In other words, we will set position to “absolute”, top and left to “50%” and transform to “translate(-50%, -50%)”. Z-index of modal-body will be just a bit higher than z-index of overlay. Otherwise, the overlay would cover it as well. Again, just to make sure, set overflow to “hidden”. Since Bootstrap has predefined padding, we will have to reset it by setting it to “0”. To make the corners of modal-body slightly round, let’s set the border-radius to $radius.

Sass:

.modal-body {
position: absolute;
top: 50%;
left: 50%;
z-index: 11;
padding: 0;
overflow: auto;
border-radius: $radius;
transform: translate(-50%, -50%);
}

It is time to style the closing modal dialog icon. This is the last sass-related thing in this learn React by practice tutorial. Set its position to “absolute”, top to “0” and right to “8px”. Next, set font-size to “1.5rem” to make it easier to click. Then, set color to $black and on hover to “#fff”. Let’s also use transition to make this change smoother.

Sass:

.modal-close {
position: absolute;
top: 0;
right: 8px;
font-size: 1.5rem;
color: $black;
transition: $transition;

&:focus,
&:hover {
color: #fff;
}
}

The whole Sass:

$black: #111;
$radius: 4px;
$transition: all .25s ease-in-out;

html,
body {
min-height: 100%;
height: 100%;
}

html {
font-size: 16px;
}

body {
position: relative;
font-size: 100%;
}

.gallery-container {
padding-top: .9375rem;
}

.gallery-card {
position: relative;
overflow: hidden;
margin-bottom: 1.875rem;
}

.gallery-thumbnail {
max-width: 100%;
height: auto;
border-radius: $radius;
}

.card-icon-open {
display: block;
position: absolute;
top: 50%;
left: 50%;
font-size: 2rem;
color: #fff;
cursor: pointer;
opacity: 0;
transform: translate(-50%, -50%);
transition: $transition;

&:focus,
&:hover {
color: $black;
}
}

.gallery-thumbnail:focus ~ .card-icon-open,
.gallery-thumbnail:hover ~ .card-icon-open,
.gallery-thumbnail ~ .card-icon-open:focus,
.gallery-thumbnail ~ .card-icon-open:hover {
opacity: 1;
}

.modal-overlay {
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
background: rgba(21,21,21,.75);
}

.modal-body {
position: absolute;
top: 50%;
left: 50%;
z-index: 11;
padding: 0;
overflow: auto;
border-radius: $radius;
transform: translate(-50%, -50%);
}

.modal-close {
position: absolute;
top: 0;
right: 8px;
font-size: 1.5rem;
color: $black;
transition: $transition;

&:focus,
&:hover {
color: #fff;
}
}

JavaScript and getting our hands dirty

HTML and Sass are behind us. Now, we have to tackle the main part of this learn React by practice tutorial. The first two steps will be saving the gallery container inside variable. Since this container is unlikely to change, we can use const keyword. Next, create array for URLs for our images. You may want to change some of these URLs in the future. Therefore, we will rather use let keyword.

JavaScript:

// Cache gallery container
const galleryContainer = document.querySelector('.react-gallery');

// Create new array with URLs for images
let imgUrls = [
'https://source.unsplash.com/3Z70SDuYs5g/800x600',
'https://source.unsplash.com/01vFmYAOqQ0/800x600',
'https://source.unsplash.com/2Bjq3A7rGn4/800x600',
'https://source.unsplash.com/t20pc32VbrU/800x600',
'https://source.unsplash.com/pHANr-CpbYM/800x600',
'https://source.unsplash.com/3PmwYw2uErY/800x600',
'https://source.unsplash.com/uOi3lg8fGl4/800x600',
'https://source.unsplash.com/CwkiN6_qpDI/800x600',
'https://source.unsplash.com/9O1oQ9SzQZQ/800x600',
'https://source.unsplash.com/E4944K_4SvI/800x600',
'https://source.unsplash.com/-hI5dX2ObAs/800x600',
'https://source.unsplash.com/vZlTg_McCDo/800x600'
];

Creating necessary components

Our next step in this learn React by practice tutorial is to create React components. We will use three components: GalleryImage, GalleryModal and Gallery. GalleryImage component generate img elements and it is the easiest. This component will have className, src and alt attributes. All these attributes will be set to the same props.

JavaScript:

// Component for gallery image
class GalleryImage extends React.Component {
render() {
return(
<img className={this.props.className} src={this.props.src} alt={this.props.alt} />
)
}
}

The second component is GalleryModal. This component will contain two div elements, anchor tag and img. The first div will be for modal-overlay, while the second on will be for modal-body. Anchor tag will use “times” icon from font Awesome and allow user to close the overlay. Lastly, the image is for preview. In addition, we will use if statement to check whether the modal should be visible or not. If not, we will return null. This will block React from rendering the component.

JavaScript:

// Component for gallery modal
class GalleryModal extends React.Component {
render() {
if (this.props.isOpen === false) {
return null;
}

return(
<div isOpen={this.props.isOpen} className='modal-overlay' onClick={this.props.onClick} name={this.props.name}>
<div className='modal-body'>
<a className='modal-close' href='#' onClick={this.props.onClick}><span className='fa fa-times'></span></a>

<img src={this.props.src} />
</div>
</div>
)
}
}

The third and last component of this learn React by practice tutorial is Gallery. It is also the most complex. This component will contain constructor() and super(). If you are not sure about how these methods work, take a look at this React form tutorial. You will learn exactly when and why use these methods. In this component, we will also create initial state of this gallery. It will contain two items: showModal and url. It would be interesting to talk about how to learn React by practice tutorial and ignore states.

To handle the modal dialog, we will create openModal and closeModal methods. Then, we will also bind these methods in constructor to make them accessible for components. Both methods will modify the state of gallery. openModal will set the showModal to “true” and url to URL of current image. closeModal will set the showModal to “false” and reset the url.

JavaScript:

// Component for gallery
class Gallery extends React.Component{
constructor(props) {
super(props);

this.state = {
showModal: false,
url: ''
}

this.openModal = this.openModal.bind(this);

this.closeModal = this.closeModal.bind(this);
}

render() {
return(
<div refs='gallery-container' className='container-fluid gallery-container'>
<div className='row'>
{
imgUrls.map((url, index) => {
return <div className='col-sm-6 col-md-3 col-xl-2'>
<div className='gallery-card'>
<GalleryImage className='gallery-thumbnail' src={url} alt={'Image number ' + (index + 1)} />

<span className='card-icon-open fa fa-expand' value={url} onClick={(e) => this.openModal(url, e)}></span>
</div>
</div>
})
}
</div>

<GalleryModal isOpen={this.state.showModal} onClick={this.closeModal} src={this.state.url} />
</div>
)
}

// Function for opening modal dialog
openModal(url, e) {
this.setState({
showModal: true,
url: url
})
};

// Function for closing modal dialog
closeModal() {
this.setState({
showModal: false,
url: ''
})
}
}

The last final step to make this learn React by practice tutorial work is to render the Gallery component.

JavaScript:

// Let's render the whole thing
ReactDOM.render(
<Gallery imgUrls={imgUrls} />
, galleryContainer);

The whole JavaScript:

// Cache gallery container
const galleryContainer = document.querySelector('.react-gallery');

// Create new array with URLs for images
let imgUrls = [
'https://source.unsplash.com/3Z70SDuYs5g/800x600',
'https://source.unsplash.com/01vFmYAOqQ0/800x600',
'https://source.unsplash.com/2Bjq3A7rGn4/800x600',
'https://source.unsplash.com/t20pc32VbrU/800x600',
'https://source.unsplash.com/pHANr-CpbYM/800x600',
'https://source.unsplash.com/3PmwYw2uErY/800x600',
'https://source.unsplash.com/uOi3lg8fGl4/800x600',
'https://source.unsplash.com/CwkiN6_qpDI/800x600',
'https://source.unsplash.com/9O1oQ9SzQZQ/800x600',
'https://source.unsplash.com/E4944K_4SvI/800x600',
'https://source.unsplash.com/-hI5dX2ObAs/800x600',
'https://source.unsplash.com/vZlTg_McCDo/800x600'
];

// Component for gallery image
class GalleryImage extends React.Component {
render() {
return(
<img className={this.props.className} src={this.props.src} alt={this.props.alt} />
)
}
}

// Component for gallery modal
class GalleryModal extends React.Component {
render() {
if (this.props.isOpen === false) {
return null;
}

return(
<div isOpen={this.props.isOpen} className='modal-overlay' onClick={this.props.onClick} name={this.props.name}>
<div className='modal-body'>
<a className='modal-close' href='#' onClick={this.props.onClick}><span className='fa fa-times'></span></a>

<img src={this.props.src} />
</div>
</div>
)
}
}

// Component for gallery
class Gallery extends React.Component{
constructor(props) {
super(props);

this.state = {
showModal: false,
url: ''
}

this.openModal = this.openModal.bind(this);

this.closeModal = this.closeModal.bind(this);
}

render() {
return(
<div refs='gallery-container' className='container-fluid gallery-container'>
<div className='row'>
{
imgUrls.map((url, index) => {
return <div className='col-sm-6 col-md-3 col-xl-2'>
<div className='gallery-card'>
<GalleryImage className='gallery-thumbnail' src={url} alt={'Image number ' + (index + 1)} />

<span className='card-icon-open fa fa-expand' value={url} onClick={(e) => this.openModal(url, e)}></span>
</div>
</div>
})
}
</div>

<GalleryModal isOpen={this.state.showModal} onClick={this.closeModal} src={this.state.url} />
</div>
)
}

// Function for opening modal dialog
openModal(url, e) {
this.setState({
showModal: true,
url: url
})
};

// Function for closing modal dialog
closeModal() {
this.setState({
showModal: false,
url: ''
})
}
}

// Let's render the whole thing
ReactDOM.render(
<Gallery imgUrls={imgUrls} />
, galleryContainer);

Closing thoughts on how to learn react by practice

Congratulations, you’ve made it again! You’ve finished this learn React by practice tutorial. Not only you learned something about React and practiced your skills. You also built a simple photo gallery with modal dialog. Also, let’s not forget to mention that you practiced modern JavaScript syntax. In other words, you did a great job. You should be proud of yourself. Now, what is the next project you will use to practice your React knowledge? Remember, learning never stops.

Thank you very much for your time.

Improve your design, development and business skills and become tech entrepreneur! Subscribe to my blog.


Originally published at Alex Devero Blog.