Building a Movie Website with HTML, CSS, and JavaScript Fetch Data from API

Elbetelmolla
8 min readAug 1, 2023

--

Introduction:

In this tutorial, we will walk you through the process of building a movie website using HTML, CSS, and JavaScript. The website will display a list of movies fetched from the TMDB API and allow users to search for specific movies. We will create a visually appealing user interface with movie posters, titles, release dates, and brief overviews. Let’s get started!

Here is the outcome of my code

1.Prerequisites:

Before we begin, make sure you have basic knowledge of HTML, CSS, and JavaScript. Additionally, you’ll need an API key from TMDB (The Movie Database) to fetch movie data. You can get your API key from the TMDB website (https://www.themoviedb.org/).

2. Setting Up the HTML Structure:

First, create a new HTML file and set up the basic structure of our movie website. We’ll include a header, a search bar, buttons for Now Playing and Top Rated movies, and a results container to display the movie cards.

<!DOCTYPE html>
<html>
<head>
<title>Movie Website</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>HANI'S MOVIES</h1>
<br><br>
<div class="input-container">
<input type="text" id="searchInput" placeholder="Search for a movie…">
<button id="searchButton">Search</button>
</div>
<br><br>
<div class="wrapper">
<button id="nowPlayingButton" class="button1">Now Playing</button>
<button id="topRatedButton" class="button1">Top Rated</button>
</div>
<div class="results"></div>
<hr>
<footer>
<div id="copyRight">
Copyright &copy; 2023 All Rights Reserved
</div>
<div id="lastFooter">
<ul>
<li>
<a href="">About Us</a>
</li>
<li>
<a href="">Contact Us</a>
</li>
<li>
<a href="">Terms</a>
</li>
<li>
<a href="">License</a>
</li>
</ul>
</div>
</footer>
<script src="script.js"></script>
</body>
</html>

3. Styling the Website with CSS:

Next, let’s add some CSS styles to make our movie website visually appealing. We’ll create styles for the header, search bar, buttons, movie cards, and footer.

@import url("https://fonts.googleapis.com/css?family=Oswald&display=swap");

body {
background: #000;
}

/* Animation styles */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

.fadeInAnimation {
animation-name: fadeIn;
animation-duration: 1s;
}
@keyframes slideInFromLeft {
0% {
transform: translateX(-100%);
}
50% {
transform: translateX(0);
}
100% {
transform: translateX(-100%);
}
}


.card-title{
width: 100%;
display: flex;
flex-wrap: wrap;
color: #000;
}
.col-lg-3{
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
list-style: none;
margin: 10px;
padding: 15px;
border-radius: 12px;
text-align: center;
background:gold;
font-family: 'Audiowide', cursive;
animation-name: fadeIn;
animation-duration: 1s;
}
.col-lg-3 img {
height: 250px;
width: 180px;
border-radius: 5px;
border: 1px solid
}
.results {
display: flex;
flex-wrap: wrap;
justify-content: center;
}

.movie {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
list-style: none;
margin: 10px;
padding: 15px;
border-radius: 12px;
text-align: center;
background:burlywood;
color:#000;
font-family: 'Audiowide', cursive;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.movie img {
height: 250px;
width: 180px;
border-radius: 5px;
border: 1px solid #fff;
}

.movie h2 {
font-size: 1.8em;
padding: 15px 10px 0;
}

.movie p {
margin-top: 10px;
font: size 1px;
font-size: 1.2em;
font-family: "Oswald", sans-serif;

}

.results {
width: 100%;

display: flex;
flex-wrap: wrap;
}
.results li {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
list-style: none;
margin: 10px;
padding: 15px;
border-radius: 12px;
text-align: center;
background: #272727;
}
.results li img {
height: 250px;
width: 180px;
border-radius: 5px;
border: 1px solid
}

.results li h2 {

color: #fff;
font-size: 1.8em;
padding: 15px 10px 0;
font-family: "Oswald", sans-serif;
}

.results h2 {

color: #fff;
font-size: 1.8em;
padding: 15px 10px 0;
font-family: "Oswald", sans-serif;
}


h1{
font-family: 'Audiowide', cursive;
font-size: 2rem;
position: sticky;
display: flex;
justify-content: center;
align-items: center;
letter-spacing: 3px;
margin-left: 10px;
color:antiquewhite;
animation-name: slideInFromLeft;
animation-duration: 5s;
animation-iteration-count: 2;
}
hr{
margin: 10px 0;
}
footer{
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
color: whitesmoke;

}
footer div{
margin: 0 10px;
font-size: 15px;
}
footer div ul{
display: flex;
flex-wrap: nowrap;

}
footer div ul li{
display: flex;
flex-wrap: nowrap;
}
footer div ul li a{
text-decoration: none;
width: 100%;
color: whitesmoke;
margin: 0.5em;
font-size: larger;
}

.wrapper {
perspective: 500px;
transform: rotatex(10deg);
animation: rotateAngle 6s linear infinite;
margin: auto;
width: auto;
display: flex;
justify-content: right;
align-items: right;
}

.button1 {
position: relative;
margin: 0.5em 1rem 3rem 1rem ;
padding:1rem 1em 2.2em;
cursor: pointer;
background: #FFFFFF;
border: none;
border-radius: 0.4em;
text-transform: uppercase;
font-size: 19px;
font-family: "Work Sans", sans-serif;
font-weight: 500;
letter-spacing: 0.04em;
mix-blend-mode: color-dodge;
perspective: 500px;
transform-style: preserve-3d;
}

.button1:before, button:after {
--z: 0px;
position:relative;
top: 0;
left: 0;
display: block;
content: "";
width: 100%;
height: 100%;
opacity: 0;
mix-blend-mode: inherit;
border-radius: inherit;
transform-style: preserve-3d;
transform: translate3d(calc(var(--z) * 0px), calc(var(--z) * 0px), calc(var(--z) * 0px));
}

.button1 span {
mix-blend-mode: none;
display: block;
}

.button1:after {
background-color:cadetblue;
}

.button1:before {
background-color:#b35353;
}

.button1:hover {
background-color:gold;
transition: background 0.3s 0.1s;
}

.button1:hover:before {
--z: 0.04;
animation: translateWobble 2.2s ease forwards;
}

.button1:hover:after {
--z: -0.06;
animation: translateWobble 2.2s ease forwards;
}

@keyframes rotateAngle {
0% {
transform: rotateY(0deg) rotateX(10deg);
-webkit-animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1);
animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1);
}

25% {
transform: rotateY(20deg) rotateX(10deg);
}

50% {
transform: rotateY(0deg) rotateX(10deg);
-webkit-animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1);
animation-timing-function: cubic-bezier(0.61, 1, 0.88, 1);
}

75% {
transform: rotateY(-20deg) rotateX(10deg);
}

100% {
transform: rotateY(0deg) rotateX(10deg);
}
}

@keyframes translateWobble {
0% {
opacity: 0;
transform: translate3d(calc(var(--z) * 0px), calc(var(--z) * 0px), calc(var(--z) * 0px));
}

16% {
transform: translate3d(calc(var(--z) * 160px), calc(var(--z) * 160px), calc(var(--z) * 160px));
}

28% {
opacity: 1;
transform: translate3d(calc(var(--z) * 70px), calc(var(--z) * 70px), calc(var(--z) * 70px));
}

44% {
transform: translate3d(calc(var(--z) * 130px), calc(var(--z) * 130px), calc(var(--z) * 130px));
}

59% {
transform: translate3d(calc(var(--z) * 85px), calc(var(--z) * 85px), calc(var(--z) * 85px));
}

73% {
transform: translate3d(calc(var(--z) * 110px), calc(var(--z) * 110px), calc(var(--z) * 110px));
}

88% {
opacity: 1;
transform: translate3d(calc(var(--z) * 90px), calc(var(--z) * 90px), calc(var(--z) * 90px));
}

100% {
opacity: 1;
transform: translate3d(calc(var(--z) * 100px), calc(var(--z) * 100px), calc(var(--z) * 100px));
}
}


.input-container {
display: flex;
border-radius: 1rem;
background: linear-gradient(45deg, #c5c5c5 0%, #ffffff 100%);
box-shadow: 20px 20px 20px #d8d8d8,-10px -10px 20px #f8f8f8;
padding: 0.3rem;
width: 550px;

gap: 0.3rem;
}

.input-container input {
border-radius: 0.8rem 0 0 0.8rem;
background: #e8e8e8;
box-shadow: inset 13px 13px 10px #dcdcdc,
inset -13px -13px 10px #f4f4f4;
flex-basis: 75%;
padding: 1rem;
border: none;
border-left: 2px solid #4998FF;
font-weight: 900;
transition: all 0.2s ease-in-out;
font-size:18px;
width: 200px;

}

.input-container input:focus {
border-left: 2px solid #4998FF;
outline: none;
box-shadow: inset 13px 13px 10px #BFF0FA,inset -13px -13px 10px #f4f4f4;
}

.input-container button {
flex-basis: 25%;
padding: 1rem;
background: linear-gradient(135deg, #BFF0FA 0%, #4998FF 100%);
font-weight: 900;
letter-spacing: 0.3rem;
text-transform: uppercase;
color:black;
border: none;
width: 100%;
border-radius: 0 1rem 1rem 0;
font-weight: bold;
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8), 2px 2px 4px rgba(0, 0, 0, 0.2); /* Add text shadow */
transition: all 0.2s ease-in-out;
}

.input-container button:hover {
background: linear-gradient(135deg, #BFF0FA 0%, #4998ffc4 100%);


}

@media (max-width: 500px) {
.input-container {
flex-direction: column;
}

.input-container input {
border-radius: 0.8rem;
}

.input-container button {
padding: 1rem;
border-radius: 0.8rem;
}
}

4. Fetching Movie Data with JavaScript:

Now, let’s implement the JavaScript code to fetch movie data from the TMDB API and display it on our website.

const options = {
method: 'GET',
headers: {
accept: 'application/json',
Authorization: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJkYmE4ODA0YjA4NjAxYjExOGExZjFhZjZhMzgzNGI3NCIsInN1YiI6IjY0OWVmZmM0YzlkYmY5MDEwN2UxZTU0MiIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.EV_B46kJXwRaqfcfXunUdvSCCDyyRzkS13QBLwEgXK4'
}
};

fetch('https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&sort_by=popularity.desc', options)
.then(response => response.json())
.then(data => {
const movielist=data.results;

movielist.map((item)=>{
const name=item.title;

const poster_path=item.poster_path;
const imageURL = `https://image.tmdb.org/t/p/w500${poster_path}`;
//console.log(imageURL)
const movies=`<li><img src="${imageURL}"> <h2>${name}</h2>
</li>`;
document.querySelector('.results').innerHTML += movies;
});
})
.catch(err => console.error(err));



function fetchMovie(){
const searchinput = document.getElementById("searchInput").value;
let results = document.querySelector('.results');
results.innerHTML = "";
//resultss.innerHTML = " ";
if (!results) {
results = document.createElement("div");
results.setAttribute("id", "results");
document.body.appendChild(results);
}

fetch("https://api.themoviedb.org/3/search/movie?query=" + searchinput + "&include_adult=false&language=en-US&page=1", options)

.then((response) => response.json())
.then((response) => {
for (let i = 0; i < response.results.length; i++) {
// console.log(response);
let title = response.results[i].title;
let release_date = response.results[i].release_date;
let poster_pat = response.results[i].poster_path;
let overvieww = response.results[i].overview;
let card = document.createElement("div");
card.style = 'style="width: 18rem';
card.setAttribute("class", "col-lg-3");

let img = document.createElement("img");
img.classList.add("card-img-top");
// const poster_path=item.poster_path;
const imageURL = `https://image.tmdb.org/t/p/w500${poster_pat}`;
img.src =imageURL;

let ctitle = document.createElement("h5");
ctitle.setAttribute("class", "card-title");
ctitle.textContent = title;

let crd = document.createElement("h7");
crd.setAttribute("class", "card-title");
crd.textContent = "Date of Release: " + release_date;

let overveiw = document.createElement("h7");
overveiw.setAttribute("class", "card-title");
overveiw.textContent = overvieww;

card.append(img);
card.append(ctitle);
card.append(crd);
card.append(overveiw);
results.prepend(card);
}
})
.catch((err) => console.error(err));
}

5. Implementing Search Functionality:

To allow users to search for movies, we’ll add an event listener to the search button and fetch movie data based on the user’s input.

document.getElementById("searchButton").addEventListener("click", fetchMovie);


// Event listener for the "Now Playing" button
document.getElementById("nowPlayingButton").addEventListener("click", function() {
fetchNowPlaying();
});

// Event listener for the "Top Rated" button
document.getElementById("topRatedButton").addEventListener("click", function() {
fetchTopRated();
});

6. Displaying Now Playing and Top Rated Movies:

We’ll implement two separate functions to fetch and display Now Playing and Top Rated movies when users click on the respective buttons.

// Function to fetch data from the "Now Playing" endpoint and display in results div
function fetchNowPlaying() {
let resultsDiv = document.querySelector('.results');
resultsDiv.innerHTML = "";

fetch("https://api.themoviedb.org/3/movie/now_playing?language=en-US&page=1", options)
.then((response) => response.json())
.then((response) => {
response.results.forEach((movie) => {
const movieDiv = document.createElement('div');
movieDiv.classList.add('movie');

const title = document.createElement('h2');
title.textContent = movie.title;

// Create an image element for the poster
const posterImage = document.createElement('img');
posterImage.src = `https://image.tmdb.org/t/p/w500${movie.poster_path}`;
posterImage.alt = movie.title; // Use the movie title as alt text for accessibility

const releaseDate = document.createElement('p');
releaseDate.textContent = "Date of Release: " + movie.release_date;

const overview = document.createElement('p');
overview.textContent = movie.overview;

movieDiv.appendChild(posterImage);
movieDiv.appendChild(title);
movieDiv.appendChild(releaseDate);
movieDiv.appendChild(overview);

resultsDiv.prepend(movieDiv);
});
})
.catch((err) => console.error(err));
}

// Function to fetch data from the "Top Rated" endpoint and display in results div
function fetchTopRated() {
let resultsDiv = document.querySelector('.results');
resultsDiv.innerHTML = "";

fetch("https://api.themoviedb.org/3/movie/top_rated?language=en-US&page=1", options)
.then((response) => response.json())
.then((response) => {
response.results.forEach((movie) => {
const movieDiv = document.createElement('div');
movieDiv.classList.add('movie');

const title = document.createElement('h2');
title.textContent = movie.title;

// Create an image element for the poster
const posterImage = document.createElement('img');
if (movie.poster_path) {
posterImage.src = `https://image.tmdb.org/t/p/w500${movie.poster_path}`;
} else {
posterImage.src = 'placeholder_image_url.jpg'; // You can use a placeholder image URL if the movie doesn't have a poster
}
posterImage.alt = movie.title; // Use the movie title as alt text for accessibility

const releaseDate = document.createElement('p');
releaseDate.textContent = "Date of Release: " + movie.release_date;

const overview = document.createElement('p');
overview.textContent = movie.overview;

movieDiv.appendChild(posterImage);
movieDiv.appendChild(title);
movieDiv.appendChild(releaseDate);
movieDiv.appendChild(overview);

resultsDiv.prepend(movieDiv);
});
})
.catch((err) => console.error(err));
}

7. Conclusion:

Congratulations! You have successfully built a movie website using HTML, CSS, and JavaScript. Users can now search for movies, view Now Playing and Top Rated movies, and explore movie details. Feel free to further enhance the website by adding more features or improving the user interface.

In this tutorial, we covered the basic implementation of the movie website. You can continue to expand and customize the website according to your preferences and creativity.

GitHub Link:https://elbetel12.github.io/moviewebsite/

--

--