westagram cloning project -2

연정·2021년 10월 18일
0

Personal Projects

목록 보기
2/6
post-thumbnail

#1에서 정리한 로그인 페이지에 이어, westagram cloning project에서 가장 많은 시간을 들인 메인 페이지를 정리한다.

구현 결과

2) 메인 페이지

코드 및 셀프 리뷰

2) 메인 페이지

HTML

<!DOCTYPE html>
<html>
<head>
    <meta charset = "UTF-8"/>
    <title>Westagram</title>
    <link href="main.css" rel="stylesheet"/>
    <script src="https://kit.fontawesome.com/b5d94dac67.js" crossorigin="anonymous"></script>
    <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=Lobster&display=swap" rel="stylesheet"/>
</head>

<body>
    <nav>
        <div class="navLogo">
            <img alt="Westagram logo image" src="img/insta_logo.png"/>
            <h1>Westagram</h1>
        </div>
        <form class="navSearchForm">
            <input type="text" placeholder="검색"/>
            <i class="fas fa-search"></i>
        </form>
        <div class="navIcon">
            <img alt="explore icon" src="img/explore.png"/>
            <img alt="heart icon" src="img/heart.png"/>
            <img alt="profile icon" src="img/profile.png"/>
        </div>
    </nav>

    <main>
        <section class="feed">
            <article>
                <div class="feedHeader">
                    <div class="userInfo">
                        <img alt="user profile image" src="https://images.unsplash.com/photo-1634161906242-43a1d5beef68?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=464&q=80"/>
                        <div class="userInfoDetail">
                            <span class="userName">eliz_j_<span>
                            <span class="description">WeCode - 위코드</span>
                        </div>
                    </div>
                    <i class="fas fa-ellipsis-h"></i>
                </div>
                <img class="feedImg" alt="feed image" src="img/Cat.JPG"/>
                <div class="feedIcon">
                    <i class="far fa-heart"></i>
                    <i class="far fa-comment"></i>
                    <i class="far fa-paper-plane"></i>
                    <i class="far fa-bookmark"></i>
                </div>
                <div class="feedBody">
                    <div class="numberOfLikes">
                        <img alt="user profile image" src="https://images.unsplash.com/photo-1634161906242-43a1d5beef68?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=464&q=80"/>
                        <span><b>yeonjeong</b>님 외 <b>10명</b>이 좋아합니다</span>
                    </div>
                    <div class="feedText">
                        <span><b>eliz_j_</b></span>
                        <span>나만 고양이 없어ㅠㅠ&nbsp&nbsp<a href="">더 보기</a></span>
                    </div>
                    <ul class="feedComment">
                        <li>
                            <span><b>yeonjeong</b></span>
                            <span>나도 고양이 없어ㅠㅠ</span>
                            <button class="deleteBtn">x</button>
                        </li>
                    </ul>
                    <span class="feedUploadTime">1시간 전</span>
                </div>
                <form class="feedCommentInput" onsubmit="return false;">
                    <input id="commentInput" type="text" placeholder="댓글 달기..."/>
                    <button id="uploadBtn" type="button">게시</button>
                </form>
            </article>
        </section>

        <section class="main_right">
            <section class="userInfo">
                <img alt="user profile image" src="https://images.unsplash.com/photo-1634161906242-43a1d5beef68?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=464&q=80"/>
                <div class="userInfoDetail">
                    <span class="userName">eliz_j_</span>
                    <span class="description">WeCode - 위코드</span>
                </div>
            </section>
            <section class="story">
                <div class="storyTitle">
                    <h4>스토리</h4>
                    <span> 모두 보기</span>
                </div>
                <ul>
                    <li class="userInfo">
                        <img alt="user profile image" src="https://images.unsplash.com/photo-1597024065285-6f47cd40f5d0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80"/>
                        <div class="userInfoDetail">
                            <span class="userName">yumyum</span>
                            <span class="description">20분 전</span>
                        </div>
                    </li>
                    <li class="userInfo">
                        <img alt="user profile image" src="https://images.unsplash.com/photo-1597024065285-6f47cd40f5d0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80"/>
                        <div class="userInfoDetail">
                            <span class="userName">lalala</span>
                            <span class="description">1시간 전</span>
                        </div>
                    </li>
                    <li class="userInfo">
                        <img alt="user profile image" src="https://images.unsplash.com/photo-1597024065285-6f47cd40f5d0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80"/>
                        <div class="userInfoDetail">
                            <span class="userName">pwwwwwww</span>
                            <span class="description">15시간 전</span>
                        </div>
                    </li>
                </ul>
            </section>
            <section class="recommend">
                <div class="recommendTitle">
                    <h4>회원님을 위한 추천</h4>
                    <span>모두 보기</span>
                </div>
                <ul>
                    <li class="userInfo">
                        <img alt="user profile image" src="https://images.unsplash.com/photo-1597024065285-6f47cd40f5d0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80"/>
                        <div class="userInfoDetail">
                            <span class="userName">yumyum</span>
                            <span class="description">yoyoyoyo님 외</span>
                        </div>
                        <button type="button">팔로우</button>
                    </li>
                    <li class="userInfo">
                        <img alt="user profile image" src="https://images.unsplash.com/photo-1597024065285-6f47cd40f5d0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80"/>
                        <div class="userInfoDetail">
                            <span class="userName">lalala</span>
                            <span class="description">sumsum님 외</span>
                        </div>
                        <button type="button">팔로우</button>
                    </li>
                    <li class="userInfo">
                        <img alt="user profile image" src="https://images.unsplash.com/photo-1597024065285-6f47cd40f5d0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=435&q=80"/>
                        <div class="userInfoDetail">
                            <span class="userName">pwwwwwww</span>
                            <span class="description">newnew님 외</span>
                        </div>
                        <button type="button">팔로우</button>
                    </li>
                </ul>
            </section>
            <section class="westaInfo">
                <ul>
                    <li>Westagram 정보</li>
                    <li>&middot;</li>
                    <li>지원</li>
                    <li>&middot;</li>
                    <li>홍보 센터</li>
                    <li>&middot;</li>
                    <li>API</li>
                    <li>&middot;</li>
                    <li>채용 정보</li>
                    <li>&middot;</li>
                    <li>개인정보처리방침</li>
                    <li>&middot;</li>
                    <li>약관</li>
                    <li>&middot;</li>
                    <li>디렉터리</li>
                    <li>&middot;</li>
                    <li>프로필</li>
                    <li>&middot;</li>
                    <li>해시태그</li>
                    <li>&middot;</li>
                    <li>언어</li>
                </ul>
                <span class="copyright">&copy; 2019 WESTAGRAM</span>
            </section>
        </section>
    </main>
    <script defer src="main.js"></script>
</body>
</html>

HTML Self-Review :)

  • 메인페이지에서는 구성요소와 구분되는 지점이 많아 section 태그를 활용해보았다. 하나의 페이지 내에서 섹션을 구분함으로써 각각의 역할을 지정하여 보기에 수월하도록 정리함
  • 디자인을 위해 요소들이 묶여서 움직여야 할 때는 div 태그를 사용할 수밖에 없었다.
  • 피드 내 댓글 부분은 추후 구현할 이벤트를 위해 ul li 태그를 활용하였다.
  • 유저 이미지 + 유저 이름 + 장소 혹은 문구로 동일한 포맷을 가진 요소들의 경우, 원활한 디자인 구현을 위해 동일한 class 속성을 부여하였다.
  • &copy;가 copyright을 표현할 수 있는 방식이라는 걸 구글링을 통해 알아냄.
CSS

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    background-color: rgb(250,250,250);
}

li {
    color: black;
    font-size: 15px;
}

 ul {
     list-style: none;
 }

/* user information 공통 적용 부분 */

.userInfo {
    display: flex;
    align-items: center;
}

.userInfo img {
    width: 40px;
    height: 40px;
    border: 1px solid lightgrey;
    border-radius: 50%;
}

.userInfoDetail {
    display: inline-block;
    margin-left: 10px;
}

.userName {
    display: block;
    font-weight: bold;
}

.description {
    display: block;
    color: grey;
    font-size: 11px;
}

/* 여기부터 nav 부분 */

nav {
    display: flex;
    justify-content: space-around;
    align-items: center;
    position: fixed;
    height: 55px;
    width: 100%;
    padding: 10px, 35px, 5px, 35px;
    background-color: white;
    border-bottom: 1px solid rgb(241,240,240);
    z-index: 1000;
}

.navLogo img {
    height: 20px;
    padding-right: 15px;
    border-right: 2px solid black;
}

.navLogo h1 {
    display: inline;
    margin-left: 10px;
    font-family: 'Lobster', cursive;
    font-size: 25px;
}

.navSearchForm {
    position: relative;
}

.navSearchForm i {
    position: absolute;
    left: 82px;
    padding-top: 8px;
    color: rgb(186,187,189);
    font-size: 12px;
}

.navSearchForm input {
    width:220px;
    height: 28px;
    border: 1px solid rgb(219,219,219);
    border-radius: 3px;
    background-color: rgb(250,250,250);
    outline: none;
}

.navSearchForm input::placeholder {
    color: rgb(165,165,165);
    text-align: center;
}

.navIcon img {
    width: 25px;
    margin: 0 7px;
}

/* 여기부터 main 부분 */

main {
    display: flex;
    justify-content: center;
    height: 100%;
    padding-top: 90px;
    margin: 0 50px 40px 50px;
}

/* main 중 feed 노출 부분 */

article {
    border: 1px solid rgb(219,219,219);
    border-radius: 3px;
    background-color: white;
}

.feedHeader {
    display: flex;
    align-items: center;
    position: relative;
    padding: 10px;
    border-bottom: 1px solid rgb(219,219,219);
}

.feedHeader i {
    position: absolute;
    right: 15px;
}

.feedImg {
    width: 600px;
}

.feedIcon {
    display: flex;
    align-items: center;
    padding: 5px 0;
}

.feedIcon i {
    padding-left: 15px;
    font-size: 25px;
}

.feedIcon .fa-bookmark {
    padding-left: 440px;   
}

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

.numberOfLikes {
    display: flex;
    align-items: center;
}

.numberOfLikes img {
    width: 20px;
    height: 20px;
    border: 1px solid lightgrey;
    border-radius: 50%;
}

.numberOfLikes span {
    padding-left: 8px;
}

.feedText {
    margin-top: 10px;
    line-height: 30px;
}

.feedText a {
    text-decoration: none;
}

.feedComment {
    position: relative;
}

.feedComment .deleteBtn {
    position: absolute;
    right: 12px;
    color: grey;
    background-color: white;
    border: none;
}

.feedUploadTime {
    margin-top: 10px;
    color: rgb(148,148,148);
    font-size: 12px;
}

.feedCommentInput {
    position: relative;
    border-top: 1px solid rgb(219,219,219);
}

.feedCommentInput input{
    width: 550px;
    padding: 15px 10px;
    border: none;
    outline: none;
}

.feedCommentInput button {
    position: absolute;
    right: 0px;
    width: 50px;
    height: 100%;
    color: rgb(198,223,250);
    background-color: white;
    border: none;
}

/* main 중 main-right 노출 부분 */

.main_right {
    width: 300px;
    margin-left: 30px;
}

.story, .recommend {
    margin-top: 15px;
    padding: 12px;
    border: 1px solid rgb(219,219,219);
    border-radius: 3px;
    background-color: white;
}

.storyTitle, .recommendTitle {
    display: flex;
    justify-content: space-between;
    margin-bottom: 5px;
    font-size: 14px;
}

.storyTitle h4, .recommendTitle h4 {
    color: rgb(144,144,144);
}

.storyTitle span, .recommendTitle span {
    font-weight: bold;
}

.story ul, .recommend ul {
    display: flex;
    flex-direction: column;
}

.story li, .recommend li {
    margin-top: 8px;
}

.story .userInfo img {
    padding: 2px;
    border: 2px solid rgb(200,61,126);
    border-radius: 50%;
}

.recommend .userInfo img {
    border: 2px solid lightgrey;
    border-radius: 50%;
}

.recommend .userInfo {
    position: relative;
}

.recommend button {
    position: absolute;
    right: 0;
    border: none;
    color: rgb(68,148,239);
    background-color: white;
    font-weight: bold;
}

.westaInfo {
    display: flex;
    flex-direction: column;
}

.westaInfo ul {
    margin-top: 15px;
}

.westaInfo li {
    float: left;
    margin: 0 1px;
    color: lightgrey;
    font-size: 12px;
}

.copyright {
    margin-top: 10px;
    color: lightgrey;
    font-size: 14px;
}

CSS Self-Review :)
긴 코드로 인해 가독성이 너무 떨어지는 것 같아, 주석을 일부 활용하여 구간을 표기하였다.

  • 공통적인 디자인이 적용되는 내용은 그냥 적어두니 코드를 다시 볼 때 알아보기가 너무 어려워 코드 앞 부분에 따로 빼서 정리하였다.
  • nav 부분이 스크롤 할 때 다른 컨텐츠에 가려지는 문제가 발생하여 구글링! 우선순위때문에 발생하는 문제라고 하여 해당 부분에 z-index를 주어 문제를 해결 :)
  • 이전의 weegle 문제를 풀며 display : flexpositon에 대해 고민했던 보람이 있다! 이제는 비교적 수월하게 해당 속성들을 활용 하는 듯.

메인 페이지에서 구현한 이벤트는,
feed 내 댓글을 입력하고 엔터를 치거나 게시버튼을 누르면 댓글이 추가되는 이벤트와,
추가된 댓글 우측의 x 버튼을 누르면 다시 댓글이 삭제되는 이벤트이다.

Javascript

"use strict";

const commentInput = document.getElementById('commentInput');
const uploadBtn = document.getElementById('uploadBtn');

function checkInput () {
    const commentValue = commentInput.value;
    
    if(commentValue.length){
        addComment(commentValue);
    } else {
        alert("댓글을 입력해주세요");
    }
}

function addComment (value) {
    const commentList = document.getElementsByClassName('feedComment')[0];
    const newComment = document.createElement('li');

    newComment.innerHTML = `<span><b>didoo</b>&nbsp&nbsp<span>${value}</span><span class="deleteBtn">x</span>`;
    deleteComment(newComment);
    commentList.appendChild(newComment);

    commentInput.value = '';
}

function deleteComment (newComment) {
    const deleteBtn = newComment.querySelector('.deleteBtn');
    deleteBtn.style.cursor = 'pointer';
    deleteBtn.addEventListener('click', () => newComment.remove());
}

const init = () => {
    uploadBtn.addEventListener('click', checkInput);
    commentInput.addEventListener('keydown', () => {
        if (window.event.code === 'Enter'){
            checkInput();
        }
    });
}

init();

Javascript Self-Review :)
로그인 페이지에서의 연습으로 게시버튼 클릭 시 댓글 추가되는 것까지는 비교적 수월하게 완성. 하지만 키이벤트에서는 꽤나 고전했는데, addEventListener 안에 함수를 넣고, 해당 함수를 통해 checkInput()을 불러오면서 문제 해결.
해결의 기쁨도 잠시,, 댓글을 삭제하는 이벤트는 더더욱 고전을 면치 못함..

  • 추가된 코멘트의 내용을 deleteComment() 함수가 온전히 받아야 하기 때문에 addComment() 내에 deleteComment() 작성
  • 다 잘 작성했는데도 작동하지 않아 코드를 살펴보니, 새롭게 생성된 newComment의 버튼이 아닌 기존 Comment의 버튼을 불러와 그곳에 addEventListener를 부여해서 문제가 생겼던 거였다. 해당 부분을 수정하니 문제 해결! 행복!!!
  • querySelector는 html 요소를 Javascript로 불러올 때 document보다 더 작은 범위에서 내가 원하는 요소를 찾을 수 있도록 도와준다. 실용적인 방법이니 사용에 익숙해지도록 하자!
profile
성장형 프론트엔드 개발자

0개의 댓글