๊ฐœ๋ฐœ ๐Ÿพ/ReactJS

React div ์Šคํฌ๋กค์‹œ Fix ํ•˜๊ธฐ (Element scroll)

JOTOKKI 2021. 6. 11. 17:42
728x90

์ด์ „์— window์—์„œ ์Šคํฌ๋กคํ•  ๋•Œ ํŠน์ • ์—˜๋ ˆ๋ฉ˜ํŠธ๊ฐ€ ๊ณ ์ •์ด ๋˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ์—๋Š” window๊ฐ€ ์•„๋‹Œ ํŠน์ • div ์—์„œ ์Šคํฌ๋กคํ–ˆ์„ ๋•Œ div์•ˆ์˜ ๋‹ค๋ฅธ ๊ฐ์ฒด๊ฐ€ ๊ณ ์ •์ด ๋˜๋„๋ก ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

์‚ฌ์‹ค ๊ตฌํ˜„ ๋ฐฉ์‹์€ ๋˜‘๊ฐ™์Šต๋‹ˆ๋‹ค. 

๋‹จ์ง€ window ์™€๋Š” ๋‹ฌ๋ฆฌ ๊ฐ์ฒด์˜ scroll ๊ฐ’์„ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” useRef๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

์ €๋„ ์ด ๋ถ€๋ถ„์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ์žˆ์–ด ๋งŽ์€ ๊ณต๋ถ€๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜

 

๊ฐ์ฒด์—์„œ ๊ณ ์ •์„ ์‹œํ‚ค๋ ค๋ฉด fixed ์™€๋Š” ๋‹ฌ๋ฆฌ absolute๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ์œ„์น˜์˜ ๊ธฐ์ค€์ด viewport ๊ฐ€ ๋˜๋Š” fixed์™€ ๋‹ค๋ฅด๊ฒŒ absolute๋Š” ์ƒ์œ„ ๊ฐ์ฒด๋“ค ์ค‘ relative๊ฐ€ ๋˜๋Š” ๊ฐ’์„ ์ฐธ์กฐํ•˜์—ฌ ์œ„์น˜๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. 

 

๊ทธ๋ž˜์„œ ์ œ๊ฐ€ ์ƒ๊ฐํ•œ ๋ฐฉ๋ฒ•์€ 2๊ฐ€์ง€ ์ž…๋‹ˆ๋‹ค. ๊ฑฐ์˜ ๊ฐ™์œผ๋ฉด์„œ๋„ ํ™œ์šฉ์„ฑ์ด ์กฐ๊ธˆ ๋‹ค๋ฅผ ๊ฒƒ ๊ฐ™์•„์„œ ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์„ ๋ชจ๋‘ ์ ์šฉํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

์ถ•์•ฝํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

1. ๊ธฐ์กด ์ฒ˜๋Ÿผ ํด๋ž˜์Šค ํ•˜๋‚˜๋ฅผ ๋ถ™์—ฌ ์œ„์น˜๋ฅผ ์ปจํŠธ๋กคํ•œ๋‹ค. 

2. scroll๊ฐ’์„ ๊ฐ€์ ธ์™€ ์ธ๋ผ์ธ ์Šคํƒ€์ผ๋กœ ์‹ค์‹œ๊ฐ„ ๋ฐ˜์˜ํ•œ๋‹ค. (๋‹ค๋ฅธ css ๋ถ€๋ถ„์„ ์ปจํŠธ๋กคํ•˜๊ธฐ ์œ„ํ•ด ์–ด์ฐจํ”ผ ํด๋ž˜์Šค๋ฅผ ๋ถ™์ด๊ธด ํ•  ๊ฒƒ์ด๋‹ค.)


1. ํด๋ž˜์Šค ํ•˜๋‚˜๋กœ๋งŒ ์ปจํŠธ๋กค ํ•˜๊ธฐ

๊ตฌ์กฐ๋ฅผ ๋จผ์ € ์งœ๋ด…๋‹ˆ๋‹ค.

 

box๋Š” ์œ„์น˜์˜ ๊ธฐ์ค€์ด ๋  ๋ถ€๋ชจ์ด๊ณ , ์‹ค์ œ ์Šคํฌ๋กค์ด ๋˜๋Š” ๋…€์„์€ boxInner์ž…๋‹ˆ๋‹ค.

์ด boxInner์˜ ์Šคํฌ๋กค ๊ฐ’์„ ๋ถˆ๋Ÿฌ์™€ 30 ์ด์ƒ์ด ๋œ๋‹ค๋ฉด ScrollActive์˜ ์ƒํƒœ ๊ฐ’์ด ๋ฐ”๋€Œ๊ณ ,

ScrollActive ์ƒํƒœ๊ฐ’์ด ๋ฐ”๋€Œ๋ฉด smallBox์—๊ฒŒ ์ถ”๊ฐ€ ํด๋ž˜์Šค๊ฐ€ ๋ถ™์Šต๋‹ˆ๋‹ค. 

// App.js
<div className="box"  >
    <div className={ScrollActive ? "smallBox fixed" : "smallBox"}>
        {
        ScrollActive ? 
            'I am fixed! โœจ' : 
            'I will be fixed! ๐Ÿ˜'
        }
    </div>
    <div className="boxInner">
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae impedit ducimus perferendis, fuga nobis nihil eius similique. Laboriosam fuga doloribus quibusdam cumque beatae! Quae omnis, explicabo possimus molestias nam tempore!
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae impedit ducimus perferendis, fuga nobis nihil eius similique. Laboriosam fuga doloribus quibusdam cumque beatae! Quae omnis, explicabo possimus molestias nam tempore!
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae impedit ducimus perferendis, fuga nobis nihil eius similique. Laboriosam fuga doloribus quibusdam cumque beatae! Quae omnis, explicabo possimus molestias nam tempore!
        { ... }
    </div>
</div>
// App.css
.box {
  position: relative; 
  top: 30px; 
  right: 30px; 
  width: 400px; 
  height: 400px;
  background: black;
  color: white; 
  overflow: hidden;
  margin-left: 100px;
}

.box .boxInner {
  width: 100%; 
  height: 100%; 
  overflow: hidden;
  overflow-y: auto;
  padding: 10px; 
}

.smallBox {
  position: absolute; 
  top: 50px; 
  right: 40px;
  z-index: 1;
  padding: 10px; 
  background: rgb(236, 97, 218); 
  border-radius: 6px;
  color: #fff;
  border: 1px solid rgb(183, 81, 187);
  text-align: left;
}

.smallBox.fixed {
  width: 100%; 
  top: 0;
  right: 0; 
  border-radius: 0;
  text-align: center;
}

 

SPAํ˜•ํƒœ์ธ ๋ฆฌ์•กํŠธ ์•ˆ์—์„œ ํ•˜๋‚˜์˜ ํŠน์ • ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์„ ํƒํ•˜๋ ค๋ฉด useRef์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. 

ref๊ฐ€ ๊ฑธ๋ฆฐ ์—˜๋ฆฌ๋จผํŠธ์˜ ์†์„ฑ์„ ํ™•์ธํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๋‚ด์žฅ ํ•จ์ˆ˜๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

์˜ˆ๋ฅผ ๋“ค์–ด boxRef๋ฅผ div์— ์—ฐ๊ฒฐํ•œ ๋’ค ์ฝ˜์†”๋กœ ์ฐ์–ด๋ณด๋ฉด ํ•ด๋‹น ์—˜๋ฆฌ๋จผํŠธ์˜ ์†์„ฑ ๊ฐ’๋“ค์„ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ref ์ •๋ณด 

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

const boxRef = useRef(null);

<div className="box">
    { ... }
    <div className="boxInner" ref={boxRef}> {/* boxRef ์„ค์ •ํ•˜๊ธฐ */}
        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae impedit ducimus perferendis, fuga nobis nihil eius similique. Laboriosam fuga doloribus quibusdam cumque beatae! Quae omnis, explicabo possimus molestias nam tempore!
        { ... }
    </div>
</div>

 

์Šคํฌ๋กค์ด ์ƒ์„ฑ๋˜๋Š” div์— boxRef๊ฐ’์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  boxRef์˜ ์Šคํฌ๋กค ๊ฐ’์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ฐ์‹œ(๐Ÿ‘€) ํ•˜์—ฌ ๊ฐ’์— ๋”ฐ๋ผ ์ปจํŠธ๋กค์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

์ €๋Š” ScrollActive๋ฅผ ํ•˜๋‚˜ ์ƒ์„ฑํ•˜์—ฌ ์ปจํŠธ๋กค์„ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

- scroll ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ธฐ : boxRef.current.scrollTop

- scroll ํ–‰์œ„ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜๊ธฐ : addEventListener 

 

const [ScrollY, setScrollY] = useState(0)
    const [ScrollActive, setScrollActive] = useState(false);
    function logit() {
        setScrollY(boxRef.current.scrollTop)
        if(boxRef.current.scrollTop > 30) {  
            setScrollActive(true);
        } else {
            setScrollActive(false);
        }
    }
    useEffect(() => {
        function watchScroll() {  boxRef.current.addEventListener("scroll", logit); }
        watchScroll();
        return () => { boxRef.current.removeEventListener("scroll", logit); }; 
    })
    <div className="box">
                <div className={ScrollActive ? "smallBox fixed" : "smallBox"}>
                    {
                    ScrollActive ? 
                        'I am fixed! โœจ' : 
                        'I will be fixed! ๐Ÿ˜'
                    }
                </div>
                <div className="boxInner" ref={boxRef}> {/* boxRef ์„ค์ •ํ•˜๊ธฐ */}
                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae impedit ducimus perferendis, fuga nobis nihil eius similique. Laboriosam fuga doloribus quibusdam cumque beatae! Quae omnis, explicabo possimus molestias nam tempore!
                    { ... }
                </div>
            </div>

์ „์ฒด ์†Œ์Šค 

 

๋ฐ˜์‘ํ˜•