Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
Parallax scrolling is the effect where the background image scrolls slower than the elements in the foreground, creating an illusion of depth of the page.
Websites often use this for informational pages, where you have some text in the foreground and an image in the background that scrolls more slowly to create a more interesting experience for the user.
https://www.mockplus.com/blog/post/parallax-scrolling-websites has some examples of web pages with parallax scrolling.
With React, it is quick and simple to create the parallax scrolling effect with the Vue-Parallaxy library, located at https://github.com/apertureless/vue-parallax.
In this article, we will make an app that displays a list of images in the background with tags text in the foreground. The images will be provided by the Pixabay API. You can register for an API key at Pixabay.
To start the project, we create the project by running:
npx @vue/cli create photo-app
Then we select ‘Manually select features’ then choose to include Babel and Vue Router.
We need to install Axios to get images from the Pixabay API, BootstrapVue for styling, and Vue-Parallaxy to create the parallax scrolling effect. To install the packages run:
npm i axios bootstra-vue vue-parallaxy
With all the packages installed, we can start building the app. To start, we add a mixin for making the HTTP requests. Create a mixins
folder in the src
folder, then in the folder, create requestsMixins.js
. In the file, add:
const axios = require("axios");
const APIURL = "https://pixabay.com/api";
export const requestsMixin = {
methods: {
getImages(page = 1) {
return axios.get(
`${APIURL}/?page=${page}&key=${process.env.VUE_APP_API_KEY}`
);
}
}
};
Next in Home.vue
, replace the existing code with the following:
<template>
<div class="page">
<div v-for="(img, i) of images" :key="i" class="parallax-container">
<parallax :speed-factor="0.5" direction="down" :parallax="true">
<div>
<img :src="img.largeImageURL" :alt="img.tags" style="image" />
<h1 class="parallax-title">{{img.tags}}</h1>
</div>
</parallax>
<br />
</div>
</div>
</template>
<script>
// @ is an alias to /src
import { requestsMixin } from "../mixins/requestsMixin";
import Parallax from "vue-parallaxy";
export default {
name: "home",
mixins: [requestsMixin],
components: {
Parallax
},
data() {
return {
images: []
};
},
methods: {
async getImagesByPage() {
const response = await this.getImages();
this.images = response.data.hits;
}
},
beforeMount() {
this.getImagesByPage();
}
};
</script>
<style>
.parallax-container {
position: relative;
height: 1000px;
}
.parallax-title {
position: absolute;
top: 30%;
left: 0;
right: 0;
padding: 20px;
color: white;
text-align: center;
}
.image {
height: 700px;
}
</style>
We include the Vue-Parallaxy component in this component by adding Parallax
in the components
object. Then we get the images by calling the this.getImages
function from the requestsMixin
we just created. We call the getImagesByPage
function in the beforeMount
hook to get the images when the page loads.
In the template, we use the parallax
component provided by Vue-Parallaxy to create the parallax scrolling effect. The parallax
serves as the container for the parallax effect. We make the speed of the scrolling different from the foreground with the speed-factor
prop, we set the direction
to down so that it scrolls down. parallax
prop is set to true
so that we get the different scrolling speed between the foreground and background.
We change the height of the parallax-container
divs to the same height of 1000px, and the images to 700px to keep the spacing consistent.
In the component, we loop through the images and show some text from the Pixbay API. We position the text inside the photo by specifying:
<style>
.parallax-container {
position: relative;
}
.parallax-title {
position: absolute;
top: 30%;
left: 0;
right: 0;
padding: 20px;
color: white;
text-align: center;
}
</style>
We place the text in the center of the images and change the text color to white.
Next in App.vue
, we replace the existing code with:
<template>
<div id="app">
<b-navbar toggleable="lg" type="dark" variant="info">
<b-navbar-brand href="#">Photo App</b-navbar-brand> <b-navbar-toggle target="nav-collapse"></b-navbar-toggle> <b-collapse id="nav-collapse" is-nav>
<b-navbar-nav>
<b-nav-item to="/" :active="path == '/'">Home</b-nav-item>
</b-navbar-nav>
</b-collapse>
</b-navbar>
<router-view />
</div>
</template>
<script>
export default {
data() {
return {
path: this.$route && this.$route.path
};
},
watch: {
$route(route) {
this.path = route.path;
}
}
};
</script>
<style lang="scss">
.page {
padding: 20px;
}
</style>
We add some padding to the pages with the page
class, and we add the BootstrapVue navigation bar to the top of the page. Also, we have the router-view
so that we see the home page.
Next in main.js
, we replace the existing code with:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
import BootstrapVue from "bootstrap-vue";
Vue.config.productionTip = false
Vue.use(BootstrapVue);
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
to add the BootstrapVue libraries and styles to the app so we can use the code in our app and see the styling in the whole app.
Then in router.js
, replace the existing code with:
import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
Vue.use(Router);
export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/",
name: "home",
component: Home
}
]
});
We added the home page route so that we can see the page we built.
Then in the root folder of the project, we add an .env
file so store the API key:
VUE_APP_API_KEY='Pixabay API key'
We can use this keep by referencing process.env.VUE_APP_API_KEY
like we have in the requestsMixin.js
.
Next in index.html
, replace the existing code with:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>Photo App</title>
</head>
<body>
<noscript>
<strong
>We're sorry but vue-parallax-scrolling-tutorial-app doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
to change the title.