[CSS] Calendar가 부모 요소를 벗어나 overflow 되는 현상
작은 모바일 화면에서 Calendar가 부모 요소를 벗어나 overflow되어 스크롤이 생겨버리는 상황
모바일 청첩장 프로젝트에서, 열심히 캘린더를 만들어 레포지토리에 푸쉬했습니다. 그런데…
문제 - 1
이렇게 부모 컨테이너를 벗어나 overflow-scroll이 되어버리는 현상이 발생했습니다.
전체 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
const days = ['일', '월', '화', '수', '목', '금', '토'];
const CalendarContent = () => {
const firstDay = new Date(2025, 3, 1).getDay(); // 화요일 = 2
const lastDate = new Date(2025, 4, 0).getDate(); // 30일
const dates = Array(firstDay)
.fill(null)
.concat([...Array(lastDate)].map((_, i) => i + 1));
return (
<div className="w-full h-full leading-9">
<div className="font-medium text-2xl tracking-wide">2025.04.05</div>
<div className="mb-5 tracking-wider">토요일 오후 3시</div>
<div className="text-center px-10 pb-10">
<Table className="">
<TableHeader>
<TableRow>
{days.map((day, index) => (
<TableHead
key={index}
className={
day === '일' ? 'text-[#c6472b] text-center' : 'text-center'
}
>
{day}
</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{Array.from({ length: Math.ceil(dates.length / 7) }, (_, week) => (
<TableRow key={week}>
{dates.slice(week * 7, (week + 1) * 7).map((date, i) => (
<TableCell
key={i}
className={
(i === 0 ? 'text-[#c6472b]' : '') ||
(date === 5 ? 'bg-[#858585] text-white rounded-full' : '')
}
>
{date || ''}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
);
};
export default CalendarContent;
문제가 되는 부분은 이 부분인 것 같습니다.
1
2
3
4
...
<div className="text-center px-10 pb-10">
<Table className="">
...
현재 shadCn의 UI 컴포넌트를 사용하고 있는데, Table 컴포넌트의 바깥쪽 컨테이너와 안 쪽 컨테이너를 보시면 w-full이 적용되어 있고, 바깥쪽에는 overflow-auto가 적용되어 있는 것을 볼 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="w-full overflow-auto">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
))
Table.displayName = "Table"
트러블 슈팅 - 1
부모 컨테이너의 너비를 벗어나고 있는 애는 table 태그 요녀석이었습니다.
이전 코드를 보니 px-10으로 왼쪽과 오른쪽에 패딩을 주고 있었는데, 이 패딩값과 테이블의 전체 너비가 맞지 않아서 발생하는 문제일 수 있겠다라는 생각을 했습니다.
그래서 px-10을 px-4로 줄여보고, 부모 너비를 넘지 않는 선에서 자신의 컨텐츠 크기만큼 차지하게 하기 위해 테이블 태그에 max-w-full을 적용해보았습니다.
max-w-fullmax-width: 100%를 적용해주는 Tailwind 클래스입니다. 이 속성은 요소가 부모 컨테이너의 너비보다 커지는 것을 방지해줍니다. 즉, 요소가 부모보다 커지려고 하면 부모 width 만큼만 커지도록 제한하고, 요소가 부모보다 작다면 요소의 원래 크기를 유지합니다.
결과 - 1
여전히 overflow되어 scroll이 생겨있었습니다… 그리고 원래 요소의 크기를 유지하다보니 화면의 너비가 커지면 왼쪽에 치우쳤습니다.
트러블 슈팅 - 2
치우쳤다면.. 가운데에 놓으면 되지 않나!
table 태그를 감싸고 있던 div 컨테이너에 flex justify-center 를 추가하고, 스크롤이 생기는 것을 방지하기 위해 overflow-auto를 지워줍니다.
table 태그의 max-w-full은 다시 부모 컨테이너의 100%를 유지하기 위해 w-full로 돌려놔주고, justify-center로 인해 남는 공간을 모두 차지하기 위해 flex-1을 추가합니다.
최종 결과
가로 길이가 제일 작았던 Galaxy Z Fold 5 (344px) 에서도 스크롤과 잘림 없이 제대로 가운데에 위치해있는 걸 볼 수 있었습니다! 성공!
➕ 아예 자식 요소들의 width를 정해줄 수도 있지만 유연하게 가고 싶어서 flex를 선택해봤습니다.