Check out a free preview of the full Fullstack Svelte with SvelteKit course

The "Movie Page" Lesson is part of the full, Fullstack Svelte with SvelteKit course featured in this preview video. Here's what you'd learn in this lesson:

Rich walks through building a page that will contain information about the selected movie, including, description, trailer, budget, genre, and recommendations for other movies. Building the movie's Hero component with the backdrop image and movie description is covered in this segment.


Transcript from the "Movie Page" Lesson

>> So our Svelte Flicks app is looking in reasonably good shape. We're just gonna add one final page before we call it a day, and that is the individual movie page that we've been linking to all over over the place. But haven't yet visited or implemented. So, open src/routes for the last time and create a new route inside movies.

I'm gonna call it in square parameters id, that's gonna uniquely identify the movie. And you'll notice that it's okay to have these two routes with dynamic parameters in the same directory, because one of them has this matcher. So the router knows that these two things are not going to conflict it's going to try.

If we go to /movies/trending is going to try the [view=list] parameter first. And if that doesn't match, then it's gonna try the ID parameter. Is one of the benefits of having a really sophisticated routing system. So once more, we're gonna create a page.ts not js and a page.svelte.

Inside our page.ts, we're gonna add an async loading function. We're gonna get the params object and we're gonna get fetch. And we're gonna make, you guessed it an API call. Const movie equals import our api helper. Api.get, pass in our fetch. The endpoint is gonna be, /movie /

And we're gonna use that append to response trick that we used before to get multiple request data in one go. We're gonna get images, videos and recommendations. And just so that we can get the most value out of our client-side caching, I'm gonna duplicate this Append to Response property on the homepage here.

This way if someone clicks from the hero image on the homepage, then they're gonna get a cache hit which is gonna be really nice. This is a movie details object, so we'll add the as MovieDetails. And on this page If we look at the one that's deployed online already, I had JavaScript disable this whole time.

Okay, Reload that page. So, on this page we have some information about the movie. We also have a trailer which is being shown on the left there. We wanna have that on the movie page that we're about to build. In order to do that, we wanna get the trailer object from the movie videos results.

And specifically, we want to have a video that is of type trailer and is hosted at YouTube because we know how to embed those. So we'll return, Video.official. So it came from from the actual studio, = YouTube. And the video.type is either a trailer or A teaser.

And then, we're just gonna return all of that to our page load function. From our page load function into our page. So we will add a script tag. Lang = ts export let data, and it has the movie details and the trailer on that object. The first thing we're gonna do is add another hero component, Which is gonna take a movie object.

We'll create a div with a class of hero. And we'll create a div class = backdrop for the for the backdrop image to go in. And then below that, we'll have some info about the movie. Right? We're gonna have the movie title first of all. Then we're gonna have a movie overview.

And let's add that component to our page, pass in the movie object. And take a look and see if it's appearing. It's giving us a not found error. And I think I know why, it's because this URL here is saying /movie, instead of /movies. So we need to figure out where that's coming from and fix it.

See this link here has /movie, just fix that. We got another one here. We'll fix that too. And try that once more. And it's giving us some information about the movie 65 with Adam Driver. As before, we can use the media helper to create this image. Give it an alt attribute first.

That's gonna be the movie title. And the source is media. I'm gonna pass in the movie backdrop. Actually, we're gonna need to figure out what backdrop to use first. So like before, we're gonna grab movie.images.backdrops. Find the first backdrop that doesn't have a language, so that we don't have any text.

Using this ISO 6391 property and if we can't find one of those then we'll just fall back to whatever the first item in the array is. All right, now that we've got that reference, we can do backdrop file_path. And we're gonna give it a width of 1280, And you'll see it's rendering it, although it's rendering it a little bit too large, so we'll add some styles.

This hero element, we're gonna give this a display of grid so that we can have a mobile view and a desktop view. Once we get above a certain width we're gonna need to stop that image from growing, so we'll add a media query. So we're gonna divide this into a grid that is stacked vertically on mobile and horizontally on larger screens.

And this backdrop element, we're gonna put that in the right hand column. At the moment because it's first in the DOM, it will be in the left hand column. Which, if you look at the original is not the way that it works. Over here it's positioned on the right.

So you can do the same thing by controlling the rendering order distinct from the DOM order. Display grid makes it really easy to do this sort of thing. We can just add a grid column attribute, which positions it on the right hand side. We need to put some maximum widths on these images.

Okay, and we can now see that it's behaving the way that we want it to. It's not spilling out into the rest of the page beyond the window. You have a question?
>> If two match functions have some similarities, which one would take priority matching route params?
>> That's a really good question.

I'm actually not sure what happened in the situation where you have two dynamic parameters with matches in the same route. I think it would probably be alphabetical. But I would have to go and check that. I would guess alphabetical. That's a great question. All right, let's add some styles for the info block here.

I'm gonna move that window over so that we can see the page as we're editing it. We'll begin by giving it some padding. Looks a little bit nice already. We'll make it a display flex element with the flex direction of column. And we're gonna give it a negative margin top.

This is gonna move the element over the image which is gonna create a nice visual effect And we're gonna get rid of the margin on the elements inside the info block. And instead we're gonna have a gap in the flex element, it looks like this. That happens to work out really nicely on this poster because it's dark around the edges and the title of the movie is quite short.

But on some other posters like let's take Super Mario Brothers. This is like super hard to read. So, we're gonna add a little black gradient at the bottom of the movie poster so that we can see that text. The way that we're gonna do that is with a pseudo element.

We need to give it some content but this can just be the empty string. I'm gonna fill the width and then give that a height of, let's say, 8 rems. And we'll just do a black background for now, check that we're doing things correctly. We need to put that over to the left and position it based on the bottom of the container element.

Okay, so we can now obviously read the textbook, we're also obscuring a bunch of the poster. So instead of having a black background, we're gonna have a linear gradient that's gonna go to the top of the element. It's gonna start black at the bottom and it's gonna end transparent at the top.

And now we have this nice fade so that we can see the poster, but we can also read the information on top of it. When we get bigger, we want to have the information on the left hand side instead. So we're gonna add some more styles inside our media query.

Create a new Info Selector. I'm gonna position it absolutely. And we're gonna give it a width of 40 ems, which should be about right. Gonna make it fill the available height. And just like the backdrop has been moved to the right hand side with this grid column rule, we're gonna do the same thing in reverse for the info to move it onto the left hand side.

And we're gonna get rid of that negative margin that we were using before. I wanna justify the content in the center. So now when we look at this we can see that the headline and the outline are going where we want them to. But again it's kind of hard to read this text because we need to add one of those nice gradients.

We can see the gradient is still being applied at the bottom of the poster where we don't want it. So we're gonna get rid of that and replace it with a horizontal gradient instead. So that backdrop after pseudo element, we'll give it a, I'm gonna just drop that breakpoint down a bit so that we can see it.

Give it a width that isn't 100%, we'll use 15 rems. Gonna make it fill the available height. Move it all the way to the left and the bottom. And this time the background is gonna be a linear gradient that goes to the right. Again, from black to transparent.

Still a little bit hard to read, so I'm just gonna shove a drop shadow on there. Drop shadow is sort of a get out of jail free card when you're trying to build these sorts of user interfaces. And you can have as many of these in sequence as you like if you need to up the power like that, okay?

So we can see the poster, but we can also read the text.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now