[React] sticky Header CSS๊ฐ ๋ณํ๋ sticky Header ๋ง๋ค๊ธฐ์ ์ต์ ํ
์ฌ๋ฌ ์น์ฌ์ดํธ์์๋ scroll๊ณผ ๊ด๊ณ์์ด ์๋จ์ ๋ถ์ด์๋ sticky header๋ฅผ ์์ฃผ ์ฌ์ฉํ๊ณ ์๋๋ฐ์,
์๋ ์์์ ๊ฐ์ด ํน์ ์์ญ์์ css๊ฐ ๋ฐ๋ ์ ์๋ header๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
โ๏ธ ์ฌ์ฉ ์คํ : React, emotion/css
๐ ๊ธฐ๋ณธ ๊ตฌ์กฐ ์์ฑํ๊ธฐ
ํค๋๋ ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์ Header๋ก ๋ถ๋ฆฌํ์ต๋๋ค.
App.js
import { css } from "@emotion/react";
import Header from "./Header.jsx";
export default function App() {
return (
<div className="App" css={wrapStyle}>
<Header />
</div>
);
}
const wrapStyle = css`
`;
Header.jsx
import { css } from "@emotion/react";
export default function Header() {
return <header css={headerStyle}>Header</header>;
}
const headerStyle = (isPoint) => css`
`;
๐ ์๋จ์ Header ๊ณ ์ ์ํค๊ธฐ
CSS๋ฅผ ์๋์ ๊ฐ์ด ์ค์ ํ๊ณ customํ ์ค์ ๋ค์ ํ๋ฉด Header๋ ๊ฐ์ฅ ์๋จ์ ๋ถ์ด์๊ฒ ๋ฉ๋๋ค.
position : sticky
top : 0
import { css } from "@emotion/react";
export default function Header() {
return <header css={headerStyle}>Header</header>;
}
const headerStyle = (isPoint) => css`
height: 44px;
position: sticky;
top: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: #e0e0e0;
`;
๐ Header์ CSS ๊ฐ ๋ฐ๋ ์กฐ๊ฑด ์ค์ ํ๊ธฐ
scroll์ด ์๊ธธ๋งํ body๋ฅผ ๋ง๋ค๊ณ ์ 30 length์ ๋ฐฐ์ด์ ๋ง๋ค๊ฒ ์ต๋๋ค.
๋ชฉํ๋ " 15๋ฒ์งธ <h1>์ ๋ง๋๋ฉด Header์ ์์์ด ๋ณ๊ฒฝ๋๋ ๊ฒ "
App.js
import { css } from "@emotion/react";
import Header from "./Header.jsx";
import { useRef } from "react";
export default function App() {
const pointRef = useRef(null);
return (
<div className="App" css={wrapStyle}>
<Header pointRef={pointRef} />
{new Array(30).fill(0).map((ele, idx) => (
<h1
key={idx}
className={idx >= 15 ? "coloredText" : "text"}
ref={idx === 15 ? pointRef : null}
>
{idx}
</h1>
))}
</div>
);
}
const wrapStyle = css`
.text {
background-color: #f5f5f5;
}
.coloredText {
background-color: #ffb600;
}
`;
Header.jsx
- setPointHeader - point์ง์ (ex 15๋ฒ์งธ h1) window scroll์ด pointRef์ ๋๋ฌํ๋ ์๊ฐ isPoint true ๋ก ์ค์ ํฉ๋๋ค.
- useEffect - addEventListener์๋ return removeEventListener๋ ํด์ค์ผ ํ๋๋ฐ ๊ทธ ์ด์ ๋ React๊ฐ ์ฌ๋ ๋๋ง ๋ ๋๋ง๋ค ์ด๋ฒคํธ ๋์์ ๊ณ์ ๊ฐ์ ํจ์๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ react component๊ฐ unmounted ๋๋ ์์ ์ ์ ํํ ์ ๊ฑฐ๋์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
import { useEffect, useState, useMemo } from "react";
import { css } from "@emotion/react";
export default function Header({ pointRef }) {
const HEADER_HEIGHT = 44;
const [isPoint, setIsPoint] = useState(false);
const setPointHeader = useMemo(
() =>{
const isReachPoint =
window.scrollY > pointRef.current.offsetTop - HEADER_HEIGHT;
if (isReachPoint !== isPoint) setIsPoint(isReachPoint);
}
, [isPoint]
);
useEffect(() => {
window.addEventListener("scroll", setPointHeader);
return () => {
window.removeEventListener("scroll", setPointHeader);
};
}, [isPoint, setPointHeader, pointRef]);
return <header css={headerStyle(isPoint)}>Header</header>;
}
const headerStyle = (isPoint) => css`
height: 44px;
position: sticky;
top: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: ${isPoint ? "#ffb600" : "#e0e0e0"};
`;
๐ throttle๋ก ์ต์ ํ
๊ทธ๋ผ์๋ scoll event๋ scroll ํ ๋๋ง๋ค ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ์ ์ธ ์ต์ ํ๊ฐ ํ์ํฉ๋๋ค.
- throttle: ๊ฐ์ ์ด๋ฒคํธ๊ฐ ๋ฐ๋ณต ์คํ๋ ๋ , ์์ ์ค์ ํ ์๊ฐ ๊ฐ๊ฒฉ (ms) ๋ด์์ ํ๋ฒ์ ์ฝ๋ฐฑํจ์๋ง ํธ์ถํ๊ฒ ํฉ๋๋ค.
Header.jsx
๋ฐ๋ผ์ ์๋์ ๊ฐ์ด 0.3์ด ์ ๋๋ก ์ค์ ํฉ๋๋ค.
// ์ค๋ต
const setPointHeader = useMemo(
() =>
throttle(() => {
const isReachPoint =
window.scrollY > pointRef.current.offsetTop - HEADER_HEIGHT;
if (isReachPoint !== isPoint) setIsPoint(isReachPoint);
}, 300),
[isPoint]
);
๐ฅณ ๊ทธ๋ผ ์๋ฃ
code๋ก ์ง์ ํ์ธํ๊ณ ์ถ๋ค๋ฉด ink_0์ codesandbox - [React] sticky header change CSS in point ๋ก ํ์ธํด์ฃผ์ธ์
[React] sticky header change CSS in point - CodeSandbox
[React] sticky header change CSS in point by ink-0 using @emotion/core, @emotion/css, @emotion/react, emotion, lodash, react, react-dom, react-scripts
codesandbox.io
์ฐธ๊ณ ๋งํฌ
๐ [React] ๋ฆฌ์กํธ ํค๋ ์คํฌ๋กค ์ CSS ๋ณ๊ฒฝ
[React] ๋ฆฌ์กํธ ํค๋ ์คํฌ๋กค ์ CSS ๋ณ๊ฒฝ
ํค๋ ์คํฌ๋กค ์ ๋์์ธ ๋ณ๊ฒฝ Vue์์ ์ ์ํ ์ฝ๋๋ฅผ React๋ก ๋ณํํ๋ ์์ ์ค์ธ๋ฐ ์ฝ๋๊ฐ ๋ฌ๋ผ์ ๋ฆฌ์กํธ ๋ฒ์ ผ์ผ๋ก๋ ์ฌ๋ ค๋ณธ๋ค. iancoding.tistory.com/216 [Vue] ์คํฌ๋กค ์ ํค๋ ์ ๋ณ๊ฒฝ 1. ๋จผ์ data์ scrol
iancoding.tistory.com
๐ [React] scroll ์ด๋ฒคํธ throttle๋ก ์ต์ ํ ์ํค๊ธฐ
[React] scroll ์ด๋ฒคํธ throttle๋ก ์ต์ ํ ์ํค๊ธฐ
Scroll ์ด๋ฒคํธ ์ด๋ฒ ํ๋ก์ ํธ ์งํ ์ค ์คํฌ๋กค์ ์ด๋์ ๋ ํ๋๋์ ๋ฐ๋ผ ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ๋ํ๋๊ณ , ์ฌ๋ผ์ง๊ฒ ํ๋ ๊ธฐ๋ฅ์ด ํ์ํ๋ค. ์ด๋ฅผ ์ํด์ ์ผ๋จ scroll ์ด๋ฒคํธ๋ฅผ ๊ฑธ์ด์ฃผ์ด์ผ ํ๋๋ฐ, scroll ์ด
mengkki.netlify.app
๐ How to Cleanup Event Listeners in React
How to Cleanup React Event Listeners | Pluralsight
When building a UI in React, you'll likely have many events that you want to listen to. That means you'll want to clean them up too. So, what are events, listeners, and why do we want to clean them up?
www.pluralsight.com