Skip to content

Instantly share code, notes, and snippets.

@tsanak
Created February 26, 2020 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsanak/0ea7df18c4db04c4f1e37105562b56a7 to your computer and use it in GitHub Desktop.
Save tsanak/0ea7df18c4db04c4f1e37105562b56a7 to your computer and use it in GitHub Desktop.
Recreate Spotify PART 2 [Create top bar and add some javascript]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://cdn.lineicons.com/1.0.1/LineIcons.min.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap" rel="stylesheet">
<title>Recreated: Spotify</title>
<style>
html {
font-size: 16px;
}
body {
margin: 0;
color: #fff;
}
* {
box-sizing: border-box;
font-family: 'Open Sans', sans-serif;
letter-spacing: -0.35px;
}
::root {
--main-color: #1db954;
--light-color: #1ed760;
}
.text-bold {
font-weight: 700;
}
.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: 24px;
margin-bottom: 20px;
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;
}
.header {
position: fixed;
top: 0;
left: 230px; /* sidebar width */
right: 0;
height: 60px;
padding-left: 24px;
padding-right: 24px;
display: flex;
justify-content: space-between;
align-items: center;
z-index:1;
}
.header--bg {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
opacity: 0;
background-color: rgb(18, 18, 18);
z-index: 0;
}
.header--buttons {
position: relative;
}
.header--button {
background: rgb(7, 7, 7);
color: #fff;
border: 0;
border-radius: 50%;
height: 34px;
width: 34px;
cursor: pointer;
outline: 0;
}
.header--button.previous {
margin-right: 10px;
}
.dropdown {
position: relative;
}
.dropdown--button {
outline: 0;
border: 0;
color: #fff;
border-radius: 20px;
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgb(45, 45, 45);
padding: 6px 14px 6px 8px;
font-size: 0.75rem;
line-height: 0.75rem;
cursor: pointer;
user-select: none;
box-shadow: 0px 3px 3px 1px rgba(0, 0, 0, 0.5);
}
.dropdown--button:hover,
.dropdown.open .dropdown--content li:hover {
background-color: rgb(49, 49, 49);
color: #fff;
}
.header .dropdown--button span:not(:last-child) {
margin-right: 10px;
}
.header .dropdown--button .user-icon {
font-size: 1.3rem;
}
.dropdown--content {
display: none;
position: absolute;
list-style: none;
right: 0;
margin: 10px 0 0 0;
padding: 0;
width: 160px;
background-color: rgb(40, 40, 40);
border-radius: 5px;
box-shadow: 0px 3px 3px 1px rgba(0, 0, 0, 0.5);
}
.dropdown.open .dropdown--content {
display: block;
}
.dropdown .dropdown--content li {
padding-left: 40px;
font-size: 0.9rem;
border-bottom: 1px solid rgb(64, 64, 64);
color: #b3b3b3;
user-select: none;
height: 40px;
line-height: 40px;
}
.dropdown .dropdown--content li:first-child {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.dropdown .dropdown--content li:last-child {
border-bottom: 0;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
main {
padding: 80px 32px 32px 262px;
max-height: 100vh;
min-height: 100vh;
background: dodgerblue;
overflow-y: auto;
/* background-color: rgb(18, 18, 18); */
}
main::-webkit-scrollbar {
width: 16px;
}
main::-webkit-scrollbar-thumb {
background-color: #909090;
}
main::-webkit-scrollbar-track {
background-color: rgb(18, 18, 18);
}
</style>
</head>
<body>
<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 main-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>
<div class="header">
<div class="header--bg"></div>
<div class="header--buttons">
<button class="header--button previous"><i class="lni-chevron-left"></i></button>
<button class="header--button next"><i class="lni-chevron-right"></i></button>
</div>
<div class="dropdown">
<button class="dropdown--button">
<span class="user-icon"><i class="lni-user"></i></span>
<span class="text-bold">username</span>
<span><i class="lni-chevron-down"></i></span>
</button>
<ul class="dropdown--content">
<li>Account</li>
<li>Logout</li>
</ul>
</div>
</div>
<main>
<div style="min-height: 200vh"></div>
</main>
<script>
document.addEventListener("DOMContentLoaded",() => {
/* Catch user click event on anywhere on the page */
document.querySelector('body').addEventListener('click', e => {
/* Close all the dropdowns */
document.querySelectorAll('.dropdown.open').forEach(item => {
item.classList.remove('open');
});
});
/* Get all the dropdowns in the page */
document.querySelectorAll('.dropdown').forEach(item => {
/*
When user clicks on a dropdown => then toggle the .open class.
.open class is responsible for opening / closing a dropdown
*/
item.addEventListener('click', e => {
e.preventDefault();
e.stopPropagation();
/* Find the closest dropdown */
const dropdown = e.target.closest('.dropdown');
if(!dropdown) return;
if (dropdown.classList.contains('open')) {
dropdown.classList.remove('open');
} else {
dropdown.classList.add('open');
}
});
});
/* Get all the left sidebar's menu items */
document.querySelectorAll('.main-menu .menu--item').forEach(item => {
/*
When user clicks on a menu item => then toggle the .active class.
.active class is responsible for adding the background to the menu--item
*/
item.addEventListener('click', e => {
e.preventDefault();
const menu_item = e.target.closest('.menu--item');
if(!menu_item) return;
/* Remove all the active menu--items */
document.querySelectorAll('.main-menu .menu--item').forEach(item => {
item.classList.remove('active');
});
/* "Activate" the click menu--item */
menu_item.classList.add('active');
});
});
const headerHeight = document.querySelector('.header').offsetHeight;
const opaqueThreshold = (headerHeight * 2);
const _main_el = document.querySelector('main');
_main_el.addEventListener('scroll', (e) => {
/* Get the vertical scroll position of the 'main' element */
const scrollTop = _main_el.scrollTop;
const _header_bg_el = document.querySelector('.header--bg');
/*
Set the opacity of the top bar
depending on the current scroll position
of the main element
*/
const opacity = scrollTop / opaqueThreshold;
if(opacity > 1) opacity = 1;
_header_bg_el.style.opacity = opacity;
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment