스티커처럼 붙어있는 UI Component를 만들기 위해서 css postion 속성을 조사한 내용을 정리하였다.
문서에 요소를 배치하는 방법을 지정한다.
fixed: 일반적인 문서 흐름 외에서, viewport 기준으로 배치
sticky: 일반적인 문서 흐름에서, 스크롤 되는 parent 요소와
코드 예시로 보면 다음과 같다.
<div id="parent">
<div id="static">static</div>
<div id="sticky">sticky</div>
<div id="relative">relative</div>
<div id="absolute">absolute</div>
<div id="fixed">fixed</div>
<div id="static">static</div>
<div id="static">static</div>
<div id="static">static</div>
</div>
#parent {
background: gray;
position: relative;
width: 500px;
height: 350px;
overflow: auto;
}
#static {
background: red;
height: 100px;
position: static;
}
#relative {
background: orange;
height: 100px;
position: relative;
left: 10px;
top: 10px;
}
#absolute {
background: yellow;
height: 100px;
position: absolute;
top: 10px;
right: 10px;
}
#fixed {
background: green;
height: 100px;
position: fixed;
right: 10px;
top: 10px;
}
#sticky {
background: blue;
height: 100px;
position: -webkit-sticky;
position: sticky;
top: 10px;
}
stacking context는 가상의 Z축을 사용한 HTML 요소의 3차원 개념화라고 한다.
z-index: 크기가 클수록 앞쪽에 배치되고 작을수록 뒤쪽에 배치된다.
stacking context 생기는 조건
https://developer.mozilla.org/ko/docs/Web/CSS/position
https://web.dev/learn/css/z-index/
relative로 배치할 경우 다른 요소에 따라 레이아웃을 다시 하는 reflow과정이 생길 수 있어 fixed 로 선택하여 구현하려고 한다.
1. block 선언
styled component 형태로 div tag block을 선언하고 다른 곳에서 재사용을 고려하여 className을 받았다.
interface StickyProps {
className?: string;
}
const StickyComponent = (props: React.PropsWithChildren<StickyProps>) => {
return (
<StickyBlock className={props.className}>
{props.children}
</StickyBlock>
);
};
const StickyBlock = styled.div`
position: fixed;
`;
2. prop 정의
interface StickyProps {
top: number;
left: number;
backgroudColor?: string;
className?: string;
}
const StickyComponent = (props: React.PropsWithChildren<StickyProps>) => {
return (
<StickyBlock className={props.className} top={props.top} left={props.left}>
{props.children}
</StickyBlock>
);
};
const StickyBlock = styled.div`
position: fixed;
top: ${props => props.top}px;
left: ${props => props.left}px;
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)'};
`;
const PostLikeShareButton = () => {
return (
<PostLikeShareStickyBox top={433} left={30}>
<CircleButton key={1} />
<CircleButton key={2} />
</PostLikeShareStickyBox>
);
};
const PostLikeShareStickyBox = styled(StickyComponent)`
padding: 0.5rem;
flex-direction: column;
@media (max-width: 1024px) {
display: none;
}
`;
결과물은 아직 내부 버튼을 구현하지 않아 휑-한 기분이다. 구현을 목표로 하는 서비스의 sticky component는 relative로 되어있어 본문 옆에 예쁘게 위치해있다. 그에 비해 fixed는 뷰포트 기준이라 위치를 유동적으로 조정하기는 어려운거 같다.
TODO