initial
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Sadee
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
54
README.md
Normal file
@ -0,0 +1,54 @@
|
||||
<div align="center">
|
||||
|
||||

|
||||

|
||||

|
||||
[](https://twitter.com/intent/follow?screen_name=codewithsadee)
|
||||
[](https://youtu.be/jbMd2NVFrZk)
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<h2 align="center">Web Music Player</h2>
|
||||
|
||||
A fully responsive web music player using vanilla javascript, <br />Responsive for all devices, build using html, css, and javascript.
|
||||
|
||||
<a href="https://codewithsadee.github.io/music-player/"><strong>➥ Live Demo</strong></a>
|
||||
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
### Demo Screeshots
|
||||
|
||||

|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before you begin, ensure you have met the following requirements:
|
||||
|
||||
* [Git](https://git-scm.com/downloads "Download Git") must be installed on your operating system.
|
||||
|
||||
### Run Locally
|
||||
|
||||
To run **Music Player** locally, run this command on your git bash:
|
||||
|
||||
Linux and macOS:
|
||||
|
||||
```bash
|
||||
sudo git clone https://github.com/codewithsadee/music-player.git
|
||||
```
|
||||
|
||||
Windows:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/codewithsadee/music-player.git
|
||||
```
|
||||
|
||||
### Contact
|
||||
|
||||
If you want to contact with me you can reach me at [Twitter](https://www.twitter.com/codewithsadee).
|
||||
|
||||
### License
|
||||
|
||||
This project is **free to use** and does not contains any license.
|
683
assets/css/style.css
Normal file
@ -0,0 +1,683 @@
|
||||
/*-----------------------------------*\
|
||||
#style.css
|
||||
\*-----------------------------------*/
|
||||
|
||||
/**
|
||||
* copyright 2022 codewithsadee
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------*\
|
||||
#CUSTOM PROPERTY
|
||||
\*-----------------------------------*/
|
||||
|
||||
:root {
|
||||
|
||||
/**
|
||||
* colors
|
||||
*/
|
||||
|
||||
--eerie-black_a95: hsla(204, 9%, 11%, 0.95);
|
||||
--eerie-black_a50: hsla(204, 9%, 11%, 0.5);
|
||||
--eerie-black: hsl(204, 9%, 11%);
|
||||
--gainsboro: hsl(225, 7%, 89%);
|
||||
--charcoal: hsl(203, 9%, 28%);
|
||||
--silver-sand: hsl(208, 12%, 78%);
|
||||
--light-sky-blue: hsl(200, 100%, 73%);
|
||||
--prussian-blue: hsl(196, 100%, 14%);
|
||||
--black: hsl(0, 0%, 0%);
|
||||
--black_a50: hsla(0, 0%, 0%, 0.5);
|
||||
--black_a20: hsla(0, 0%, 0%, 0.2);
|
||||
--light-sky-blue_a8: hsla(200, 100%, 73%, 0.08);
|
||||
--light-sky-blue_a12: hsla(200, 100%, 73%, 0.12);
|
||||
--silver-sand_a8: hsla(208, 12%, 78%, 0.08);
|
||||
--silver-sand_a12: hsla(208, 12%, 78%, 0.12);
|
||||
|
||||
--background: var(--eerie-black);
|
||||
--background-opacity: var(--eerie-black_a95);
|
||||
--on-background: var(--gainsboro);
|
||||
--surface-variant: var(--charcoal);
|
||||
--on-surface-variant: var(--silver-sand);
|
||||
--on-surface-variant-hover: var(--light-sky-blue_a8);
|
||||
--on-surface-variant-focus: var(--light-sky-blue_a12);
|
||||
--primary: var(--light-sky-blue);
|
||||
--on-primary: var(--prussian-blue);
|
||||
|
||||
/**
|
||||
* gradient
|
||||
*/
|
||||
|
||||
--gradient: linear-gradient(180deg, hsla(204, 9%, 11%, 0.90) 60%, transparent 120%);
|
||||
|
||||
/**
|
||||
* typography
|
||||
*/
|
||||
|
||||
--ff-inter: 'Inter', sans-serif;
|
||||
|
||||
--headline-sm: 2.4rem;
|
||||
--title-lg: 2.2rem;
|
||||
--label-lg: 1.4rem;
|
||||
--label-md: 1.2rem;
|
||||
|
||||
--fw-400: 400;
|
||||
--fw-500: 500;
|
||||
|
||||
/**
|
||||
* box shadow
|
||||
*/
|
||||
|
||||
--shadow-1: 0 1px 4px 1px var(--black_a20);
|
||||
--shadow-2: 0 1px 4px 1px var(--black_a50);
|
||||
|
||||
/**
|
||||
* border radius
|
||||
*/
|
||||
|
||||
--radius-24: 24px;
|
||||
--radius-16: 16px;
|
||||
--radius-12: 12px;
|
||||
--radius-pill: 100px;
|
||||
--radius-circle: 50%;
|
||||
|
||||
/**
|
||||
* transition
|
||||
*/
|
||||
|
||||
--transition-1: 200ms cubic-bezier(0.2, 0, 0, 1);
|
||||
--transition-2: 300ms cubic-bezier(0.2, 0, 0, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------*\
|
||||
#RESET
|
||||
\*-----------------------------------*/
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
li { list-style: none; }
|
||||
|
||||
a,
|
||||
img,
|
||||
span,
|
||||
input,
|
||||
button { display: block; }
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
img { height: auto; }
|
||||
|
||||
input,
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
input { width: 100%; }
|
||||
|
||||
button { cursor: pointer; }
|
||||
|
||||
html {
|
||||
font-family: var(--ff-inter);
|
||||
font-size: 10px;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--black);
|
||||
color: var(--on-background);
|
||||
font-size: 1.6rem;
|
||||
line-height: 1.5;
|
||||
min-height: 100vh;
|
||||
min-width: 250px;
|
||||
background-image: url("../images/poster-1.jpg");
|
||||
background-size: 150%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: top;
|
||||
overflow: overlay;
|
||||
}
|
||||
|
||||
body.modalActive { overflow: hidden; }
|
||||
|
||||
::-webkit-scrollbar { width: 8px; }
|
||||
|
||||
::-webkit-scrollbar-track { background: transparent; }
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
border-radius: var(--radius-pill);
|
||||
}
|
||||
|
||||
body:hover::-webkit-scrollbar-thumb { background-color: var(--surface-variant); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------*\
|
||||
#REUSED STYLE
|
||||
\*-----------------------------------*/
|
||||
|
||||
.material-symbols-rounded {
|
||||
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' -25, 'opsz' 24;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title-lg {
|
||||
font-size: var(--title-lg);
|
||||
font-weight: var(--fw-400);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
color: var(--on-surface-variant);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: var(--radius-circle);
|
||||
}
|
||||
|
||||
.btn-icon:hover { background-color: var(--on-surface-variant-hover); }
|
||||
|
||||
.btn-icon:is(:focus, :focus-visible) {
|
||||
background-color: var(--on-surface-variant-focus);
|
||||
}
|
||||
|
||||
.img-cover {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.headline-sm {
|
||||
font-size: var(--headline-sm);
|
||||
font-weight: var(--fw-400);
|
||||
}
|
||||
|
||||
.label-lg,
|
||||
.label-md { font-weight: var(--fw-500); }
|
||||
|
||||
.label-lg {
|
||||
font-size: var(--label-lg);
|
||||
letter-spacing: 0.1px;
|
||||
}
|
||||
|
||||
.label-md {
|
||||
font-size: var(--label-md);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------*\
|
||||
#TOP APP BAR
|
||||
\*-----------------------------------*/
|
||||
|
||||
.top-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: var(--background-opacity);
|
||||
min-width: 250px;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
padding-inline: 16px;
|
||||
justify-content: space-between;
|
||||
backdrop-filter: blur(50px);
|
||||
box-shadow: var(--shadow-1);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.logo { gap: 12px; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------*\
|
||||
#PLAYER
|
||||
\*-----------------------------------*/
|
||||
|
||||
.volume { display: none; }
|
||||
|
||||
.player {
|
||||
--padding: 24px;
|
||||
background-image: var(--gradient);
|
||||
padding: var(--padding);
|
||||
padding-block-start: calc(64px + var(--padding));
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
backdrop-filter: blur(30px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.player .container {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: 1fr max-content;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.music-banner {
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: var(--surface-variant);
|
||||
max-width: 400px;
|
||||
margin-inline: auto;
|
||||
align-self: center;
|
||||
overflow: hidden;
|
||||
border-radius: var(--radius-24);
|
||||
}
|
||||
|
||||
.label-wrapper {
|
||||
justify-content: center;
|
||||
opacity: 0.8;
|
||||
margin-block: 8px 4px;
|
||||
}
|
||||
|
||||
.label-wrapper span:first-child::after {
|
||||
content: "|";
|
||||
display: inline-block;
|
||||
margin-inline: 4px;
|
||||
}
|
||||
|
||||
.artist {
|
||||
opacity: 0.6;
|
||||
margin-block-end: 36px;
|
||||
}
|
||||
|
||||
.seek-control { margin-block-end: 20px; }
|
||||
|
||||
.range-wrapper { position: relative; }
|
||||
|
||||
.range {
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.range::-webkit-slider-runnable-track {
|
||||
appearance: none;
|
||||
background-color: var(--surface-variant);
|
||||
height: 6px;
|
||||
width: 100%;
|
||||
border-radius: var(--radius-pill);
|
||||
}
|
||||
|
||||
.range-fill {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 6px;
|
||||
background-color: var(--primary);
|
||||
border-radius: var(--radius-pill);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.range::-webkit-slider-thumb {
|
||||
appearance: none;
|
||||
background-color: var(--primary);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-block-start: -5px;
|
||||
border-radius: var(--radius-pill);
|
||||
transition: var(--transition-1);
|
||||
}
|
||||
|
||||
.range::-webkit-slider-thumb:hover {
|
||||
box-shadow: 0 0 0 12px var(--on-surface-variant-hover);
|
||||
}
|
||||
|
||||
.range::-webkit-slider-thumb:is(:focus, :focus-visible) {
|
||||
box-shadow: 0 0 0 12px var(--on-surface-variant-focus);
|
||||
}
|
||||
|
||||
.duration-label {
|
||||
justify-content: space-between;
|
||||
margin-block-start: 12px;
|
||||
}
|
||||
|
||||
.player-control { justify-content: space-evenly; }
|
||||
|
||||
.player-control .toggle.active { color: var(--primary); }
|
||||
|
||||
.player-control .play {
|
||||
background-color: var(--surface-variant);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.player-control .play.active {
|
||||
background-color: var(--primary);
|
||||
color: var(--on-primary);
|
||||
}
|
||||
|
||||
.player-control .btn-icon.active .default-icon,
|
||||
.player-control .btn-icon .active-icon { display: none; }
|
||||
|
||||
.player-control .btn-icon .default-icon,
|
||||
.player-control .btn-icon.active .active-icon { display: block; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------*\
|
||||
#PLAYLIST
|
||||
\*-----------------------------------*/
|
||||
|
||||
.playlist {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: -180px;
|
||||
width: 180px;
|
||||
height: 100vh;
|
||||
background-color: var(--background);
|
||||
padding: 28px;
|
||||
border-top-left-radius: var(--radius-16);
|
||||
border-bottom-left-radius: var(--radius-16);
|
||||
box-shadow: var(--shadow-2);
|
||||
overflow-y: overlay;
|
||||
visibility: hidden;
|
||||
transition: var(--transition-2);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.playlist:hover::-webkit-scrollbar-thumb { background-color: var(--surface-variant); }
|
||||
|
||||
.playlist.active {
|
||||
transform: translateX(-180px);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.music-list {
|
||||
display: grid;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.music-item {
|
||||
position: relative;
|
||||
border-radius: var(--radius-12);
|
||||
background-color: var(--surface-variant);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.music-item .item-icon {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-color: var(--eerie-black_a50);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.music-item.playing .item-icon { opacity: 1; }
|
||||
|
||||
.music-item .item-icon .material-symbols-rounded {
|
||||
color: var(--primary);
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.music-item:is(:hover, :focus-visible, :active, .playing) {
|
||||
outline: 1px solid var(--primary);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: var(--black);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: var(--transition-2);
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.overlay.active {
|
||||
pointer-events: all;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------*\
|
||||
#MEDIA QUERIES
|
||||
\*-----------------------------------*/
|
||||
|
||||
/**
|
||||
* responsive for large than 575px screen
|
||||
*/
|
||||
|
||||
@media (min-width: 575px) {
|
||||
|
||||
/**
|
||||
* RESET
|
||||
*/
|
||||
|
||||
body { background-size: 100%; }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PLAYER
|
||||
*/
|
||||
|
||||
.player { justify-content: center; }
|
||||
|
||||
.player .container { max-width: 540px; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* responsive for large than 992px screen
|
||||
*/
|
||||
|
||||
@media (min-width: 992px) {
|
||||
|
||||
/**
|
||||
* CUSTOM PROPERTY
|
||||
*/
|
||||
|
||||
:root {
|
||||
|
||||
/**
|
||||
* typography
|
||||
*/
|
||||
|
||||
--headline-sm: 4.2rem;
|
||||
--label-lg: 2.2rem;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* RESET
|
||||
*/
|
||||
|
||||
body {
|
||||
background-size: 40% 100%;
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
article { display: flex; }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* REUSED STYLE
|
||||
*/
|
||||
|
||||
.btn-icon {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
}
|
||||
|
||||
.btn-icon .material-symbols-rounded { font-size: 2.8rem; }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* TOP APP BAR
|
||||
*/
|
||||
|
||||
.top-bar-actions { display: none; }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PLAYER
|
||||
*/
|
||||
|
||||
.player {
|
||||
--padding: 48px;
|
||||
text-align: left;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
backdrop-filter: blur(100px);
|
||||
}
|
||||
|
||||
.player .container {
|
||||
max-width: 1200px;
|
||||
grid-template-columns: 0.8fr 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
gap: 48px;
|
||||
max-height: 500px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.music-banner {
|
||||
aspect-ratio: unset;
|
||||
max-width: max-content;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.music-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-block-start: 48px;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.music-content :is(.headline-sm, .label-lg, .label-md) {
|
||||
max-width: 85%;
|
||||
}
|
||||
|
||||
.label-wrapper {
|
||||
justify-content: flex-start;
|
||||
margin-block-end: 8px;
|
||||
}
|
||||
|
||||
.artist { --label-md: 1.8rem; }
|
||||
|
||||
.seek-control {
|
||||
margin-block-start: auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 150px;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.volume {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-block-start: -30px;
|
||||
}
|
||||
|
||||
.volume .btn-icon { flex-shrink: 0; }
|
||||
|
||||
.volume .range-fill { width: 100%; }
|
||||
|
||||
.player-control {
|
||||
margin-inline-end: 174px;
|
||||
min-width: max-content;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PLAYLIST
|
||||
*/
|
||||
|
||||
.overlay { display: none; }
|
||||
|
||||
.playlist {
|
||||
position: static;
|
||||
visibility: visible;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.playlist.active { transform: unset; }
|
||||
|
||||
.music-item:is(:hover, :focus-visible, :active, .playing) {
|
||||
outline: 2px solid var(--primary);
|
||||
}
|
||||
|
||||
.music-item .item-icon .material-symbols-rounded {
|
||||
font-size: 3.6rem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* responsive for large than 1200px screen
|
||||
*/
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
|
||||
/**
|
||||
* PLAYLIST
|
||||
*/
|
||||
|
||||
.playlist {
|
||||
padding: 32px;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.music-list { gap: 28px; }
|
||||
|
||||
}
|
BIN
assets/images/Thumbs.db
Normal file
BIN
assets/images/poster-1.jpg
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
assets/images/poster-2.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
assets/images/poster-3.jpg
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
assets/images/poster-4.jpg
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
assets/images/poster-5.jpg
Normal file
After Width: | Height: | Size: 64 KiB |
410
assets/js/script.js
Normal file
@ -0,0 +1,410 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* all music information
|
||||
*/
|
||||
|
||||
const musicData = [
|
||||
{
|
||||
backgroundImage: "./assets/images/poster-1.jpg",
|
||||
posterUrl: "./assets/images/poster-1.jpg",
|
||||
title: "Happy Moments (Master)",
|
||||
album: "No Spirit",
|
||||
year: 2022,
|
||||
artist: "No Spirit x Tonion",
|
||||
musicPath: "./assets/music/music-1.mp3",
|
||||
},
|
||||
{
|
||||
backgroundImage: "./assets/images/poster-2.jpg",
|
||||
posterUrl: "./assets/images/poster-2.jpg",
|
||||
title: "We Are Going To Be Ok (Master)",
|
||||
album: "No Spirit",
|
||||
year: 2022,
|
||||
artist: "No Spirit x Jhove",
|
||||
musicPath: "./assets/music/music-2.mp3",
|
||||
},
|
||||
{
|
||||
backgroundImage: "./assets/images/poster-3.jpg",
|
||||
posterUrl: "./assets/images/poster-3.jpg",
|
||||
title: "Winter Meadow",
|
||||
album: "No Spirit",
|
||||
year: 2022,
|
||||
artist: "No Spirit x juniorodeo",
|
||||
musicPath: "./assets/music/music-3.mp3",
|
||||
},
|
||||
{
|
||||
backgroundImage: "./assets/images/poster-4.jpg",
|
||||
posterUrl: "./assets/images/poster-4.jpg",
|
||||
title: "From Where We Started",
|
||||
album: "No Spirit",
|
||||
year: 2022,
|
||||
artist: "No Spirit",
|
||||
musicPath: "./assets/music/music-4.mp3",
|
||||
},
|
||||
{
|
||||
backgroundImage: "./assets/images/poster-5.jpg",
|
||||
posterUrl: "./assets/images/poster-5.jpg",
|
||||
title: "Where I Found You",
|
||||
album: "No Spirit",
|
||||
year: 2022,
|
||||
artist: "No Spirit",
|
||||
musicPath: "./assets/music/music-5.mp3",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* add eventListnere on all elements that are passed
|
||||
*/
|
||||
|
||||
const addEventOnElements = function (elements, eventType, callback) {
|
||||
for (let i = 0, len = elements.length; i < len; i++) {
|
||||
elements[i].addEventListener(eventType, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PLAYLIST
|
||||
*
|
||||
* add all music in playlist, from 'musicData'
|
||||
*/
|
||||
|
||||
const playlist = document.querySelector("[data-music-list]");
|
||||
|
||||
for (let i = 0, len = musicData.length; i < len; i++) {
|
||||
playlist.innerHTML += `
|
||||
<li>
|
||||
<button class="music-item ${i === 0 ? "playing" : ""}" data-playlist-toggler data-playlist-item="${i}">
|
||||
<img src="${musicData[i].posterUrl}" width="800" height="800" alt="${musicData[i].title} Album Poster"
|
||||
class="img-cover">
|
||||
|
||||
<div class="item-icon">
|
||||
<span class="material-symbols-rounded">equalizer</span>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PLAYLIST MODAL SIDEBAR TOGGLE
|
||||
*
|
||||
* show 'playlist' modal sidebar when click on playlist button in top app bar
|
||||
* and hide when click on overlay or any playlist-item
|
||||
*/
|
||||
|
||||
const playlistSideModal = document.querySelector("[data-playlist]");
|
||||
const playlistTogglers = document.querySelectorAll("[data-playlist-toggler]");
|
||||
const overlay = document.querySelector("[data-overlay]");
|
||||
|
||||
const togglePlaylist = function () {
|
||||
playlistSideModal.classList.toggle("active");
|
||||
overlay.classList.toggle("active");
|
||||
document.body.classList.toggle("modalActive");
|
||||
}
|
||||
|
||||
addEventOnElements(playlistTogglers, "click", togglePlaylist);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PLAYLIST ITEM
|
||||
*
|
||||
* remove active state from last time played music
|
||||
* and add active state in clicked music
|
||||
*/
|
||||
|
||||
const playlistItems = document.querySelectorAll("[data-playlist-item]");
|
||||
|
||||
let currentMusic = 0;
|
||||
let lastPlayedMusic = 0;
|
||||
|
||||
const changePlaylistItem = function () {
|
||||
playlistItems[lastPlayedMusic].classList.remove("playing");
|
||||
playlistItems[currentMusic].classList.add("playing");
|
||||
}
|
||||
|
||||
addEventOnElements(playlistItems, "click", function () {
|
||||
lastPlayedMusic = currentMusic;
|
||||
currentMusic = Number(this.dataset.playlistItem);
|
||||
changePlaylistItem();
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PLAYER
|
||||
*
|
||||
* change all visual information on player, based on current music
|
||||
*/
|
||||
|
||||
const playerBanner = document.querySelector("[data-player-banner]");
|
||||
const playerTitle = document.querySelector("[data-title]");
|
||||
const playerAlbum = document.querySelector("[data-album]");
|
||||
const playerYear = document.querySelector("[data-year]");
|
||||
const playerArtist = document.querySelector("[data-artist]");
|
||||
|
||||
const audioSource = new Audio(musicData[currentMusic].musicPath);
|
||||
|
||||
const changePlayerInfo = function () {
|
||||
playerBanner.src = musicData[currentMusic].posterUrl;
|
||||
playerBanner.setAttribute("alt", `${musicData[currentMusic].title} Album Poster`);
|
||||
document.body.style.backgroundImage = `url(${musicData[currentMusic].backgroundImage})`;
|
||||
playerTitle.textContent = musicData[currentMusic].title;
|
||||
playerAlbum.textContent = musicData[currentMusic].album;
|
||||
playerYear.textContent = musicData[currentMusic].year;
|
||||
playerArtist.textContent = musicData[currentMusic].artist;
|
||||
|
||||
audioSource.src = musicData[currentMusic].musicPath;
|
||||
|
||||
audioSource.addEventListener("loadeddata", updateDuration);
|
||||
playMusic();
|
||||
}
|
||||
|
||||
addEventOnElements(playlistItems, "click", changePlayerInfo);
|
||||
|
||||
/** update player duration */
|
||||
const playerDuration = document.querySelector("[data-duration]");
|
||||
const playerSeekRange = document.querySelector("[data-seek]");
|
||||
|
||||
/** pass seconds and get timcode formate */
|
||||
const getTimecode = function (duration) {
|
||||
const minutes = Math.floor(duration / 60);
|
||||
const seconds = Math.ceil(duration - (minutes * 60));
|
||||
const timecode = `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
|
||||
return timecode;
|
||||
}
|
||||
|
||||
const updateDuration = function () {
|
||||
playerSeekRange.max = Math.ceil(audioSource.duration);
|
||||
playerDuration.textContent = getTimecode(Number(playerSeekRange.max));
|
||||
}
|
||||
|
||||
audioSource.addEventListener("loadeddata", updateDuration);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* PLAY MUSIC
|
||||
*
|
||||
* play and pause music when click on play button
|
||||
*/
|
||||
|
||||
const playBtn = document.querySelector("[data-play-btn]");
|
||||
|
||||
let playInterval;
|
||||
|
||||
const playMusic = function () {
|
||||
if (audioSource.paused) {
|
||||
audioSource.play();
|
||||
playBtn.classList.add("active");
|
||||
playInterval = setInterval(updateRunningTime, 500);
|
||||
} else {
|
||||
audioSource.pause();
|
||||
playBtn.classList.remove("active");
|
||||
clearInterval(playInterval);
|
||||
}
|
||||
}
|
||||
|
||||
playBtn.addEventListener("click", playMusic);
|
||||
|
||||
|
||||
/** update running time while playing music */
|
||||
|
||||
const playerRunningTime = document.querySelector("[data-running-time");
|
||||
|
||||
const updateRunningTime = function () {
|
||||
playerSeekRange.value = audioSource.currentTime;
|
||||
playerRunningTime.textContent = getTimecode(audioSource.currentTime);
|
||||
|
||||
updateRangeFill();
|
||||
isMusicEnd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* RANGE FILL WIDTH
|
||||
*
|
||||
* change 'rangeFill' width, while changing range value
|
||||
*/
|
||||
|
||||
const ranges = document.querySelectorAll("[data-range]");
|
||||
const rangeFill = document.querySelector("[data-range-fill]");
|
||||
|
||||
const updateRangeFill = function () {
|
||||
let element = this || ranges[0];
|
||||
|
||||
const rangeValue = (element.value / element.max) * 100;
|
||||
element.nextElementSibling.style.width = `${rangeValue}%`;
|
||||
}
|
||||
|
||||
addEventOnElements(ranges, "input", updateRangeFill);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SEEK MUSIC
|
||||
*
|
||||
* seek music while changing player seek range
|
||||
*/
|
||||
|
||||
const seek = function () {
|
||||
audioSource.currentTime = playerSeekRange.value;
|
||||
playerRunningTime.textContent = getTimecode(playerSeekRange.value);
|
||||
}
|
||||
|
||||
playerSeekRange.addEventListener("input", seek);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* END MUSIC
|
||||
*/
|
||||
|
||||
const isMusicEnd = function () {
|
||||
if (audioSource.ended) {
|
||||
playBtn.classList.remove("active");
|
||||
audioSource.currentTime = 0;
|
||||
playerSeekRange.value = audioSource.currentTime;
|
||||
playerRunningTime.textContent = getTimecode(audioSource.currentTime);
|
||||
updateRangeFill();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SKIP TO NEXT MUSIC
|
||||
*/
|
||||
|
||||
const playerSkipNextBtn = document.querySelector("[data-skip-next]");
|
||||
|
||||
const skipNext = function () {
|
||||
lastPlayedMusic = currentMusic;
|
||||
|
||||
if (isShuffled) {
|
||||
shuffleMusic();
|
||||
} else {
|
||||
currentMusic >= musicData.length - 1 ? currentMusic = 0 : currentMusic++;
|
||||
}
|
||||
|
||||
changePlayerInfo();
|
||||
changePlaylistItem();
|
||||
}
|
||||
|
||||
playerSkipNextBtn.addEventListener("click", skipNext);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SKIP TO PREVIOUS MUSIC
|
||||
*/
|
||||
|
||||
const playerSkipPrevBtn = document.querySelector("[data-skip-prev]");
|
||||
|
||||
const skipPrev = function () {
|
||||
lastPlayedMusic = currentMusic;
|
||||
|
||||
if (isShuffled) {
|
||||
shuffleMusic();
|
||||
} else {
|
||||
currentMusic <= 0 ? currentMusic = musicData.length - 1 : currentMusic--;
|
||||
}
|
||||
|
||||
changePlayerInfo();
|
||||
changePlaylistItem();
|
||||
}
|
||||
|
||||
playerSkipPrevBtn.addEventListener("click", skipPrev);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SHUFFLE MUSIC
|
||||
*/
|
||||
|
||||
/** get random number for shuffle */
|
||||
const getRandomMusic = () => Math.floor(Math.random() * musicData.length);
|
||||
|
||||
const shuffleMusic = () => currentMusic = getRandomMusic();
|
||||
|
||||
const playerShuffleBtn = document.querySelector("[data-shuffle]");
|
||||
let isShuffled = false;
|
||||
|
||||
const shuffle = function () {
|
||||
playerShuffleBtn.classList.toggle("active");
|
||||
|
||||
isShuffled = isShuffled ? false : true;
|
||||
}
|
||||
|
||||
playerShuffleBtn.addEventListener("click", shuffle);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* REPEAT MUSIC
|
||||
*/
|
||||
|
||||
const playerRepeatBtn = document.querySelector("[data-repeat]");
|
||||
|
||||
const repeat = function () {
|
||||
if (!audioSource.loop) {
|
||||
audioSource.loop = true;
|
||||
this.classList.add("active");
|
||||
} else {
|
||||
audioSource.loop = false;
|
||||
this.classList.remove("active");
|
||||
}
|
||||
}
|
||||
|
||||
playerRepeatBtn.addEventListener("click", repeat);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* MUSIC VOLUME
|
||||
*
|
||||
* increase or decrease music volume when change the volume range
|
||||
*/
|
||||
|
||||
const playerVolumeRange = document.querySelector("[data-volume]");
|
||||
const playerVolumeBtn = document.querySelector("[data-volume-btn]");
|
||||
|
||||
const changeVolume = function () {
|
||||
audioSource.volume = playerVolumeRange.value;
|
||||
audioSource.muted = false;
|
||||
|
||||
if (audioSource.volume <= 0.1) {
|
||||
playerVolumeBtn.children[0].textContent = "volume_mute";
|
||||
} else if (audioSource.volume <= 0.5) {
|
||||
playerVolumeBtn.children[0].textContent = "volume_down";
|
||||
} else {
|
||||
playerVolumeBtn.children[0].textContent = "volume_up";
|
||||
}
|
||||
}
|
||||
|
||||
playerVolumeRange.addEventListener("input", changeVolume);
|
||||
|
||||
|
||||
/**
|
||||
* MUTE MUSIC
|
||||
*/
|
||||
|
||||
const muteVolume = function () {
|
||||
if (!audioSource.muted) {
|
||||
audioSource.muted = true;
|
||||
playerVolumeBtn.children[0].textContent = "volume_off";
|
||||
} else {
|
||||
changeVolume();
|
||||
}
|
||||
}
|
||||
|
||||
playerVolumeBtn.addEventListener("click", muteVolume);
|
BIN
assets/music/music-1.mp3
Normal file
BIN
assets/music/music-2.mp3
Normal file
BIN
assets/music/music-3.mp3
Normal file
BIN
assets/music/music-4.mp3
Normal file
BIN
assets/music/music-5.mp3
Normal file
4
favicon.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="100" height="100" rx="20" fill="#1E1A1C"/>
|
||||
<path d="M34.2812 73C33.4687 73 32.7969 72.7344 32.2656 72.2031C31.7344 71.6719 31.4688 71 31.4688 70.1875V30.8125C31.4688 30 31.7344 29.3281 32.2656 28.7969C32.7969 28.2656 33.4687 28 34.2812 28C35.0938 28 35.7656 28.2656 36.2969 28.7969C36.8281 29.3281 37.0938 30 37.0938 30.8125V70.1875C37.0938 71 36.8281 71.6719 36.2969 72.2031C35.7656 72.7344 35.0938 73 34.2812 73ZM49.75 88C48.9375 88 48.2656 87.7344 47.7344 87.2031C47.2031 86.6719 46.9375 86 46.9375 85.1875V15.8125C46.9375 15 47.2031 14.3281 47.7344 13.7969C48.2656 13.2656 48.9375 13 49.75 13C50.5625 13 51.2344 13.2656 51.7656 13.7969C52.2969 14.3281 52.5625 15 52.5625 15.8125V85.1875C52.5625 86 52.2969 86.6719 51.7656 87.2031C51.2344 87.7344 50.5625 88 49.75 88ZM18.8125 58C18 58 17.3281 57.7344 16.7969 57.2031C16.2656 56.6719 16 56 16 55.1875V45.8125C16 45 16.2656 44.3281 16.7969 43.7969C17.3281 43.2656 18 43 18.8125 43C19.625 43 20.2969 43.2656 20.8281 43.7969C21.3594 44.3281 21.625 45 21.625 45.8125V55.1875C21.625 56 21.3594 56.6719 20.8281 57.2031C20.2969 57.7344 19.625 58 18.8125 58ZM65.2188 73C64.4062 73 63.7344 72.7344 63.2031 72.2031C62.6719 71.6719 62.4062 71 62.4062 70.1875V30.8125C62.4062 30 62.6719 29.3281 63.2031 28.7969C63.7344 28.2656 64.4062 28 65.2188 28C66.0313 28 66.7031 28.2656 67.2344 28.7969C67.7656 29.3281 68.0312 30 68.0312 30.8125V70.1875C68.0312 71 67.7656 71.6719 67.2344 72.2031C66.7031 72.7344 66.0313 73 65.2188 73ZM80.6875 58C79.875 58 79.2031 57.7344 78.6719 57.2031C78.1406 56.6719 77.875 56 77.875 55.1875V45.8125C77.875 45 78.1406 44.3281 78.6719 43.7969C79.2031 43.2656 79.875 43 80.6875 43C81.5 43 82.1719 43.2656 82.7031 43.7969C83.2344 44.3281 83.5 45 83.5 45.8125V55.1875C83.5 56 83.2344 56.6719 82.7031 57.2031C82.1719 57.7344 81.5 58 80.6875 58Z" fill="#FF007A"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
185
index.html
Normal file
@ -0,0 +1,185 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!--
|
||||
- primary meta tags
|
||||
-->
|
||||
<title>Music Player</title>
|
||||
<meta name="title" content="Music Player">
|
||||
<meta name="description" content="A web music player html template made by codewithsadee">
|
||||
|
||||
<!--
|
||||
- favicon
|
||||
-->
|
||||
<link rel="shortcut icon" href="./favicon.svg" type="image/svg+xml">
|
||||
|
||||
<!--
|
||||
- google font link
|
||||
-->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap" rel="stylesheet">
|
||||
|
||||
<!--
|
||||
- material icon font
|
||||
-->
|
||||
<link rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,400,0,-25" />
|
||||
|
||||
<!--
|
||||
- custom css link
|
||||
-->
|
||||
<link rel="stylesheet" href="./assets/css/style.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!--
|
||||
- #TOP APP BAR
|
||||
-->
|
||||
|
||||
<div class="top-bar wrapper">
|
||||
|
||||
<div class="logo wrapper">
|
||||
<span class="material-symbols-rounded">graphic_eq</span>
|
||||
|
||||
<h1 class="title-lg">Music Player</h1>
|
||||
</div>
|
||||
|
||||
<div class="top-bar-actions">
|
||||
<button class="btn-icon" data-playlist-toggler>
|
||||
<span class="material-symbols-rounded">queue_music</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<main>
|
||||
<article>
|
||||
|
||||
<!--
|
||||
- #PLAYER
|
||||
-->
|
||||
|
||||
<div class="player">
|
||||
<div class="container">
|
||||
|
||||
<figure class="music-banner">
|
||||
<img src="./assets/images/poster-1.jpg" width="800" height="800" alt="Happy Moments (Master) Album Poster"
|
||||
class="img-cover" data-player-banner>
|
||||
</figure>
|
||||
|
||||
<div class="music-content">
|
||||
|
||||
<h2 class="headline-sm" data-title>Happy Moments (Master)</h2>
|
||||
|
||||
<p class="label-lg label-wrapper wrapper">
|
||||
<span data-album>No Spirit</span>
|
||||
|
||||
<span data-year>2022</span>
|
||||
</p>
|
||||
|
||||
<p class="label-md artist" data-artist>No Spirit x Tonion</p>
|
||||
|
||||
<div class="seek-control">
|
||||
|
||||
<div>
|
||||
<div class="range-wrapper">
|
||||
<input type="range" step="1" max="60" value="0" class="range" data-range data-seek>
|
||||
|
||||
<div class="range-fill" data-range-fill></div>
|
||||
</div>
|
||||
|
||||
<div class="duration-label wrapper">
|
||||
<span class="label-md" data-running-time>0:00</span>
|
||||
|
||||
<span class="label-md" data-duration>1:00</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="volume">
|
||||
<button class="btn-icon" data-volume-btn>
|
||||
<span class="material-symbols-rounded">volume_up</span>
|
||||
</button>
|
||||
|
||||
<div class="range-wrapper">
|
||||
<input type="range" step="0.05" max="1" value="1" class="range" data-range data-volume>
|
||||
|
||||
<div class="range-fill" data-range-fill></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="player-control wrapper">
|
||||
|
||||
<button class="btn-icon toggle" data-repeat>
|
||||
<span class="material-symbols-rounded default-icon">repeat</span>
|
||||
<span class="material-symbols-rounded active-icon">repeat_one</span>
|
||||
</button>
|
||||
|
||||
<button class="btn-icon" data-skip-prev>
|
||||
<span class="material-symbols-rounded">skip_previous</span>
|
||||
</button>
|
||||
|
||||
<button class="btn-icon play" data-play-btn>
|
||||
<span class="material-symbols-rounded default-icon">play_arrow</span>
|
||||
<span class="material-symbols-rounded active-icon">pause</span>
|
||||
</button>
|
||||
|
||||
<button class="btn-icon" data-skip-next>
|
||||
<span class="material-symbols-rounded">skip_next</span>
|
||||
</button>
|
||||
|
||||
<button class="btn-icon toggle" data-shuffle>
|
||||
<span class="material-symbols-rounded">shuffle</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
- #PLAYLIST
|
||||
-->
|
||||
|
||||
<div class="playlist" data-playlist>
|
||||
|
||||
<ul class="music-list" data-music-list></ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="overlay" data-playlist-toggler data-overlay></div>
|
||||
|
||||
</article>
|
||||
</main>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
- custom js link
|
||||
-->
|
||||
<script src="./assets/js/script.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
51
index.txt
Normal file
@ -0,0 +1,51 @@
|
||||
Music Player
|
||||
|
||||
A web music player html template made by codewithsadee
|
||||
|
||||
|
||||
|
||||
#---------- TOP APP BAR ----------#
|
||||
|
||||
<span class="material-symbols-rounded">graphic_eq</span>
|
||||
|
||||
Music Player
|
||||
|
||||
<span class="material-symbols-rounded">queue_music</span>
|
||||
|
||||
|
||||
|
||||
#---------- PLAYER ----------#
|
||||
|
||||
alt = Happy Moments (Master) Album Poster
|
||||
|
||||
Happy Moments (Master)
|
||||
|
||||
No Spirit
|
||||
2022
|
||||
|
||||
No Spirit x Tonion
|
||||
|
||||
0:00
|
||||
1:00
|
||||
|
||||
<span class="material-symbols-rounded">volume_up</span>
|
||||
|
||||
<span class="material-symbols-rounded">repeat</span>
|
||||
<span class="material-symbols-rounded active-icon">repeat_one</span>
|
||||
|
||||
<span class="material-symbols-rounded">skip_previous</span>
|
||||
|
||||
<span class="material-symbols-rounded">play_arrow</span>
|
||||
<span class="material-symbols-rounded active-icon">pause</span>
|
||||
|
||||
<span class="material-symbols-rounded">skip_next</span>
|
||||
|
||||
<span class="material-symbols-rounded">shuffle</span>
|
||||
|
||||
|
||||
|
||||
#---------- PLAYLIST ----------#
|
||||
|
||||
alt = Happy Moments (Master) Album Poster
|
||||
|
||||
<span class="material-symbols-rounded">equalizer</span>
|
BIN
readme-images/desktop.png
Normal file
After Width: | Height: | Size: 108 KiB |
93
style-guide.md
Normal file
@ -0,0 +1,93 @@
|
||||
# Essential Stuff
|
||||
|
||||
## Html import links
|
||||
|
||||
Google font
|
||||
|
||||
``` html
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap" rel="stylesheet">
|
||||
```
|
||||
|
||||
Material icon
|
||||
|
||||
``` html
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,400,0,-25" />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Colors
|
||||
|
||||
``` css
|
||||
--eerie-black_a95: hsla(204, 9%, 11%, 0.95);
|
||||
--eerie-black_a50: hsla(204, 9%, 11%, 0.5);
|
||||
--eerie-black: hsl(204, 9%, 11%);
|
||||
--gainsboro: hsl(225, 7%, 89%);
|
||||
--charcoal: hsl(203, 9%, 28%);
|
||||
--silver-sand: hsl(208, 12%, 78%);
|
||||
--light-sky-blue: hsl(200, 100%, 73%);
|
||||
--prussian-blue: hsl(196, 100%, 14%);
|
||||
--black: hsl(0, 0%, 0%);
|
||||
--black_a50: hsla(0, 0%, 0%, 0.5);
|
||||
--black_a20: hsla(0, 0%, 0%, 0.2);
|
||||
--light-sky-blue_a8: hsla(200, 100%, 73%, 0.08);
|
||||
--light-sky-blue_a12: hsla(200, 100%, 73%, 0.12);
|
||||
--silver-sand_a8: hsla(208, 12%, 78%, 0.08);
|
||||
--silver-sand_a12: hsla(208, 12%, 78%, 0.12);
|
||||
|
||||
--background: var(--eerie-black);
|
||||
--background-opacity: var(--eerie-black_a95);
|
||||
--on-background: var(--gainsboro);
|
||||
--surface-variant: var(--charcoal);
|
||||
--on-surface-variant: var(--silver-sand);
|
||||
--on-surface-variant-hover: var(--light-sky-blue_a8);
|
||||
--on-surface-variant-focus: var(--light-sky-blue_a12);
|
||||
--primary: var(--light-sky-blue);
|
||||
--on-primary: var(--prussian-blue);
|
||||
```
|
||||
|
||||
## Gradient color
|
||||
|
||||
``` css
|
||||
--gradient: linear-gradient(180deg, hsla(204, 9%, 11%, 0.90) 60%, transparent 120%);
|
||||
```
|
||||
|
||||
## Typography
|
||||
|
||||
``` css
|
||||
--ff-inter: 'Inter', sans-serif;
|
||||
|
||||
--headline-sm: 2.4rem;
|
||||
--title-lg: 2.2rem;
|
||||
--label-lg: 1.4rem;
|
||||
--label-md: 1.2rem;
|
||||
|
||||
--fw-400: 400;
|
||||
--fw-500: 500;
|
||||
```
|
||||
|
||||
## Shadow
|
||||
|
||||
``` css
|
||||
--shadow-1: 0 1px 4px 1px var(--black_a20);
|
||||
--shadow-2: 0 1px 4px 1px var(--black_a50);
|
||||
```
|
||||
|
||||
## Border Radius
|
||||
|
||||
``` css
|
||||
--radius-24: 24px;
|
||||
--radius-16: 16px;
|
||||
--radius-12: 12px;
|
||||
--radius-pill: 100px;
|
||||
--radius-circle: 50%;
|
||||
```
|
||||
|
||||
## Transition
|
||||
|
||||
``` css
|
||||
--transition-1: 200ms cubic-bezier(0.2, 0, 0, 1);
|
||||
--transition-2: 300ms cubic-bezier(0.2, 0, 0, 1);
|
||||
```
|