모달창 스크롤 막기 - modalchang seukeulol maggi

티스토리 뷰

eungwang1 2022. 2. 20. 18:04

모달창을 띄울 때, 스크롤을 비활성화 하는 방법과

모달창이 닫힐 때, 스크롤을 다시 활성화 하는 방법입니다.

// 스크롤 비활성화 const openModal = (e) => { document.body.style.overflow = "hidden"; }; // 스크롤 활성화 const closeModal = (e) => { document.body.style.overflow = "unset"; };

body 태그의 css를 position을 fixed로 변경하고, top을 현재 스크롤 위치로 하고 overflow-y: scroll; width: 100%;을 추가하면 스크롤 방지를 할 수 있다.

해당 css를 변경할 때는 useEffect를 사용할 것이다. 모달이 사라질 때에는 useEffect의 return을 사용해 react-dom0시킨 다음 react-dom1를 이용해 현재 스크롤 위치로 이동시키면 된다.

3-2. 구현 코드

useEffect(() => { document.body.style.cssText = ` position: fixed; top: -${window.scrollY}px; overflow-y: scroll; width: 100%;`; return () => { const scrollY = document.body.style.top; document.body.style.cssText = ''; window.scrollTo(0, parseInt(scrollY || '0', 10) * -1); }; }, []);

4. 마무리

프로그래밍을 잘 모르는 사람이 볼 때는 모달을 컴포넌트 트리에서 빼든 안 빼든 css적으로 동일하다면 상관없을 것이다. 하지만 이런 사소한 부분 하나 하나 모여 코드의 완성도와 깔끔함이 결정된다고 믿기에 이 방법이 좋은 프로그래밍이라고 생각한다.

fixed로 화면을 덮는 모달을 열었을 때 모달창이 덮고 있는데 외부 화면이 스크롤 되는게 어색하다는 QA가 있었다.

모달 open state에 따라 외부 화면도 fixed <-> static으로 변경하면 외부화면도 고정이 되었지만 외부화면의 스크롤이 최상단으로 초기화되는 문제가 있었다.

처음에 생각했던대로 event.preventDefault(); 로 막아야겠다는 생각을 했지만
이벤트 리스너에 scroll이 아닌 wheel 이벤트인 것을 알게되어서 조치할 수 있었다.

  • wheel 같은 passive 이벤트는 preventDefault 사용하려면 passive false가 필요하다

참고

//alvarotrigo.com/blog/prevent-scroll-on-scrollable-element-js/

TIL/2022 TIL

리액트 모달창 세로 스크롤 막기

ryurim 2022. 7. 30. 22:42

반응형

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ모달창을 띄웠는데 !!!!

이럴수가 ?

고수찾기 페이지의 

height 값이 3000px이어서 ..위처럼 스크롤이 되는 끔찍한 ...현상이 발생되었다..

홀..리 ~~~~~~~~~~~~~~

 

웨..웨 !!웨그러는고야 !!!

import React, { useEffect, useState } from "react"; import styled from "styled-components"; interface SearchProModalProps { filterIsOpen: boolean; setFiterIsOpen: any; } const SearchProModal = (props: SearchProModalProps) => { const { filterIsOpen, setFiterIsOpen } = props; const tabTitle: string[] = ["서비스", "지역"]; const [openTab, setOpenTab] = useState<number>(0); const onClickTab = (idx: number) => { setOpenTab(idx); }; const ModalClose = () => { setFiterIsOpen(!filterIsOpen); }; return ( <> <BackDrop onClick={ModalClose} /> <ModalOutter> <ModalSearchBox> <FilterTitle> {tabTitle.map((title, idx) => { return ( <FilterLi key={idx} idx={idx} openTab={openTab} onClick={() => { onClickTab(idx); }} > {title} </FilterLi> ); })} </FilterTitle> <button onClick={ModalClose} /> </ModalSearchBox> </ModalOutter> </> ); }; export default SearchProModal; const BackDrop = styled.div` width: 100%; height: 100vh; position: absolute; top: 0; left: 0; z-index: 999; background: rgba(0, 0, 0, 0.5); `; const ModalOutter = styled.div` width: 420px; height: 42.5rem; overflow-y: scroll; background: #fff; position: absolute; top: 8px; left: 50%; transform: translateX(-50%); z-index: 9999; `; const ModalSearchBox = styled.div` width: 100%; height: 60px; padding: 10px 16px; display: flex; justify-content: space-between; align-items: center; & > button { width: 14px; height: 14px; background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHZpZXdCb3g9IjAgMCAxOCAxOCI+CiAgICA8ZGVmcz4KICAgICAgICA8cGF0aCBpZD0iYSIgZD0iTTkgNy44NjlMMTYuNDM0LjQzNGwxLjEzMiAxLjEzMkwxMC4xMyA5bDcuNDM1IDcuNDM0LTEuMTMyIDEuMTMyTDkgMTAuMTNsLTcuNDM0IDcuNDM1LTEuMTMyLTEuMTMyTDcuODcgOSAuNDM0IDEuNTY2IDEuNTY2LjQzNCA5IDcuODd6Ii8+CiAgICA8L2RlZnM+CiAgICA8dXNlIGZpbGw9IiMzMjMyMzIiIGZpbGwtcnVsZT0ibm9uemVybyIgeGxpbms6aHJlZj0iI2EiLz4KPC9zdmc+Cg==") center; } `; const FilterTitle = styled.ul` width: 96px; height: 40px; font-size: 1rem; display: flex; justify-content: space-between; align-items: center; font-weight: 500; `; interface LiType { idx: number; openTab: number; } const FilterLi = styled.li<LiType>` height: 40px; padding: 0 2px; line-height: 40px; cursor: pointer; color: ${({ openTab, idx }) => (idx === openTab ? "#00c7ae" : "#323232")}; border-bottom: ${({ openTab, idx }) => idx === openTab ? `2px solid #00c7ae` : "none"}; `;

문제의 이전 코드 ..

BackDrop에 .. overflow:hidden을 주어도 아무런 변화가 일어나지 않았다고 한다. 🧐

 

하지만 구글링하다가..ㅋㅋ발견해버렸다 마법의 코드를

 

useEffect(() => { document.body.style.cssText = ` position: fixed; top: -${window.scrollY}px; overflow-y: scroll; width: 100%;`; return () => { const scrollY = document.body.style.top; document.body.style.cssText = ""; window.scrollTo(0, parseInt(scrollY || "0", 10) * -1); }; }, []);

위의 코드만 넣어주면 해결된다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

해결된 모달창의 모습

나이스 !!!

 

원래 오늘의 집 클론코딩에서 숨고 클론코딩으로 바뀌었고,,

내가 맡은 기능은 .. 무시무시한 숨고의 고수찾기 카테고리 기능이다 .. ^^

일단 뷰먼저 해두고..내일..카테고리 시도 해봐야징...핫..

320x100

반응형

Toplist

최신 우편물

태그