저번 포스트에서 fixed position 속성으로 구현하였는데 sticky로 변경하려고 한다.
Q. 왜 바꾸는가?
그래서 기존 flow에 따라 순서대로 배치될 수 있는 sticky로 변경!
- sticky in mdn(https://developer.mozilla.org/ko/docs/Web/CSS/position)
"요소를 일반적인 문서 흐름에 따라 배치하고, 테이블 관련 요소를 포함해 가장 가까운, 스크롤 되는 조상과, 표 관련 요소를 포함한 컨테이닝 블록(가장 가까운 블록 레벨 조상) 을 기준으로 top, right, bottom, left의 값에 따라 오프셋을 적용합니다. 오프셋은 다른 요소에는 영향을 주지 않습니다.
이 값은 항상 새로운 쌓임 맥락을 생성합니다. 끈끈한 요소는 "스크롤 동작"(overflow가 hidden, scroll, auto 혹은 overlay)이 존재하는 가장 가까운 조상에 달라붙으며, 사실 그 조상은 스크롤 불가하며 실제로 스크롤 가능한 조상이 따로 존재할 경우 "끈끈한" 동작을 보이지 않는 점에 주의하세요. (W3C CSSWG의 Github 이슈 참조)"
code는 큰 차이 없다. position 속성이랑 상대적 배치로 top과 left를 rem으로 변경!
const StickyComponent = (props: React.PropsWithChildren<StickyProps>) => {
return (
<StickyBlock className={props.className} top={props.top} left={props.left}>
{props.children}
</StickyBlock>
);
};
const StickyBlock = styled.div<StickyProps>`
position: sticky;
top: ${props => props.top}rem;
left: ${props => props.left}rem;
border: 1px solid rgb(241, 243, 245);
border-radius: 2rem;
align-items: center;
-webkit-box-align: center;
background-color: ${props => props.backgroudColor || 'rgb(248, 249, 250)'};
`;
그리고 부모 노드에서 사용할 때 height를 지정하고 px값으로 주던걸 rem값으로 변경!
const PostLikeShareButton = () => {
return (
<PostLikeShareStickyBox top={10} left={1}>
<CircleButton key={1} />
<CircleButton key={2} />
</PostLikeShareStickyBox>
);
};
const PostLikeShareStickyBox = styled(StickyComponent)`
padding: 0.5rem;
height: 6.5rem;
flex-direction: column;
@media (max-width: 1024px) {
display: none;
}
`;
sticky 동작은 scroll 가능한 부모 노드기준으로 임계치까지 relative처럼 동작하고 그 후 fixed로 동작한다.
relative로 일부 동작하면 성능에 차이가 심할까싶어 측정도 해봤다.
composite layers에서 차이가 있는 것으로 보인다.
하지만 5sec도 아닌 5ms이면...음...
시간을 좀 들여서 기능에 초점을 둬도 좋을거 같다.
폴리필 패키지를 설치하거나, media 쿼리로 사용하는 방법 두가지로 좁혀졌었다.
const StickyBlock = styled.div<StickyProps>`
position: sticky;
top: ${props => props.top}rem;
left: ${props => props.left}rem;
border: 1px solid rgb(241, 243, 245);
border-radius: 2rem;
align-items: center;
-webkit-box-align: center;
background-color: ${props => props.backgroudColor || 'rgb(248, 249, 250)'};
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
position: fixed;
}
`;
아쉽게도 이 기능을 넣기 전부터 토이프로젝트가 i*에서 켜지지 않았다.^^...