Emil Andersson logotype
Written by Emil Andersson on
August 18th, 2022 in Tutorials

Coverflow with PHP & CURL

In this tutorial we will build a modern coverflow web application with dynamic content from The Movie DB. We will use PHP and CURL to set this up. Then make use of CSS animations and finally make the coverflow effect with the jQuery plugin Flipster.

Coverflow with PHP and CURL

View Demo

First of all we need the API key. Create a free account to get your free API key: https://www.themoviedb.org/signup. When you activated your account by email, visit this URL to see your API key: https://www.themoviedb.org/settings/api

Download Flipster JS from here. Create two new folders "css" and "js" and move the downloaded files to the correct folder. Start your local dev enviroment and paste the following code into index.php:

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Cover Flow X</title>
    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="css/flipster.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    <section class="main-content">
        <div class="movie-title"><h2>New Movies</h2></div>
        <div id="coverflow">
            <ul class="flip-items">
                $apiKey = '';
                $ApiUrl = 'https://api.themoviedb.org/3/discover/movie?api_key='. $apiKey .'&language=en-US';

                $ch = curl_init();

                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_setopt($ch, CURLOPT_REFERER, 'https://www.domain.com/');
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_URL, $ApiUrl);
                $results = curl_exec($ch);

                $movies = json_decode($results);

                foreach($movies->results as $movie) { ?>
                <li data-flip-title="<?php echo $movie->title; ?>" data-source="https://www.themoviedb.org/movie/<?php echo $movie->id; ?>" data-rating="<?php echo $movie->vote_average; ?>" data-backdrop="https://www.themoviedb.org/t/p/w1920_and_h1080_multi_faces<?php echo $movie->backdrop_path; ?>">
                    <img src="https://image.tmdb.org/t/p/w600_and_h900_bestv2<?php echo $movie->poster_path; ?>">
            <?php } ?>
    <script src="js/flipster.js"></script>
    <script src="js/main.js"></script>

Now we create a new file called main.js and put it into the folder "js". Then paste the following code to create the coverflow effect:

$(document).ready(function() {
        itemContainer:    'ul',
        itemSelector:     'li',
        style:'coverflow', // 'coverflow' or 'carousel' or 'flat' or 'wheel'
        start: 'center',
        fadeIn: 400,
        loop: true,
        autoplay: false,
        pauseOnHover: true,
        spacing: -0.3,
        click: true,
        keyboard: true,
        scrollwheel: true,
        touch: true,
        nav: false, // If true, flipster will insert an unordered list of the slides
        buttons: false,
        onItemSwitch: (currentItem, previousItem) => { // Callback function when items are switched
            var movieTitle = $(currentItem).attr('data-flip-title');
            var movieLink = $(currentItem).attr('data-source');
            var movieRating = $(currentItem).attr('data-rating');
            $('.movie-title').removeClass('active'); // Used to restart CSS animations
            $('.movie-title').addClass('active'); // Used to restart CSS animations
            $('.movie-title').html('<h2><span class="movie-rating">' + movieRating + '</span>' + movieTitle + '</h2>' + '<div class="movie-actions"><div class="movie-actions-container"><a href="' + movieLink + '" target="_blank" class="movie-info"><i class="bi bi-camera-video"></i> More</a><a href="#" class="tickets"><i class="bi bi-ticket-perforated"></i> Tickets</a></div></div>');
            $(currentItem).css('cursor', 'pointer');

Finally, we create style.css and put it into the "css" folder. Paste these lines in style.css:

body {
    background: #f9fbff;
    font-family: 'Roboto', 'Calibri', sans-serif;
    height: 100%;
a {
    text-decoration: none;
    color: #2347ff;
a:hover {
    color: #5c77ff;
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
#coverflow {
    margin-top: 5%;
    display: inline-block;
.movie-title {
    position: relative;
    color: #75798d;
    margin: 100px auto;
    width: 100%;
    display: flex;
    animation-name: none;
    justify-content: center;
.movie-title h2 {
    font-size: 50px;
    font-weight: normal;
    padding: 24px 40px;
    display: flex;
.movie-title.active {
    animation-name: movieTitle;
    animation-duration: .5s;
    animation-fill-mode: forwards;
    animation-iteration-count: 1;
@keyframes movieTitle {
    0% {
        opacity: 0;
        transform: translateY(10px);
    100% {
        opacity: 1;
        transform: translateY(0px);
.movie-title.active .movie-actions {
    animation-name: movieTitleActions;
    animation-duration: .5s;
    animation-fill-mode: forwards;
    animation-iteration-count: 1;
    animation-delay: .4s;
@keyframes movieTitleActions {
    0% {
        opacity: 0;
        transform: translateY(10px);
    100% {
        opacity: 1;
        transform: translateY(0px);
.movie-rating {
    width: 60px;
    height: 60px;
    font-size: 24px;
    font-weight: bold;
    background: #d73991;
    color: #fff;
    display: flex;
    align-content: flex-start;
    justify-content: center;
    align-items: center;
    border-radius: 50%;
    margin-right: 20px;
.movie-actions {
    opacity: 0;
    display: flex;
    font-size: 18px;
    justify-content: center;
    position: absolute;
    width: 100%;
    top: 105px;
.movie-actions-container {
    display: flex;
    font-size: 18px;
    justify-content: center;
    padding: 14px 30px;
    background-color: #fff;
    width: fit-content;
    border-radius: 8px;
    box-shadow: 0px 18px 20px rgb(153 172 243 / 8%), 0px 10px 14px rgb(178 187 207 / 6%), 0px 8px 9px rgb(213 213 213 / 4%);
.movie-actions a {
    font-weight: bold;
.movie-actions a:first-child {
    margin-right: 10px;
.movie-actions a:last-child {
    margin-left: 10px;
.movie-actions a i {
    margin-right: 3px;
.flipster__item__content img {
    width: 300px;
    height: 450px;
    border-radius: 14px;

All we need to do now is to paste the API key from https://www.themoviedb.org/settings/api into $apiKey = 'your-api-key-here' in index.php.


    No tags