본문 바로가기

React/Furry

9. 반응형 Header 만들기

728x90

개요

상품이 많아지게 된다면 스크롤을 하게 되면 헤더가 안보이게 되는데 최근 웹페이지의 트렌드는 헤더가 같이 따라오는것이 트렌드라 반응형 Header를 제작하도록 하겠습니다.

 

스크롤이벤트 추가하기

 

Home.js

import React , {useState , useEffect ,useRef} from 'react';

import styled from 'styled-components';

/* Header import */
import Header from '../components/Header/Header';

/* Top import */
import Top from '../components/Top/Top';

/* Nav import */
import Nav from '../components/Nav/Nav';

/* Item import */
import Item from '../components/Item/Item';

/* Footer import */
import Footer from '../components/Footer/Footer';

function Home(){

    const [pcategory , setPcategory] = useState('animal')

    const clickPcategory = (pcategory) => {
        setPcategory(pcategory)
    }    

    /*스크롤 이벤트 */

    const [ScrollY, setScrollY] = useState(0); // window 의 pageYOffset값을 저장 
    const [ScrollActive, setScrollActive] = useState(false); 

    const handleScroll = () => { 
        if(ScrollY > 120) {
            setScrollY(window.pageYOffset);
            setScrollActive(true);
        } else {
            setScrollY(window.pageYOffset);
            setScrollActive(false);
        }
    }

    useEffect(() => {
        function scrollListener() {  window.addEventListener("scroll", handleScroll); } //  window 에서 스크롤을 감시 시작
        scrollListener(); // window 에서 스크롤을 감시
        return () => { window.removeEventListener("scroll", handleScroll); }; //  window 에서 스크롤을 감시를 종료
    });

    return(
    <>
        <Container>
        <Top ScrollActive={ScrollActive} /> 
        <Header ScrollActive={ScrollActive}/> 

        <Nav pcategory={pcategory} clickPcategory={clickPcategory} />
        <Item pcategory={pcategory} ScrollActive={ScrollActive}/>
        
        </Container>
        
        <Footer />
    </>
    )
}

export default Home;

const Container = styled.div`

position: relative;
padding: 0px;
border: 0px;

width : 100%;
height: 200%;
`

Home 페이지에 스크롤 이벤트를 작성해줍니다. ScrollY 값이 120 이상이면 ScrollActive가 true값이 되면서 css 값을 바꾸게 해줄것입니다.

 

Top.js

import React ,{useState} from 'react'
import styled from 'styled-components';

export default function Top({ScrollActive}){
    const [login,setLogin] = useState(false)


    return(
        <Positioner className={ScrollActive ? 'flexible' : null}>
            <GreyBackground>
            <TopContents>
                <Spacer />
                <P>홈</P>
                <Spacer />

                {login === false ? 
                <>
                <P>회원가입</P>
                <P>로그인</P>
                </>
                :
                // 로그인 했을 때
                <>
                <P></P>
                <P>로그아웃</P>
                </>}
                
            </TopContents>
            </GreyBackground>
        </Positioner>
    )
}

// 상단 고정
const Positioner = styled.div`

    display: flex;
    flex-direction: column;
    position: absolute;
    top: 0px;
    left : calc(50vw - 600px);
    width: 1300px;
    z-index:99;

    padding : 0px;
    border: 0px;    

    &.flexible{

        position: fixed;
        background : #e2e2e2;
        height: 40px;
    }
`;



// 회색 배경
const GreyBackground = styled.div`

    flex-direction: row;
    align-items: center;

`

const TopContents = styled.div`
    width: 1200px;
    height: 30px;
    display : inline-grid;
    flex-direction: row;
    align-items: right;

    grid-template-columns: 220px 50px 600px 90px 100px;
`

//글씨
const P = styled.span`
margin: 5px;
font-family : 'tway';

`

//여백
const Spacer = styled.div`
`

ScrollActive 를 props로 받아와 조건이 만족할때 포지션값을 바꿔줍니다.

 

Header.js

import React from "react";
import styled from "styled-components";

export default function Header({ScrollActive}){
    return(
        <Positioner className={ScrollActive ? 'flexible' : null}>
        <WhiteBackground>
            <HeaderContents>
                <Spacer/>
                <Title>Furry</Title>
                <Search>
                <Input 
                    placeholder="찾고 싶은 상품을 검색해보세요!"/>
                <IMG> 🔎 </IMG>
                </Search>

                <MY className={ScrollActive ? 'flexible' : null}>
                    <ICON>😀</ICON>
                    <P>마이퓨리</P>
                </MY>
                <Cart className={ScrollActive ? 'flexible' : null}>
                    <ICON>🛒</ICON>
                    <P>장바구니</P>
                </Cart>
                <Spacer/>
            </HeaderContents>
        </WhiteBackground>
    </Positioner>
    )
}


// 상단 고정, 그림자
const Positioner = styled.div`
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 35px;
    left : calc(50vw - 600px);
    width: 1300px;
    padding : 0px;
    border: 0px;

    z-index:99;

    &.flexible{

    
    position: fixed;
    background : #e2e2e2;
    height: 60px;

    }
    `

// 흰 배경, 내용 중간 정렬
const WhiteBackground = styled.div`
    
    display: flex;
    justify-content: center;
    height: auto;
`

// 해더의 내용
const HeaderContents = styled.div`
    width: 1200px;
    height: 55px;
    display: flex;
    flex-direction: row;
    align-items: center;

`

// 로고
const Title = styled.div`
    font-size: 2rem;
    letter-spacing: 5px;
    font-family: 'tway';

    margin: 30px;

`

//검색창

const Search = styled.div`
margin: 30px;

position: relative;
width: 450px;

`
const Input = styled.input`

width: 400px;

height: 30px;

border : 3px solid #8ec64e;
border-radius : 24px;
outline: none;
padding-left: 10px;

`
const IMG = styled.span`
position: absolute;

top : 7px;
right : 45px;

margin: 0;
`

//장바구니
const MY = styled.button`
    margin: 5px;
    border : 0px;
    
    line-height: 0;

    overflow : hidden;

    background: #e2e2e2;
    &.flexible{
    background: transparent;

    }
`
const Cart = styled.button`
    margin: 5px;
    
    border : 0px;

    line-height: 0;

    background: #e2e2e2;
    
    &.flexible{
    background: transparent;

    }

`
const ICON = styled.p`
font-size : 2rem;

`
const P = styled.p`
font-weight : 1000;
`
// 중간 여백

const Spacer = styled.div`
    flex-grow: 1;
`;

 

Item 렌더링 될때 처음에 보여줄 컴포넌트

아직 정한것이 없어 모든 상품을 보여주도록 했다.

 

Item.js

import React, { useState } from "react";
import styled from "styled-components";

/*상품 불러오기*/
import product from '../../JSON/product.json'

function ItemList({item,pcategory}){

    // console.log(Object.keys(product.product).length)

    return(
        <>
            {item.pcategory.includes(pcategory)
            ?
            <Frame>
            <Img src='' alt='x' />
            <Name>
                {item.pname}
            </Name>

            <Price>
                {item.pprice}
            </Price>

            </Frame>
            :
            <>
            </>
            }

        </>
    )
}   

function AllItemList({item}){

    // console.log(Object.keys(product.product).length)

    return(
        <>
            {item
            ?
            <Frame>
            <Img src='' alt='x' />
            <Name>
                {item.pname}
            </Name>

            <Price>
                {item.pprice}
            </Price>

            </Frame>
            :
            <>
            </>
            }

        </>
    )
} 

export default function Item({pcategory , ScrollActive}){


    return(
        
        <Positioner className={ScrollActive ? 'flexible' : null}>            
            {pcategory !== 'animal' ?
            <>
            {product.product.map((item)=>
            <ItemList item={item} id={item.id} pcategory={pcategory} />)}
            </>
                
            :
            <>
            {product.product.map((item)=>
            <AllItemList item={item} id={item.id} />)}
            </>

            }
        </Positioner>
    )
}

const Positioner = styled.div`
    display: block;
    flex-direction: column;
    position: absolute;
    top: 220px;

    left : calc(50vw - 400px );
    width: calc(100vw - (50vw - 400px) * 2 );

    @media (min-width : 1200px){
        left : calc(50vw - 600px );
        width: calc(100vw - (50vw - 600px) * 2 );
    }

    height: fit-content;
    
    padding : 0px;
    padding-bottom : 5rem;
    border: 0px;

    background-color: #FFFFFF;

    &.flexible{
    }
    
`;

const Frame = styled.div`
display: inline-block;
/*부모 요소에 따라 크기 변경 => %*/
width: 30%;
height: 300px;

margin-left : 2.5%;
margin-top : 2.5%;

@media (min-width : 1200px){
        width: 18%;
        
        /*광기*/
        margin-left : 1.666666666666667%;
    }

border-radius: 10px;
background: #fffaf2;
box-shadow: 1px 1px 2px #bebebe, -1px -1px 2px #ffffff;

`

const Img = styled.img`

width: 90%;
height: 65%;
margin: 5%;

display: block;

`

const Name = styled.p`
padding-left : 5px;
font-family : 'tway';
`

const Price = styled.p`
padding-left : 5px;
font-family : 'tway';

`

 

728x90

'React > Furry' 카테고리의 다른 글

10-2 ItemDetail 페이지 만들기  (1) 2023.02.27
10-1. ItemDetail 페이지 만들기  (0) 2023.02.15
8. Item 제작하기  (0) 2023.02.10
7. Props 흐름 수정하기  (0) 2023.02.08
6. NavDetail 제작하기  (0) 2023.02.08