React Hook의 useState를 이용해서 반응형 헤더와 메뉴 동작을 만들어보려고 한다.
useStateCSS 속성 값을 바꿔서 메뉴가 동작하는 것처럼 보일 수 있다.

Web 화면

Mobile 화면

App.js - import

import React, { useState } from "react";
import styled from "styled-components";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faApple } from "@fortawesome/free-brands-svg-icons";
import { faBars, faUser, faTimes } from "@fortawesome/free-solid-svg-icons";

아이콘을 쉽게 가져올 수 있는 Fontawesome 설치가 필요하다.
CSSstyled-components를 사용했다.

jsx 구조

├── Header
│   ├── toggle Button
│   ├── logo
│   ├── user Button
│   ├── header__menulist
│   └── header__right

jsx 구조를 이렇게까지 작성한 이유는 반응형을 구현하기 위해서 부모, 자식 관계나 순서가 꽤나 중요했다.
아직 CSS가 미숙한 부분일수도 있지만, 위의 구조처럼 진행했을 때 좀 더 수월하게 반응형 헤더를 구현할 수 있었다.

웹 화면에서는 toggle ButtonuserButtondisplay:none;으로 되어있다.
반응형이 적용되는 화면에서는 toggleButtonuserButtondisplay:block;으로 되고 header__menulistheader__rightdisplay:none;으로 된다.
이 상황에서 header__menulistheader__rightdisplay 속성이 flex로 바뀌게 되면서 width:100% 속성을 적용하면 자연스럽게 toggle Button, logo, userButton 아래로 내려갈 수 있다.

버튼 적용 화면


App.js - javascript

function App() {
  const [isToggled, setIsToggled] = useState(false);
  const [userToggled, setUserToggled] = useState(false);

  return (
    <Header isToggled={isToggled} userToggled={userToggled}>
      {/* 햄버거 버튼(bar) */}
      <div
        className="toggle"
        onClick={() => {
          setIsToggled(!isToggled);
        }}
      >
        <FontAwesomeIcon icon={!isToggled ? faBars : faTimes} />
      </div>

      {/* Apple 로고 */}
      <div className="logo">
        <FontAwesomeIcon icon={faApple} />
      </div>

      {/* User 버튼 */}
      <div
        className="user"
        onClick={() => {
          setUserToggled(!userToggled);
        }}
      >
        <FontAwesomeIcon icon={!userToggled ? faUser : faTimes} />
      </div>

      {/* 메뉴 리스트 */}
      <ul className="header__menulist">
        <li>Mac</li>
        <li>iPad</li>
        <li>iPhone</li>
        <li>Watch</li>
        <li>Music</li>
        <li>고객지원</li>
      </ul>

      {/* User 메뉴 리스트 */}
      <ul className="header__right">
        <li>Login</li>
        <li>Register</li>
      </ul>
    </Header>
  );
}

export default App;

App.js - CSS

const Header = styled.div`
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: white;
  background-color: black;

  .logo {
    margin: 0 1rem;
    font-size: 2rem;
  }

  .header__menulist {
    list-style: none;
    display: flex;
  }

  .header__left {
    display: flex;
  }

  .header__right {
    list-style: none;
    display: flex;
  }

  .header__right div {
    margin: 0 1rem;
  }

  li {
    padding: 0 1rem;
  }

  .toggle {
    display: none;
    font-size: 1.5rem;
    padding: 1rem 1rem;
  }

  .user {
    display: none;
    font-size: 1.5rem;
    padding: 1rem 1rem;
  }

  @media screen and (max-width: 768px) {
    flex-wrap: wrap;

    .header__right {
      display: ${(props) => (props.userToggled ? "flex" : "none")};
      flex-direction: column;
      width: 100%;
      background-color: black;
    }

    .header__menulist {
      display: ${(props) => (props.isToggled ? "flex" : "none")};
      flex-direction: column;
      width: 100%;
      background-color: black;
    }

    .header__menulist li,
    .header__right li {
      margin: 1rem 0;
      padding: 0;
    }

    .toggle {
      display: block;
    }

    .user {
      display: block;
    }
  }
`;

버튼 눌렀을 때 event 적용

jsx 부분

const [isToggled, setIsToggled] = useState(false);
const [userToggled, setUserToggled] = useState(false);

<div className="toggle"
  onClick={() => {
    setIsToggled(!isToggled);
  }}
>

<Header isToggled={isToggled} userToggled={userToggled}>

CSS 부분

@media screen and (max-width: 768px) {
  .header__right {
    display: ${(props) => (props.userToggled ? "flex" : "none")};
    flex-direction: column;
    width: 100%;
    background-color: black;
  }

  .header__menulist {
    display: ${(props) => (props.isToggled ? "flex" : "none")};
    flex-direction: column;
    width: 100%;
    background-color: black;
  }
}

useState를 통해서 isToggleduserToggled의 초깃값을 false로 지정한다.
onClick event가 실행됐을 때 해당 값을 반대로(false -> true) 바꾼다.
해당 값이 CSS 부분으로 전달되고 display 속성에 영향을 미친다.
CSS 부분으로 전달되는 것은 <Header isToggled={isToggled} userToggled={userToggled}>이 부분을 통해서 props로 전달할 수 있다.

onClick 이벤트로 바뀐 값을 CSS로 넘겨주는 부분에서 꽤나 많은 시간을 썼다.
onClick 이벤트로만 해당 기능이 작동하기 때문에 다른 영역을 선택한다고 display 속성이 바뀌지 않는다.

0개의 댓글

Powered by GraphCDN, the GraphQL CDN