Recreate: Spotify (part 1)
Tags: beginners, css, ui, frontend
Published: 2020-02-20 21:35:28

#Hello 🌍
This is the first part of the Recreate Spotify series!
I will document all the steps that I take along the way, in the hope that someone will benefit from this process. If you think that I could do anything differently feel free to leave a comment 🙂.

#Disclaimer
I will use the magic of the Inspect element for properties that I think do not truly matter in the context of these series. Examples are: the background colors, text colors and the scrollbar(the width).
Lastly, throughout these the font family will be Open Sans and all the icons will be [LineIcons](https://lineicons.com/), if I do not find the exact icon then I will use one that is similar.

In these series I will recreate the [open.spotify.com](https://open.spotify.com) UI. You can see the UI in the following images: 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dl4uuwu8dfz5qnatpam6.png)
<figcaption>1. Spotify Homepage</figcaption>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7dyrjxfi3gten4zf8ms9.png)
<figcaption>2. Spotify Search</figcaption>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c66netbjbnuri91q87gc.png)
<figcaption>3. Spotify Album</figcaption>

#First steps

The first step is to go through the pages of the [open.spotify.com](https://open.spotify.com) web app. 
My goal is to: 
- Understand which components are always visible (Left Sidebar).
- Make a rough estimation of the total number of the components.
- Understand the general look & feel of the app.

#Cutting the design to smaller pieces

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6i3prdg3syg24owlsgge.png)
<figcaption>4. Main areas marked</figcaption>

Scanning through the application, I counted 4 main components that are always there
1. Left sidebar
2. Top bar
3. Main area that holds the data between every page
4. Music playback bar

Of course the main (parent) components consist of many children components.
For example: looking at the Left Sidebar, we can see that it has some children inside. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/6n2n1nay9d5ff35584fl.png)
<figcaption>5. Sidebar with different elements selected
</figcaption>

Those are the following: 
- Logo/Brand
- Menu item that has one icon and text
- Heading text
- Menu item that has image and text
- Separator
- Install application link on the bottom


#Coding the left sidebar💻

I start with creating a <nav> item that will be the left sidebar and just give a proper width and position to it.
```css
html {
    font-size: 16px;
}

body {
    margin: 0;
    color: #fff;
}

* {
    box-sizing: border-box;
    font-family: 'Open Sans', sans-serif;
    letter-spacing: -0.35px;
}

.sidebar {
    background-color: rgba(4, 4, 4);
    position: fixed;
    height: 100%;
    width: 230px;
}
```
 
```html
<nav class="sidebar"></nav>
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/qxgpdnv1f8mmre37dyl0.png)
<figcaption>6. Sidebar position at the left</figcaption>

I continue with creating the top bar and the main area. At this point I like to give the components different background colors and full height so that I can easily see if I misplaced something.

```css
.sidebar {
    background-color: rgba(4, 4, 4);
    position: fixed;
    height: 100%;
    width: 230px;
}

main {
    min-height: 100vh;
    background: dodgerblue;
}

.header {
    position: fixed;
    top: 0;
    left: 230px; /* sidebar width */
    right: 0;
    height: 80px;
    background-color: rgb(18, 18, 18);
}


```
 
```html
<nav class="sidebar"></nav>
<div class="header"></div>
<main></main>
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ofsim1uee4a2puf1k9ey.png)
<figcaption>7. Left sidebar, top bar & main area</figcaption>

Don't worry, I promise it will start looking like the Spotify web app. 

Let's go back to the sidebar, but now we will progress a bit more. When we finish the sidebar will have all the different marked elements from the Image 5.

#Further examination of the sidebar
Looking at the sidebar I try to think of all the paddings and the margins that I will need. For example it looks like there is a padding-left in the main element. If you look at the sidebar you can see that all the elements inside the <nav> start from the same point (horizontally).

So starting from the parent element I add the padding. Next I insert the logo of spotify in svg format and I create the html for the main menu items (Home, Browse, Library). 

```html
<nav class="sidebar">
    <div class="brand">
        <svg viewBox="0 0 1134 340" class="spotify-logo--text"><title>Spotify</title><path fill="currentColor" d="M8 171c0 92 76 168 168 168s168-76 168-168S268 4 176 4 8 79 8 171zm230 78c-39-24-89-30-147-17-14 2-16-18-4-20 64-15 118-8 162 19 11 7 0 24-11 18zm17-45c-45-28-114-36-167-20-17 5-23-21-7-25 61-18 136-9 188 23 14 9 0 31-14 22zM80 133c-17 6-28-23-9-30 59-18 159-15 221 22 17 9 1 37-17 27-54-32-144-35-195-19zm379 91c-17 0-33-6-47-20-1 0-1 1-1 1l-16 19c-1 1-1 2 0 3 18 16 40 24 64 24 34 0 55-19 55-47 0-24-15-37-50-46-29-7-34-12-34-22s10-16 23-16 25 5 39 15c0 0 1 1 2 1s1-1 1-1l14-20c1-1 1-1 0-2-16-13-35-20-56-20-31 0-53 19-53 46 0 29 20 38 52 46 28 6 32 12 32 22 0 11-10 17-25 17zm95-77v-13c0-1-1-2-2-2h-26c-1 0-2 1-2 2v147c0 1 1 2 2 2h26c1 0 2-1 2-2v-46c10 11 21 16 36 16 27 0 54-21 54-61s-27-60-54-60c-15 0-26 5-36 17zm30 78c-18 0-31-15-31-35s13-34 31-34 30 14 30 34-12 35-30 35zm68-34c0 34 27 60 62 60s62-27 62-61-26-60-61-60-63 27-63 61zm30-1c0-20 13-34 32-34s33 15 33 35-13 34-32 34-33-15-33-35zm140-58v-29c0-1 0-2-1-2h-26c-1 0-2 1-2 2v29h-13c-1 0-2 1-2 2v22c0 1 1 2 2 2h13v58c0 23 11 35 34 35 9 0 18-2 25-6 1 0 1-1 1-2v-21c0-1 0-2-1-2h-2c-5 3-11 4-16 4-8 0-12-4-12-12v-54h30c1 0 2-1 2-2v-22c0-1-1-2-2-2h-30zm129-3c0-11 4-15 13-15 5 0 10 0 15 2h1s1-1 1-2V93c0-1 0-2-1-2-5-2-12-3-22-3-24 0-36 14-36 39v5h-13c-1 0-2 1-2 2v22c0 1 1 2 2 2h13v89c0 1 1 2 2 2h26c1 0 1-1 1-2v-89h25l37 89c-4 9-8 11-14 11-5 0-10-1-15-4h-1l-1 1-9 19c0 1 0 3 1 3 9 5 17 7 27 7 19 0 30-9 39-33l45-116v-2c0-1-1-1-2-1h-27c-1 0-1 1-1 2l-28 78-30-78c0-1-1-2-2-2h-44v-3zm-83 3c-1 0-2 1-2 2v113c0 1 1 2 2 2h26c1 0 1-1 1-2V134c0-1 0-2-1-2h-26zm-6-33c0 10 9 19 19 19s18-9 18-19-8-18-18-18-19 8-19 18zm245 69c10 0 19-8 19-18s-9-18-19-18-18 8-18 18 8 18 18 18zm0-34c9 0 17 7 17 16s-8 16-17 16-16-7-16-16 7-16 16-16zm4 18c3-1 5-3 5-6 0-4-4-6-8-6h-8v19h4v-6h4l4 6h5zm-3-9c2 0 4 1 4 3s-2 3-4 3h-4v-6h4z"></path></svg>
    </div>
    <div class="menu">
        <div class="menu--item">
            <a href="#">
                <i class="lni-home"></i> <span class="menu--item--text">Home</span>
            </a>
        </div>
        <div class="menu--item">
            <a href="#">
                <i class="lni-search"></i> <span class="menu--item--text">Search</span>
            </a>
        </div>
        <div class="menu--item">
            <a href="#">
                <i class="lni-library"></i> <span class="menu--item--text">Library</span>
            </a>
        </div>
    </div>
    <p class="sidebar--header">PLAYLIST</p>
    <div class="menu menu-extra">
        <div class="menu--item">
            <a href="#">
                <img src="http://via.placeholder.com/32x32" alt="">
                <span class="menu--item--text">Create a playlist</span>
            </a>
        </div>
        <div class="menu--item">
            <a href="#">
                <img src="http://via.placeholder.com/32x32" alt="">
                <span class="menu--item--text">Songs that you like</span>
            </a>
        </div>
    </div>
    <div class="separator"></div>
    <div class="menu menu-playlist">
        <div class="menu--item">
            <a href="#">
                <span class="menu--item--text">Dev</span>
            </a>
        </div>
        <div class="menu--item">
            <a href="#">
                <span class="menu--item--text">That playlist that I really liked from the show</span>
            </a>
        </div>
    </div>
    <div class="sidebar--download-app">
        <a href="#">
            <i class="lni-arrow-down-circle"></i> <span>Install the app</span>
        </a>
    </div>
</nav>
```

Without any more css the sidebar looks like the image below:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ok75i7c0uwtug7fvvqw6.png)
<figcaption>8. Left sidebar without css</figcaption>

Now let’s think about the necessary styles.
- the sidebar itself, needs a padding-left and a padding-top.
- the logo needs to have specific width and a padding-bottom ( to create some distance between the logo and the menu items
- the menu items need to have specific font-size, color and height. They also need an active state where a background is applied to them and a hover state where their color changes to a lighter one.

```css
.sidebar {
    background-color: rgba(4, 4, 4);
    padding: 24px 24px 0 24px;
    position: fixed;
    height: 100%;
    width: 230px;
}

.sidebar .brand {
    padding-bottom: 18px;
}

.sidebar .brand svg {
    width: 131px;
}

.sidebar .menu .menu--item {
    font-size: 1.5rem;
    position: relative; /* Needed for the .active state to add the background */
}

.sidebar .menu.menu-extra .menu--item:not(:first-child) {
    margin-top: 5px;
}

.sidebar .menu .menu--item a,
.sidebar .sidebar--download-app a {
    text-decoration: none;
    color: #B3B3B3;
    width: 100%;
    display: flex;
    align-items: center;
    height: 40px;
    transition: all 350ms;
}

.sidebar .menu.menu-extra .menu--item a img {
    opacity: 0.7;
    transition: all 350ms;
}

.sidebar .menu.menu-extra .menu--item:hover a img {
    opacity: 1;
}

.sidebar .menu .menu--item.active a,
.sidebar .menu .menu--item:hover a,
.sidebar .sidebar--download-app:hover a {
    color: #fff;
}
/* Active state of the menu  item, adds a background color to the element */
.sidebar .menu .menu--item.active:before {
    content: ' ';
    position: absolute;
    top: 0;
    height: 100%;
    left: 8px;
    left: -16px; /* -(Sidebar's padding left) + 8px */
    right: -16px; /* -(Sidebar's padding left) + 8px */
    background: rgb(40, 40, 40);
    z-index: -1;
    border-radius: 5px;
}

.menu--item--text,
.sidebar--download-app a span {
    font-size: 0.88rem;
    font-weight: 700;
    margin-left: 15px;
}

.sidebar--header {
    margin-top: 1.5rem;
    margin-bottom: 1.3rem;
    font-size: 0.68rem;
    letter-spacing: 1.5px;
    color: #B3B3B3;
}

.sidebar .separator {
    height: 1px;
    width: 100%;
    border-top: 1px solid #303030;
    margin-top: 16px;
}

.sidebar .menu.menu-playlist .menu--item--text {
    font-weight: 400;
    margin-left: 0;
    /*
        Add ellipsis when the text is bigger than the width of the sidebar
        Read more: https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow
    */
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
}

.sidebar .menu.menu-playlist a {
    cursor: default;
}

.sidebar--download-app {
    position: absolute;
    bottom: 0;
}

```

The current UI looks like this, we can see that it needs changes but it is starting to take shape.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/484f1nhezrlrw8g6nz6y.png)
<figcaption>9. All the UI with the sidebar having correct styling</figcaption>

#Hover animation
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/losbzpdf2zdndaqffoa8.gif)
<figcaption>10. Hover on menu item animation</figcaption>

As shown on the gif when the user hovers over a menu item, the _color_ and the _image_ becomes brighter. The effect is very simple to create and the code responsible for it is the following:

```css
/* Start the menu item with a gray color */
.sidebar .menu .menu--item a,
.sidebar .sidebar--download-app a {
    color: #B3B3B3;
    /*
        All changes will take 350ms to finish. 
        Read More: https://css-tricks.com/almanac/properties/t/transition/
    */
    transition: all 350ms;
}
/* When the user hovers -> change the color */
.sidebar .menu .menu--item.active a,
.sidebar .menu .menu--item:hover a {
    color: #fff;
}
/*
    Changing the opacity of the image gives the brighter effect. This happens because the background is dark.
*/
.sidebar .menu.menu-extra .menu--item a img {
    opacity: 0.7;
    transition: all 350ms;
}

.sidebar .menu.menu-extra .menu--item:hover a img {
    opacity: 1;
}
```

#Wrapping up
I want to keep these posts short and easy to follow, so I will finish this one here. If you have any questions about the post or any suggestions, let me know in the comments 🙂!

In the next post I will style the Top Bar and add two small Javascript interactions.