)<div class="api">
<div class="container">πβ‘This demo needs a YouTube API key to work. <a target="_blank" href="https://console.cloud.google.com/">Get yours here for free!</a>
</div>
</div>
<section class="top-banner">
<div class="container">
<div class="text">
<h1>Simple App With the YouTube API</h1>
<p class="label">Use <mark>UC8lxnUR_CzruT2KA6cb7p0Q</mark> for testing (the Envato Tuts+ channel ID)</p>
</div>
<form>
<input type="search" minlength="24" maxlength="24" placeholder="Insert a valid YT channel ID" autofocus required>
<button type="submit">SUBMIT</button>
<span class="msg"></span>
</form>
</div>
</section>
<footer class="page-footer">
<span>made by </span>
<a href="https://georgemartsoukos.com/" target="_blank">
<img width="24" height="24" src="https://assets.codepen.io/162656/george-martsoukos-small-logo.svg" alt="George Martsoukos logo">
</a>
</footer>
/* RESET & BASIC STYLES
ββββββββββββββββββββββββββββββββββββββββββββββββββ */
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
:root {
--total-black: #000;
--black: #222;
--white: #fff;
--red: #c4302b;
--darkred: #ae2012;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
button {
cursor: pointer;
font-size: 100%;
}
input,
input[type="search"]::search-decoration,
input[type="search"]::search-cancel-button,
input[type="search"]::search-results-button,
input[type="search"]::search-results-decoration {
appearance: none;
}
button,
input {
border: none;
background: none;
outline: none;
color: inherit;
font-family: inherit;
}
img {
max-width: 100%;
height: auto;
}
a {
color: inherit;
}
body {
font: 20px/1.5 "Roboto", sans-serif;
padding: 70px;
background: var(--black);
}
.container {
width: 100%;
max-width: 1200px;
padding: 0 15px;
margin: 0 auto;
}
/* MAIN STYLES
ββββββββββββββββββββββββββββββββββββββββββββββββββ */
.top-banner {
color: var(--white);
}
.top-banner h1 {
font-size: clamp(48px, 3.5vw, 72px);
line-height: 1.2;
}
.top-banner .label {
font-size: clamp(18px, 2vw, 28px);
margin-top: 10px;
}
.top-banner .text {
margin-bottom: 30px;
}
.top-banner form {
position: relative;
display: grid;
grid-template-columns: 1fr auto;
grid-gap: 15px;
align-items: center;
justify-content: center;
max-width: 1000px;
}
.top-banner form input {
font-size: clamp(24px, 2vw, 32px);
height: 40px;
padding-bottom: 10px;
border-bottom: 1px solid currentColor;
}
.top-banner form input::placeholder {
opacity: 1;
color: var(--white);
}
.top-banner form button {
font-weight: bold;
padding: 15px 30px;
border-radius: 5px;
background: var(--red);
transition: background 0.3s ease-in-out;
}
.top-banner form button:disabled {
pointer-events: none;
}
.top-banner form button:hover {
background: var(--darkred);
}
.top-banner form .msg {
position: absolute;
top: 100%;
left: 0;
}
.card {
padding: 4%;
text-align: center;
margin-top: 70px;
color: var(--white);
background: var(--total-black);
border-radius: 7px;
overflow: hidden;
}
.card .details img {
border-radius: 50%;
}
.card .details .title {
margin-top: 10px;
}
.card .details .description {
max-width: 80%;
margin: 30px auto 0;
}
.card .total-videos {
position: relative;
z-index: 1;
margin-top: 30px;
}
.card .total-subscribers {
position: relative;
display: inline-grid;
grid-template-columns: auto auto;
grid-gap: 10px;
align-items: center;
font-weight: bold;
margin-top: 60px;
background: var(--red);
}
.card .total-subscribers dotlottie-player {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.card .total-subscribers .outer {
padding: 10px;
}
.card .total-subscribers svg {
fill: var(--red);
background: var(--white);
padding: 5px;
box-sizing: content-box;
}
/* MQ STYLES
ββββββββββββββββββββββββββββββββββββββββββββββββββ */
@media (max-width: 700px) {
body {
padding: 70px 15px;
}
.top-banner form {
grid-template-columns: 1fr;
}
.top-banner form .msg {
position: static;
}
}
/* API BANNER STYLES
ββββββββββββββββββββββββββββββββββββββββββββββββββ */
.api {
background: #fffbbc;
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 10px;
font-size: 16px;
z-index: 1;
}
.api a {
text-decoration: underline;
}
.api a:hover {
text-decoration: none;
}
/* FOOTER STYLES
ββββββββββββββββββββββββββββββββββββββββββββββββββ */
.page-footer {
position: fixed;
right: 0;
bottom: 50px;
display: flex;
align-items: center;
padding: 5px;
z-index: 1;
font-size: 16px;
background: var(--white);
}
.page-footer a {
display: flex;
margin-left: 4px;
}
import { DotLottiePlayer } from "https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs";
const topBanner = document.querySelector(".top-banner");
const form = topBanner.querySelector("form");
const input = topBanner.querySelector("input");
const msg = topBanner.querySelector(".msg");
const BASE_URL =
"https://www.googleapis.com/youtube/v3/channels?part=statistics,snippet";
const API_KEY = "PUT YOUR API HERE!!!";
form.addEventListener("submit", (e) => {
e.preventDefault();
const channelId = input.value;
fetchYTStatistics(channelId)
.then((data) => {
if (typeof data.items !== "undefined") {
createCard(data);
} else {
msg.textContent = "Please search for a valid YT channel ID π©";
}
})
.catch((error) => {
msg.textContent = error;
});
if (document.querySelector(".card")) {
document.querySelector(".card").remove();
}
msg.textContent = "";
form.reset();
input.focus();
});
async function fetchYTStatistics(channelId) {
const url = `${BASE_URL}&id=${channelId}&key=${API_KEY}`;
const response = await fetch(url);
if (!response.ok) {
return Promise.reject(
`Something isn't working as expected. Error: ${response.status}`
);
}
const data = await response.json();
return data;
}
function createCard(data) {
const allData = data.items[0];
const { customUrl, title, description, thumbnails } = allData.snippet;
const { default: thumbnail } = thumbnails;
const { videoCount, subscriberCount } = allData.statistics;
const div = document.createElement("div");
div.classList.add("card", "container");
const markup = `
<div class="details">
<img width="${thumbnail.width}" height="${thumbnail.height}" src="${
thumbnail.url
}" alt="${title}">
<div class="title">
<a href="https://www.youtube.com/${customUrl}" target="_blank">${title}</a>
</div>
<p class="description">${description}</p>
</div>
<div class="total-videos">
<a href="https://www.youtube.com/${customUrl}/videos" target="_blank">Browse</a>
<span class="count">${formatNumber(videoCount)}</span> videos
</div>
<div class="total-subscribers">
${
subscriberCount >= 1000000
? `<dotlottie-player src="https://lottie.host/5fa38a1c-c8ba-4c3d-83b5-1a99b8796da3/jJFC2WMsxa.lottie" background="transparent" speed="1" style="width: 300px; height: 300px;" loop autoplay></dotlottie-player>`
: ""
}
<span class="outer">
<span class="count">${formatNumber(subscriberCount)}</span>
Subscribers
</span>
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24">
<path d="M4.652 0h1.44l.988 3.702.916-3.702h1.454l-1.665 5.505v3.757h-1.431v-3.757l-1.702-5.505zm6.594 2.373c-1.119 0-1.861.74-1.861 1.835v3.349c0 1.204.629 1.831 1.861 1.831 1.022 0 1.826-.683 1.826-1.831v-3.349c0-1.069-.797-1.835-1.826-1.835zm.531 5.127c0 .372-.19.646-.532.646-.351 0-.554-.287-.554-.646v-3.179c0-.374.172-.651.529-.651.39 0 .557.269.557.651v3.179zm4.729-5.07v5.186c-.155.194-.5.512-.747.512-.271 0-.338-.186-.338-.46v-5.238h-1.27v5.71c0 .675.206 1.22.887 1.22.384 0 .918-.2 1.468-.853v.754h1.27v-6.831h-1.27zm2.203 13.858c-.448 0-.541.315-.541.763v.659h1.069v-.66c.001-.44-.092-.762-.528-.762zm-4.703.04c-.084.043-.167.109-.25.198v4.055c.099.106.194.182.287.229.197.1.485.107.619-.067.07-.092.105-.241.105-.449v-3.359c0-.22-.043-.386-.129-.5-.147-.193-.42-.214-.632-.107zm4.827-5.195c-2.604-.177-11.066-.177-13.666 0-2.814.192-3.146 1.892-3.167 6.367.021 4.467.35 6.175 3.167 6.367 2.6.177 11.062.177 13.666 0 2.814-.192 3.146-1.893 3.167-6.367-.021-4.467-.35-6.175-3.167-6.367zm-12.324 10.686h-1.363v-7.54h-1.41v-1.28h4.182v1.28h-1.41v7.54zm4.846 0h-1.21v-.718c-.223.265-.455.467-.696.605-.652.374-1.547.365-1.547-.955v-5.438h1.209v4.988c0 .262.063.438.322.438.236 0 .564-.303.711-.487v-4.939h1.21v6.506zm4.657-1.348c0 .805-.301 1.431-1.106 1.431-.443 0-.812-.162-1.149-.583v.5h-1.221v-8.82h1.221v2.84c.273-.333.644-.608 1.076-.608.886 0 1.18.749 1.18 1.631v3.609zm4.471-1.752h-2.314v1.228c0 .488.042.91.528.91.511 0 .541-.344.541-.91v-.452h1.245v.489c0 1.253-.538 2.013-1.813 2.013-1.155 0-1.746-.842-1.746-2.013v-2.921c0-1.129.746-1.914 1.837-1.914 1.161 0 1.721.738 1.721 1.914v1.656z" />
</svg>
</div>
`;
div.innerHTML = markup;
document.body.appendChild(div);
}
function formatNumber(number) {
return new Intl.NumberFormat("en", {
notation: "compact"
}).format(number);
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.