210722_반응형 웹페이지 클론 코딩(basic)

Bitnara Lee·2021년 7월 22일
0

코딩을 배우면서 항상 css와 리액트의 기초 틀이 마련되 있는 상태에서 리액트에 대한 스프린트를 진행했기에
리액트와 css 문법을 이용해 바닥부터 웹페이지를 구현해본 적이 없었다.

css와 리액트에 대해 이것저것 공부해보고 있다가 아예 처음부터 구현하며 기본적인 프로세스를 알고 싶어 클론코딩 동영상을 찾게 되었다.

기본적인 메인 화면이 있고 (배경화면은 움직이는 영상) 메뉴의 페이지들이 라우팅되어 페이지 제목 클릭시 가운데의 화면만 바뀌는 SPA
(beginner 용이라 메인 제외 다른 페이지들은 추가적인 구현없이 기본 라우팅으로 연결만 해주고 각각 다른 배경이미지만 삽입했다.)
또, 화면크기에 따라 웹페이지의 레이아웃이나 크기비율이 달라지는 반응형 웹페이지이다.

메인 화면에서 스크롤을 내리면 사진이미지들이 구현되있고 클릭할 수 있다.(hover효과)
또 하단에는 footer 컴포넌트도 구현해주었다.

나는 처음 react-creat-app 설치와 기타 환경 세팅, 리액트의 기본기능을 복습하며 css의 활용, 레이아웃 패턴, 기타 디자인적 효과들에 대해 공부해볼 수 있었다.


🎂 새로 알게 된 것들 (잡다함 주의)

🍰 LAYOUT

기본적으로 컨텐츠(가 든 박스)를 정중앙에 위치시키려면
부모 박스는 아래 속성을 가지고 있어야 한다.

  • display : flex(or grid)
  • align-items: center
  • justify-content: center;

(경우에 따라 width나 height 설정)

padding : _컨텐츠 주변으로 여백이 생김 - 보이는 박스 넓이가 늘어남
margin : 컨텐츠가 든 박스 주변으로 여백이 생김 - 박스 위치가 이동

margin: auto -> 남는 여백을 알아서 나눠가진다.

부모에 따라 사이즈 변경 원할시 -> %, em
broswer 따라 사이즈 변경 원할시 -> v*, rem

요소box의 너비나 높이 따라 사이즈 변경 -> %, v*
font 사이즈에 따라 변경 -> em, rem

.child {
  font-size: 800%  // 부모의 font-size의 800 % ('em'과 비슷)
}
-> 반응형 페이지 만들때 유용

:nth-child()
()안에는 odd,even,숫자 등 어떤 child를 선택할 것인지에 대한 속성 들어간다

.parents > h1 {
parents 자식 중 h1선택

inset : margin같은것

div ::after {
content: "anything"
}
-> div 내용물 뒤에 뭔가 붙일수 있다
div ::before
-> div 내용물 앞에 뭔가 붙일수있다
w3school참고

🍩 IMAGE

css에서 background-image 삽입시

background-image : url('images/img-2.jpg') 

//이미지들은 작업중인 src폴더에 있어야 한다.

jsx에서 이미지 태그 이용시

<img src='images/img-9.jpg' />
<video src='/videos/video-2.mp4' autoPlay loop muted />

//이미지들은 public 폴더 내에 있어야 한다.

import , require 등 기타 방법들도 있음

🧁 DESIGN

linear-gradient(90deg, rgb(28, 27, 27) 0%, rgb(26, 23, 23) 100%)

그라데이션! deg는 각도

transform: translate(-100%,60%); ->움직임

✨ 특정 화면길이 미만일때 메뉴바의 버튼이 바뀌는 효과

🔸 SIGN UP 버튼의 유무

function Navbar() {
    const [click, setClick] = useState(false);
    const [button, setButton] = useState(true);

    const handleClick = () => setClick(!click);
    const closeMobileMenu = () => setClick(false);

    const showButton = () => {
        if(window.innerWidth <= 960) {
            setButton(false);
        } else {
            setButton(true);
        }
    };
    useEffect(() => {
       showButton();
    }, []) //처음 화면 렌더링할때 한번 발생

    window.addEventListener('resize', showButton);
  
  //SIGN-UP 버튼이 모바일 사이즈에선 사라진다!

window.innerWidth: 창 틀을 뺀 내용과 스크롤을 포함한 크기
window.addEventListener('resize', ..) : 화면 윈도우가 resize 될 때마다 이벤트가 발생한다.

1. 창을 특정 길이만큼 줄였을때 메뉴바의 sign-up 버튼이 사라진다 !

-> window.addEventListener('resize',..)가 showButton 호출
-> window.innerWidth의 크기에 따라 button의 불리언 값 변경됨
-> {button && <Button buttonStyle='btn--outline'>SIGN UP</Button>} 연산에 의해 렌더링

mdn- window.addEventListener('resize',..)

🔹 hamburger 메뉴바 및 클릭시 변환

<nav className="navbar">
   <div className="navbar-container">
      <Link to="/" className="navbar-logo" onClick={closeMobileMenu}>
          TRVL <i className="fab fa-typo3"></i>
      </Link>
      <div className="menu-icon" onClick={handleClick}>
          <i className={click ? 'fas fa-times' : 'fas fa-bars'} /> /** click 상태에 따라 햄버거, x버튼 **/
      </div>
         <ul className={click ? "nav-menu active" : "nav-menu"}>/* nav,menu 바는 보통 ul,li태그로 구현 */
            <li className="nav-item">  
              <Link to='/' className="nav-links" onClick={closeMobileMenu}>
                  Home
              </Link>
            </li>
                      .
                      .
                      .
            <li className="nav-item">  
              <Link to='/sign-up' className="nav-links-mobile" onClick={closeMobileMenu}>
                  Sign-Up      /*  보통 화면에서는 안보이다가 창이 좁아졌을때 메뉴클릭시 나옴  */
              </Link>
            </li>
         </ul>
        {button && <Button buttonStyle='btn--outline'>SIGN UP</Button>}  /* 기본버튼 */
     </div>
 </nav>       
                   
/*   CSS   */

  .nav-links-mobile {
    display: none;
  }
  
  .menu-icon {
    display: none;  /*  보통 display의 상태는 none! */
  }
  
  @media screen and (max-width: 960px) {
    .NavbarItems {
      position: relative;
    }
  
    .nav-menu {     /*  보통시에는 상단에 구성, 화면이 일정 가로 길이 이하가 되면 위치 옮기고 숨겨짐   */
      display: flex;
      flex-direction: column;
      width: 100%;
      height: 90vh;
      position: absolute;
      top: 80px;
      left: -100%;
      opacity: 1;
      transition: all 0.5s ease;
    }
  
    .nav-menu.active {         /*  햄버거 버튼 클릭시 위치 오른쪽으로 이동  */
      background: #242222;
      left: 0;
      opacity: 1;
      transition: all 0.5s ease;
      z-index: 1;
    }
  
    .menu-icon {     /*  화면이 일정 가로 길이 이하가 되어 나타남  */
      display: block;
      position: absolute;
      top: 0;
      right: 0;
      transform: translate(-100%, 60%);
      font-size: 1.8rem;
      cursor: pointer;
    }
      /*  나머지 생략  */
  }

2. sign-up 버튼 대신 hambuger 메뉴바가 등장한다 !

(위 참고)
-> CSS에서 @media screen 이용, 화면 사이즈에 따라 레이아웃과 효과를 설정한다.
-> 일정 화면의 길이 이하가 되었을 때, 상단 메뉴들이 사라지고, (위 코드처럼 위치가 이동됨) 햄버거 버튼 등장
-> 버튼 이벤트에 따라 click의 상태가 변하며 햄버거 버튼이 x버튼으로 변한다.(메뉴들이 옆에서 등장)

그 외

참고 영상에서는 자주 쓰는 button의 CSS를 효율적으로 적용하기 위해
Button 컴포넌트를 따로 만들어 두고
임의의 배열에 (STYLES,SIZES) 기본 클래스명, 효과를 적용할 클래스명을 담아뒀다.
props로 해당 클래스를 받아서 위 배열과 비교-로직 후, 링크와 버튼 리턴

import React from 'react';
import './Button.css';
import { Link } from 'react-router-dom';

const STYLES = ['btn--primary', 'btn--outline'];

const SIZES = ['btn--medium', 'btn--large'];

export const Button = ({
    children,
    type,
    onClick,
    buttonStyle,
    buttonSize
}) => {
    const checkButtonStyle = STYLES.includes(buttonStyle)
      ? buttonStyle 
      : STYLES[0];

      const checkButtonSize = SIZES.includes(buttonSize) ? buttonSize : SIZES[0]

      return (
       <Link to='/sign-up' className="btn--mobile">
         <button
           className={`btn ${checkButtonStyle} ${checkButtonSize}`}
           onClick={onClick}
           type={type}
         >
           {children}
         </button>

       </Link>

      )
}

이런식으로 Button 컴포넌트에 props를 주며 렌더링

   <Button className='btns' buttonStyle='btn--outline' buttonSize='btn--large'>
       GET STARTED
   </Button>
   <Button className='btns' buttonStyle='btn--primary' buttonSize='btn--large'>
       WATCH TRAILER <i className="far fa-play-circle" />
   </Button>
profile
Creative Developer

0개의 댓글