ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Assignment] 위스타그램 코딩 Chapter 2. main page
    Develope/Assignment 2020. 5. 2. 15:32

    logo

    1. 시작

    ◎ 위스타그램 login page를 마무리하고 main page 작업을 시작하였다.

    repl.it 에 있는 위스타그램 메인 페이지를 구현을 하였다.

    2. 가이드

    ◎ html, css

    • header는 scroll 되어도 최상단에 fiexd 되어야 한다.

    • hedaer와 main은 화면의 중앙에 위치하여야 한다.

    • main을 두 개로 나누어 좌측에는 피드, 우측에는 스토리 및 팔로우 추천이 있다.

    • 우측 정보들은 scroll 되어도 fiexd 되어야 한다.

    • 피드는 하나만 만들어도 된다.

    ◎ javascript

    • 댓글 input 창에 엔터 치거나 "게시"를 누르면 댓글이 추가되어야 한다.

    • createElement로 요소를 생성해서, input에 입력한 값이 추가되어야 한다.

    3. 레이아웃

    ◎ 위스타그램 메인 페이지는 레이아웃 구현이 오래 걸렸다.(생각보다 신경 써야 할게 많았다..)

    repl.it에 있는 main page 디자인을 보았다.

     

    repl.it 메인 페이지 디자인

    hedaer와 main 이 정확히 중앙에 위치하여야 하며, main안에 좌측 , 우측을 정확히 나눠야 하기 때문이다.

    아이콘도 영역의 중앙에 배치하여야 하며, 프로필 이미지와 아이디 부분도 영역의 중앙에 배치해야 한다.

    main page는 전체적으로 중앙에 배치하여야 하기 때문에 신경 쓸 부분이 많았다.

    로그인 페이지를 구현할 때와 같이 html로 레이아웃을 먼저 구성하고 css를 작업하기 시작했다.

    westagram main layout

    레이아웃만 구성한 화면이다. 이제 css를 입혀보자.

     

    위스타그램 메인 페이지

    4. 코드

    ◎ html code

    ※ 내용이 많아서 전체적인 코드는 깃에서 확인할 수 있다.

    <div class="wrap">
          <!-- header -->
          <header class="header">
          </header>
          <!-- //header -->
    
          <!-- main -->
          <div class="main">
              <div class="container">
                  <!--left -->
                  <div class="contents_left">
                  </div>
                  <!--//left -->
                  <!-- rigth -->
                  <div class="contents_right">
                      <!-- aside -->
                      <aside class="aside">
                      </aside>
                      <!-- //aside -->
                      <!-- footer -->
                      <footer class="footer">
                      </footer>
                      <!-- //footer -->
                  </div>
                  <!-- //rigth -->
              </div>
          </div>
          <!-- //main -->
     </div>
    • 레이아웃은 크게 header, main, left, rigth로 나누었다.

    • header tag 안에는 Img 태그를 사용하여 logo를 나타내었다.

    • form태그 안에는 comment의 input, button으로 나누었다.

    ◎  css code

    ※ 내용이 많아서 전체적인 코드는 깃에서 확인할 수 있다.

    /* main.css */
    
    /* header */
    .header {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        z-index: 100;
        height: 55px;
        background: #fff; 
        box-sizing: border-box;
        border-bottom: 1px solid #dbdbdb;
    }
    .header .header_wrap {
        height: 100%;
        max-width: 1066px;
        margin: 0 auto;
    }
    .header .inner {
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 100%;
    }
    /* //header */
    
    /* main */
    .main {
        position: relative;
        top: 55px;
        background: #f8f9fa;
    }
    .main .container {
        display: flex;
        max-width: 1066px;
        margin: 0 auto;
        padding: 30px 0;
    }
    
    /* 왼쪽 영역 */
    .contents_left {
        width: 650px;
        box-sizing: border-box;
        margin-right: 40px;
    }
    /* 왼쪽 영역 */
    
    /* 오른쪽 영역 */
    .main .container .contents_right {
        position: fixed;
        left: calc(100% - 712px);
        width: 383px;
        box-sizing: border-box;
    }
    /* // 오른쪽 영역 */
    /* // 메인 영역 */
    • header에 position: fiexd로 설정하여 스크롤해도 고정되게 구현하였고, z-index 속성을 주어서 메인 페이지보다 위에 나타내게 하였다.

    • .header_wrap를 가진 div에 max-width값을 주고 marign: 0 autu; 로 설정하여 영역을 중앙으로 배치하였다.

    • hedaer안에 있는 자식들이 영역 안의 중앙으로 오고 그 영역에 맞게 적절한 수평 위치를 배치하여야 하기 때문에 display: flex; justify-content: space-between;  align-items: center; 로 설정하였다.

    • .main class를 가진 div에 position: relative; top: 55px; 로 설정하여 header의 높이만큼 떨어진 곳에 배치하였다.

    • .container class를 가진 div에 .header_wrap class와 같이 중앙으로 배치하여야 하기 때문에 max-width, margin을 사용하였고 좌측 영역과 오른쪽 영역을 수평으로 배치하여야 하기 때문에 display:flex를 주었다.

    • 왼쪽영역 .contents_left class를 가진 div에 width값을 주어 영역을 잡아주었다.

    • 오른쪽 영역 .contents_right class를 가진 div에 position: fixed;를 주고 left 값만큼 떨어진 곳에 배치하였다.

    /* main.css media query */
    @media only screen and (max-width: 1150px) {
        .contents_left {
            margin-left: 40px;
        }
    }
    
    @media only screen and (max-width: 800px) {  
        .contents_right {  
          display: none;
        } 
      }
    • 반응형을 조금 적용해 보고 싶어서 간단하게 작성해 보았다.

    • 화면을 줄였을 때 .content_left class를 가진 div가 왼쪽으로 붙은 현상을 발견하여 max-width: 1150px로 설정하여 marin-left: 40px; 만큼 띄어주었다.

    • 화면을 줄였을 때, .content_rigth class를 가진 div를 display: none;으로 설정하여 안 보이게 설정하였다.

    /* common.css */
    
    .wrap {
        height: 100%;
    }
    .scroll {
        overflow: auto;
    }
    .link_list {
        display: flex;
        align-items: center;
    }
    .link_list li {
        margin-left: 20px;
    }
    .link_list li:first-child {
        margin: 0;
    }
    .state_btn {
        border: none;
        padding: 0;
        width: 25px;
    }
    .state_btn img {
        width: 100%;
    }
    .feed_profile {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 10px 20px;
    }
    .profile {
        display: flex;
        align-items: center;
    }
    .profile .profile_img {
        width: 40px;
        margin-right: 10px;
        border-radius: 50%; 
    }
    .follow_info {
        margin-bottom: 10px;
        padding: 10px 13px;
        border: 1px solid #dee2e6;
        border-radius: 5px;
        background: #fff;
    }
    .follow_title {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 5px;
    }
    .follow_title span {
        font-size: 13px;
        line-height: 1.4;
    }
    .follow_title .text_tit {
        font-size: 15px;
        color: #828282;
    }
    .follow_title .sub_tit {
        font-weight: bold;
    }
    .follow_title a {
        display: block;
    }
    .follow_title a .profile_intro {
        font-size: 14px;
    }
    .feed_profile.follow_list_wrap {
        padding: 0;
    }
    .follow_list {
        display: block;
        width: 100%;
        max-height: 175px;
    }
    .follow_list li {
        display: flex;
        align-items: center;
        padding: 5px 0;
    }
    • 공통적으로 사용하는 css는 common.css 파일을 만들고 코딩하였다.

    • 특히 우측 스토리와 팔로우 영역은 공통적으로 사용하는 css가 많아 클래스를 동일하게 주고 재사용하였다.

    ◎ Javascript code

    const commentForm = document.querySelector('.comments_form');
    const comments = document.querySelector("#comment_input");
    const submitButton = document.querySelector(".btn span");
    
    function commentUpdate() {
            const ulbox = document.querySelector(".comments_info.comment_list_ul")
            const liBox =  document.createElement("li");
            const pBox =  document.createElement("div");
            const userBox = document.createElement("span");
            const commentCtnBox = document.createElement("span");
            let user ="test";
    
            userBox.setAttribute("class", "user_id");
            commentCtnBox.setAttribute("class", "comment_contents");
            pBox.setAttribute("class", "comments_tit");
           
            userBox.innerHTML = user;
            commentCtnBox.innerHTML = comments.value;
           
            pBox.appendChild(userBox);
            pBox.appendChild(commentCtnBox);
            liBox.appendChild(pBox);
            ulbox.appendChild(liBox);
            comments.value = "";
    };
    
    
    // keydown시 page stop
    commentForm.addEventListener("submit", function(e) {
        e.preventDefault();
    });
    
    // 게시버튼 클릭 시 발생하는 함수
    submitButton.addEventListener("click",commentUpdate);
    
    // 댓글 작성 후 엔터를 쳤을 때 발생하는 함수
    comments.addEventListener("keydown", function(e) {
        if(e.keyCode === 13) {
            const ulbox = document.querySelector(".comments_info.comment_list_ul")
            const liBox =  document.createElement("li");
            const pBox =  document.createElement("div");
            const userBox = document.createElement("span");
            const commentCtnBox = document.createElement("span");
            let user ="test";
    
            userBox.setAttribute("class", "user_id");
            commentCtnBox.setAttribute("class", "comment_contents");
            pBox.setAttribute("class", "comments_tit");
            userBox.innerHTML = user;
            commentCtnBox.innerHTML = comments.value;
           
            pBox.appendChild(userBox);
            pBox.appendChild(commentCtnBox);
            liBox.appendChild(pBox);
            ulbox.appendChild(liBox);
            comments.value = "";
        }
    });
    • DOM에 접근하여 해당 요소들을 전역 변수로 선언하였다.

    • 댓글 작성 후 submitButton을 클릭했을 때 commentUpdate 함수를 호출하게 구현하였다.

    • 댓글 작성 후 엔터를 눌렀을 때 게시글이 작성되야 하므로 'keydown' 이벤트를 연결하고 함수를 내부에 작성하였다.

    • 댓글 작성 후 작성한 댓글이 보이도록 createElement(), settAttribute(), innetHTML(), appendChild() 등의 DOM 함수를 사용하였다.

    • keydown 시 page reload 현상을 막기 위해 e.preventDefault(); 를 설정하였다.

    5. 문제점

    ◎ 오른쪽 영역 position: fiexd를 설정하였을 때, 화면을 줄이면 계속 띄어지면서 따라오는 현상을 발견하였다.

    left값에 문제가 있는 거 같으며, 검색을 해보고 해결되지 않아서 멘토님한테 질문을 드렸는데, 반응형 웹을 배울 때 이 문제를 다룬다고 하셨다. 아직 해결방안은 잘 모르겠다..ㅜㅜ

     

    ◎ 댓글을 작성했을 때 엔터를 치면 댓글이 추가 안되고 페이지가 새로고침 되는 현상이 나타났다.

    검색해본 결과 e.preventDefault(); 를 사용하여 해결하였다.

    6. 최종 결과

    ◎ 디자인에 맞게 구현하였고, 댓글 기능을 구현하였다.

     

    ◎ 추가로 레이아웃만! 반응형을 조금 적용해보았다.

     

    7. 느낀 점

    • fiex를 헤더 말고 옆에 주었을 때, 화면을 줄였을 때 띄워지는 현상을 좀 더 알아봐야겠다.

    • click, keydown 이벤트를 발생할 때 실행되는 로직은 똑같아서 리펙토링을 해봤는데 실패했다. 리펙토링 정말 어렵다.

    • 공통적으로 사용하는 css는 common.css 파일을 만들어 재사용하는 방법은 좋은 거 같다.

    • 반응형에 대해서 좀 더 알아보고 싶어 졌다.

    • appendChild() 사용이 미숙하여 요소를 붙이는데 오래 걸렸다.. 많이 실습하여 익숙해지도록 하자.

    ※ 참조

    https://www.w3schools.com/jsref/event_onkeydown.asp

     

    onkeydown Event

    onkeydown Event ❮ DOM Events ❮ KeyboardEvent Example Execute a JavaScript when a user is pressing a key:

    Try it Yourself » More "Try it Yourself" examples below. Definition and Usage The onkeydown event occ

    www.w3schools.com

     

    https://developer.mozilla.org/ko/docs/Web/API/Event/preventDefault

     

    event.preventDefault

    이벤트를 취소할 수 있는 경우, 이벤트의 전파를 막지않고 그 이벤트를 취소합니다.

    developer.mozilla.org

     

    https://developer.mozilla.org/ko/docs/Web/API/Node/appendChild

     

    Node.appendChild()

    Node.appendChild() 메소드는 한 노드를 특정 부모 노드의 자식 노드 리스트 중 마지막 자식으로 붙입니다. 만약 주어진 노드가 이미 문서에 존재하는 노드를 참조하고 있다면 appendChild() 메소드는 ��

    developer.mozilla.org

    - Git

     

    https://github.com/JinDevT/fast-html-css/tree/master/westrgram

     

    JinDevT/fast-html-css

    Contribute to JinDevT/fast-html-css development by creating an account on GitHub.

    github.com

     

Designed by Tistory.