Build Youtube in React 16: Video Infobox
1 Overview
Well, well well, glad you still stick around.
There are two omore bigger components left in our Watch
component.
Here’s what we’re up to. Click on the image to see it in high resolution.

In this tutorial we will work on the Youtube info box
, i.e. the component directly underneath the video’s view count.
Let’s take a closer look. Click on the images to see them in high resolution.

If we click the Show More
button, the component is supposed to show the entire description that is available. Per default, it only shows two lines.

2 Building the Youtube VideoInfoBox component
2.1 Creating the files
Our VideoInfoBox
component will only be responsible for laying out some data. It will not reach out to an API
or access our Redux
store later on. Therefore, we consider it a presentational component and put it into src/components
.
- Create a new directory inside
src/components
and call itVideoInfoBox
- Create a
VideoInfoBox.js
and aVideoInfoBox.scss
file inside the directory you just created
2.2. Designing Youtube’s video info box
Let me give you another image to show you how we’ll create the markup for our info box.

Our component clearly has a two dimensional layout. Therefore we’ll use CSS-Grid
again. We could also built it using flexbox
, but then we would need nested flex
containers. Grid
makes our life way easier. So let’s get started.
2.3 Youtube Video info box CSS Grid layout
Here’s the basic layout structure of ourVideoInfoBox
component.
Our root element is a div
with the class .video-info-box
. We make it a grid container
by setting display: grid
. As already shown in the image above, we need a 2x3 grid
, i.e. a grid with two rows and three columns. We don’t really care about the rows’ height, that’s why we specify auto
two times in our grid property.
In the original Youtube app, the channel’s image is 48px x 48px
. Since the circular channel image will go into the top left cell, we give the column a width of 58px
to have 10px
of additional whitespace. The third column is different though as it will hold our Subscribe
button. We set the column’s width to max-content
so that the text in the subscribe button never wraps.
Now that we have the first and the third column out of the way, we just set the width of the second column to auto
. Grid
will take care of the rest.
In addition, we want our channel image, the video’s title and the subscribe button to be on one imaginary horizontal line because that looks better. Therefore, we instruct Grid
to center its children vertically by setting align-items: center
.
2.4 Updating our Watch component
To see the result of our efforts in action, we actually need to use our newly created component somewhere. Head over to our Watch
component and update the markup of the render
function like so:.
Note that we removed the video-info-box
placeholder div
.
2.5. Refining video info box
We have our Grid
, but we still need to put some content there.
Let me show you the content of the render
function first:
The markup itself should be relatively straight forward. Before I show you the SCSS
, please have a look at the image below where I marked the horizontal grid lines in red and the vertical ones in black.

I’ve also annotated their grid line numbers, so the following SCSS
is easier to understand.
Our .channel-image
class puts the channel’s image into the top left cell. We place the video’s title and its publication date into the second column of the first row by applying the .video-info
class. Our subscribe button is put into the top right cell by applying the .subscribe
class.
In the original Youtube app, the video’s description text block has a maximum width of 615px
. That’s why we apply a max-width
constraint in our .video-description
class. This SCSS
class that is applied to the element that holds the video’s description text.
Here’s what we have so far: Click on the image to see it in high resolution.

Great, we’re done with the basic layout. As we already discussed earlier, we want the video’s description to be sort of collapsed. The user should only see the first two lines of it. If the user clicks expand, we show the entire content. So let’s get to it.
2.6 Adding expanding capability to video info box
Now, we’re going to do something we have not done before. We will add local state to a component. We will introduce a prop
called collapsed
to our local state so that our VideoInfoBox
knows whether it’s currently showing the full text or not. Note that it is our component’s business whether it is currently collapsed or not. Therefore this property will not belong to our global state.
In our constructor, we set our component’s initial state and add a collapsed
property whose default value is true
. This flag is supposed to indicate whether we currently only show two lines of the video’s description or the entire text.
We also added the onToggleCollapseButtonClick
event handler. This function is just flipping our local state’s collapsed
boolean
variable.
Calling the setState
function will force the component to re-render.
2.7. Video Info Box dynamic styling
To make the video info box'
styling dynamic we need to apply different CSS
depending on whether it is currently collapsed or not. So please go ahead and add the following code to your VideoInfoBox.scss
file:
We apply a little bit of cosmetics to the p
element and explicitly set its line-height
. By setting the max-height
to twice a paragraph’s line-height
, we automatically put a height constraint on the element if the .collapsed
class is applied. The overflow-y: hidden
property makes sure that overflowing content is not displayed.
To show the entire text, we just need to apply the .expanded
class which removes the max-height
constraint and allows the container to vertically expand as much as it needs to display the full content.
Oh yeah, one more thing. We explicitly set the margin-bottom
to 0px
because the Semantic UI SCSS
applies a default bottom margin of 1em
which we don’t want in this case.
2.8. Toggling the video info box description
Let’s make use of our new SCSS
classes in our component. First, the component needs to determine what SCSS
class it should apply. Therefore, it needs to check the collapsed boolean of its local state and pick the desired SCSS
class.
Please put the following code at the top of the render
function:
So depending on whether our collapsed
flag is set, we adapt our SCSS
classes accordingly and also change our button’s title.
As a last step, we need to adapt our component’s markup.
Note that we added a new div
inside the .video-description
element that applies the descriptionTextClass
. We put all our text (i.e. all paragraphs) in here.
In addition, the component now reacts to the click event of the Show more / Show less button and displays the value of the buttonTitle
variable as text.
Here’s how the collapsed version of our info box looks like.

Click on the image to see it in high resolution.

And here is the expanded version:
3 Tests
That was more logic than expected. Let’s add tests have this component done as well.
- Create a new directory inside
src/components/VideoInfoBox
and call it__tests__
- Add a
VideoInfoBox.unit.test.js
file inside of the directory you just created.
In order to capture the component’s markup in both expanded
and collapsed
state we added two tests. Since VideoInfoBox
is collapsed per default, we can just render
it without any props or something to get the markup when it’s collapsed.
We use setState
in our component to trigger a re-render when the button is clicked. To get the component’s markup in expanded
state, we could programatically trigger the button
click.
However, we might refactor this component in the future and might not rely on a button anymore. Therefore, let’s set the state directly from within our test by calling wrapper.setState({collapsed: false})
.
If we change the component’s state later on, this test will fail. But that’s ok. We want it to fail, so we know something has changed.
You can run your tests by executing
4 Wrap Up
Aaaand we’re done with yet another component.
Note that we did not add the logic for displaying links properly. We will do that once we fetch video descriptions from the Youtube
endpoint. For now, the VideoInfoBox
component is good enough.
However, our Watch
component still needs an element that displays the video’s comments. We’ll do that in the next tutorial.
As always, thanks for reading.
You can find the entire code on our Github repository.
Follow @productioncoderPlease follow me on Twitter @productioncoder to stay up-to-date. I’m happy to receive feedback of any kind.
If you are interested in more high-quality production-ready content, please enter your email below.
Recent Comments