본문 바로가기
샘플코드

[프론트엔드] 유튜브 페이지 코드 샘플

by jinwanseo 2021. 2. 17.
728x90

FrontEnd Youtube Html, Css, Javascript Code Sample (반응형)

 

프론트 엔드 연습을 위해 유튜브 페이지를 만들어보았다.

오랜시간에 걸쳐서 만든 페이지가 아니라 허접하다.

필요한 사람은 잘 다듬어서 사용하면 좋을 것같다.

출력화면, 소스코드 순서대로 기재해 두었으니 참고바란다.

 

 

구동 로직은 

header에 css 파일 을 추가하고 body에 script만 추가하면

해당 페이지에 데이터 베이스 또는 사용자가 미리 설정한 데이터를 토대로 

페이지 내 마크업 언어가 작성되는 방식이다.

파일은 가장 하단에 첨부해 놓았으니 참고바람.

 

[CSS]

 

:root {
    /* color */
    --headerColor : #252525;
    --fontColor : #252525;
    --logoColor : #df2928;
    --videoBackColor : #000000;
    --headerIcon : #fefefe;
    --infoIcon : #909090;
    --borderColor : #e0e0e0;
    --blueColor :#3656c7;
}

body { margin : 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;}
button,button:focus {
    cursor : pointer;
    outline: none;
    border :none;
    background-color: transparent;
}


header {
    display : flex;
    justify-content:space-between;
    align-items: center;
    padding : 10px 10px;
    font-size : 20px;
    background : var(--headerColor);
    color : var(--headerIcon);
}
    header>.logo>i {
        color : var(--logoColor);
    }
    header > .icon {
        font-size : 16px;
    }
    
.player {
    display : flex;
    justify-content: center;
    align-items: center;
    width : 100%;
    height: 45vw;
    max-width : 1000px;
    background : var(--videoBackColor);
}

    .player video {
        height: 100%;
    }

.info {
    display : flex;
    margin : 15px;
    flex-direction: column;
}
    .info > .hash {
        display : flex;
        justify-content: flex-start;
        padding : 0;
        margin-top : 0;
        margin-bottom : 5px;
        list-style: none;
        color : var(--blueColor);
    }
        .info > .hash > li {
           margin : auto 4px;
        }

    .info > .title {
        display : flex;
        justify-content: space-between;
    }

        .info > .title > .title-simple.clamp {
            display: -webkit-box;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 2;
            overflow: hidden;
        }

        .info>.title > .title-icon.clicked {
            transform: rotate(180deg);
        }

        .info > .title > .title-icon > i {
            height: 100%;
        }

    .info > .info-detail {
        color : var(--infoIcon);
        font-size : 12px;
        margin : 5px 0;
    }

    .info > .buttons {
        display : flex;
        justify-content: space-around;
        padding-top : 18px;
        padding-bottom : 18px;
    }

        .info > .buttons > .icon {
            display : flex;
            flex-direction: column;
            align-items: center;
        }

        .info > .buttons > .icon.clicked {
            color : var(--blueColor);
        }

        .info > .buttons > .icon > i {
            margin-bottom : 5px;
        }

    .info > .sub-info {
        display : flex;
        justify-content: space-between;
        align-items: center;
        border-top : 1px solid var(--borderColor);
        border-bottom : 1px solid var(--borderColor);
        margin : 5px 10px;
        padding-top : 18px;
        padding-bottom : 18px;
    }

    
        .info > .sub-info > .channel {
            display : flex;
            align-items: center;
            font-size : 14px;
        }
            .info > .sub-info > .channel > img {
                width : 45px;
                height: 45px;
                border-radius: 50%;
                margin-right: 10px;
            }
            .info > .sub-info > .channel > .channel-title {
                font-weight: bolder;
            }

            .info > .sub-info > .channel >  .channel-title >.channel-info {
                font-weight: lighter;
            }

        .info > .sub-info > .subscribe {
            text-transform: uppercase;
            user-select: none;
            padding : 5px;
            border : 1px solid var(--logoColor);
            background-color: transparent;
            color : var(--logoColor);
        }
        .info > .sub-info > .subscribe:hover {
            cursor: pointer;
        }
        .info > .sub-info > .subscribe.clicked {
            background-color: var(--logoColor);
            color : var(--headerIcon);
        }


.upNext {
    margin : 15px;
    display : flex;
    flex-direction: column;
}

    .upNext > .nextList {
        display : flex;
        flex-direction: column;
        list-style: none;
        padding : 0;
    }
    .upNext > .nextList li {
        display : flex;
        justify-content: space-between;
    }

    .upNext > .nextList li .imgAndTitle {
        display : flex;
        flex-direction: row;
    }

        .upNext > .nextList li .imgAndTitle .img img{
            cursor : pointer;
            width : 168px;
            height: 94px;
        }

        .upNext > .nextList li .imgAndTitle .title {
            cursor : pointer;
            font-size : 15px;
            margin : 0px 15px;
        }

        .upNext > .nextList li .title .title-by,
        .upNext > .nextList li .title .title-views {
            font-weight: lighter;
        }

.infoAndUpnext {
    display : flex;
    flex-direction: row;
    max-width : 1000px;
}

@media screen and (max-width : 768px){
    .infoAndUpnext {
        flex-direction: column;
    }
}

 

[Javascript]

 

//데이터 SET
const dataList = {
    siteName : 'YouTube',   //사이트명
    siteLogo : '<i class="fab fa-youtube"></i>',    //사이트 로고 (현재 유튜브로고)
    channelName : 'ChannelName',    //채널이름
    subscribe : '9999', //구독
    hash : [
        '#신짱구','#짱구는못말려','#귀여운짱구'
    ],
    video : {//동영상 url, 제목, 조회수, 지난날짜, 좋아요, 싫어요
        videoUrl : './video/videoplayback.mp4',  //동영상 url (경로내 파일 없을시 재생안됨)
        videoTitle : '짱구는 못말려 짱구 아바타 이미지 짱구는 못말려 19기 먹방 리보터를 하고 싶어요 짱구가 졸업하고 칭찬 받아요 짱구 아빠 머릿결이 찰랑찰랑 해요',
        videoView : '9999',
        videoDate : '1',
        videoLike : '1K',
        videoDisLike : '0'
    },
    othervideoList : [  //동영상 재생 목록
        {
            thumbNailImg : 'https://img.insight.co.kr/static/2020/08/26/700/um01e66fr9c3b1x3yax7.jpg',
            videoTitle : '재생목록 내 타이틀',
            channelName : 'ChannelName',
            videoView : '9999'
        },
    ],
};

//태그 생성
//header
const haederElement = document.createElement('header');
haederElement.innerHTML = `
        <div class="logo">
            ${dataList.siteLogo}
            <span class="title">${dataList.siteName}</span>
        </div>
        <div class="icon">
            <i class="fas fa-search"></i>
            <i class="fas fa-ellipsis-v"></i>
        </div>
`;

//.player
const playerElement = document.createElement('section');
playerElement.classList.add('player');
playerElement.innerHTML = `
    <video controls src="${dataList.video.videoUrl}"></video>
`;

//.infoAndUpnext
const infoAndNextElement = document.createElement('section');
infoAndNextElement.classList.add('infoAndUpnext');

//.infoAndUpnext > .info
const infoElement = document.createElement('section');
infoElement.classList.add('info');
let hashTags = '';
dataList.hash.forEach(hash => hashTags+= `<li>${hash}</li>`);
infoElement.innerHTML = `
            <ul class="hash">
               ${hashTags}
            </ul>
            <div class="title">
                <div class="title-simple clamp">
                    ${dataList.video.videoTitle}
                </div>
                <button class="title-icon">
                    <i class="fas fa-caret-down"></i>
                </button>
            </div>
            <div class="info-detail">${dataList.video.videoView} views ${dataList.video.videoDate} month ago</div>
            <div class="buttons">
                <button class="icon">
                    <i class="fas fa-thumbs-up"></i>
                    ${dataList.video.videoLike}
                </button>
                <button class="icon">
                    <i class="fas fa-thumbs-down"></i>
                    ${dataList.video.videoDisLike}
                </button>
                <button class="icon">
                    <i class="fas fa-share"></i>
                    Share
                </button>
                <button class="icon">
                    <i class="fas fa-plus"></i>
                    Save
                </button>
                <button class="icon">
                    <i class="fab fa-font-awesome-flag"></i>
                    Report
                </button>
            </div>
            <div class="sub-info">
                <div class="channel">
                    <img src="http://img.lifestyler.co.kr/uploads/program/1/1765/menu/2/html/f131755988183457049(0).jpg" alt="" class="thumbnail">
                    <div class="channel-title">
                        ${dataList.channelName}
                        <div class="channel-info">${dataList.subscribe} subscribers</div>
                    </div>
                    
                </div>
                <span class="subscribe">subscribe</span>
            </div>
`;

//.infoAndUpnext > .upNext
const upNextElement = document.createElement('section');
const upNextElement_titleElement = document.createElement('div');
const upNextElement_nextListElement = document.createElement('ul');
upNextElement.classList.add('upNext');
upNextElement_titleElement.classList.add('title');
upNextElement_titleElement.innerText = 'Up next';
upNextElement_nextListElement.classList.add('nextList');
upNextElement.append(upNextElement_titleElement,upNextElement_nextListElement);

dataList.othervideoList.forEach(video => {
    upNextElement_nextListElement.innerHTML += `
        <li>
            <div class="imgAndTitle">
                <div class="img">
                    <img src="${video.thumbNailImg}" class="title-img">
                </div>
                <div class="title">
                    <div class="title-text">
                        ${video.videoTitle}
                    </div>
                    <div class="title-by">${video.channelName}</div>
                    <div class="title-views">${video.videoView} views</div>
                </div>
            </div>
            <div class="detail">
                <button class="detail-btn">
                    <i class="fas fa-ellipsis-v"></i>
                </button>
            </div>
        </li>
    `;
});

infoAndNextElement.append(infoElement,upNextElement);

//Html 작성
document.querySelector('body').append(haederElement,playerElement,infoAndNextElement);

//FontAwesome 추가
const fontawesome = document.createElement('script');
fontawesome.src = 'https://use.fontawesome.com/releases/v5.2.0/js/all.js';

document.querySelector('body').append(fontawesome);


//------------------- 기능 스크립트 영역------------------------

//타이틀 2줄만 보기 / 모두 보기
document.querySelector('.title-icon').addEventListener('click',e=>{
    document.querySelector('.title-simple').classList.toggle('clamp');
   document.querySelector('.title-icon').classList.toggle('clicked');
});

//좋아요 싫어요 클릭시 색상 변경
document.querySelector('.info>.buttons').addEventListener('click',e=>{
    if(e.target.nodeName === 'I'){
        console.log(e.target.parentElement);
        e.target.parentElement.classList.toggle('clicked');
    }
});

//구독버튼 클릭시 색상변경
document.querySelector('.sub-info>.subscribe').addEventListener('click',e=>{
    e.target.classList.toggle('clicked');
});

 

 

 

[소스파일]

script.js
0.01MB
style.css
0.00MB

728x90

댓글