그리드
그리드 (Grid)
24 컬럼 기반의 반응형 그리드 레이아웃 컴포넌트예요. Row와 Col을 조합해 정보 영역을 안정적으로 나누고 정렬할 수 있어요.
출처: 문서
본문
디자인 컨셉 (Design concept)
대부분의 비즈니스 상황에서 Ant Design은 디자인 영역 안의 많은 정보 저장 문제를 해결해야 해요. 그래서 12 그리드 시스템을 기반으로 디자인 영역을 24개 섹션으로 나눴어요.
나뉜 영역을 'box'라고 부르며, 가로로 최대 4개, 최소 1개의 box 배치를 권장해요. box는 그림처럼 전체 화면에 비례해요. 높은 수준의 시각적 편안함을 보장하기 위해 box 단위를 기반으로 box 안의 타이포그래피를 커스터마이즈해요.
개요 (Outline)
그리드 시스템에서 정보 영역 바깥의 프레임을 row와 column으로 정의해, 모든 영역이 안정적으로 배치되도록 해요.
동작 방식은 간단히 이렇습니다.
row가 정의한 가로 공간 안에column세트를 만든다 (col로 줄여 말해요).- 콘텐츠 요소는
col에 직접 넣어야 하고,row에는col만 직접 넣어야 해요. - 컬럼 그리드 시스템은 1-24 값을 그 범위로 나타내요. 예를 들어
<Col span={8} />으로 동일한 너비의 3개 컬럼을 만들 수 있어요. - 한
row안의colspan 합이 24를 넘으면, 넘친col전체가 새 줄로 배치돼요.
우리 그리드 시스템은 Flex 레이아웃을 기반으로 해서 부모 안의 요소를 가로로 정렬할 수 있어요. 왼쪽, 중앙, 오른쪽, 넓게, 분산 배치 등이 가능하고요. 세로 정렬(위쪽, 세로 중앙, 아래쪽)도 지원하며 order로 요소의 순서를 정의할 수도 있어요.
레이아웃은 24 그리드 레이아웃을 사용해 각 'box'의 너비를 정의하지만, 그리드 레이아웃에 딱딱하게 얽매이지는 않아요.
예시 (Examples)
기본 그리드 (Basic Grid)
스택에서 가로 배치로 나아가는 예시예요.
단일 Row와 Col 그리드 조합으로 기본 그리드 시스템을 만들 수 있어요. 모든 컬럼(Col)은 Row 안에 배치돼야 해요.
import React from 'react';
import { Col, Row } from 'antd';
const App: React.FC = () => (
<>
<Row>
<Col span={24}>col</Col>
</Row>
<Row>
<Col span={12}>col-12</Col>
<Col span={12}>col-12</Col>
</Row>
<Row>
<Col span={8}>col-8</Col>
<Col span={8}>col-8</Col>
<Col span={8}>col-8</Col>
</Row>
<Row>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
</Row>
</>
);
export default App;
그리드 거터 (Grid Gutter)
Row의 gutter 속성을 그리드 간격으로 사용할 수 있어요. (16 + 8n) px(n은 자연수)로 설정하는 것을 권장해요.
반응형 디자인을 위해 { xs: 8, sm: 16, md: 24, lg: 32 } 같은 객체로도 설정할 수 있어요.
배열로 세로 간격을 설정할 수도 있어요. [horizontal, vertical] 형식으로 [16, { xs: 8, sm: 16, md: 24, lg: 32 }]와 같아요.
gutter를 string CSS 단위로도 설정할 수 있어요. 예: px, rem, vw, vh 등.
세로(vertical) gutter는
3.24.0이후 지원됐고, string 타입은5.28.0이후 지원됐어요.
import React from 'react';
import { Col, Divider, Row } from 'antd';
const style: React.CSSProperties = {
padding: '8px 0',
backgroundColor: '#0092ff',
};
const App: React.FC = () => (
<>
<Divider titlePlacement="start">Horizontal</Divider>
<Row gutter={16}>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
</Row>
<Divider titlePlacement="start">Responsive</Divider>
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
</Row>
<Divider titlePlacement="start">Vertical</Divider>
<Row gutter={[16, 24]}>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
</Row>
<Divider titlePlacement="start">Gutter(string)</Divider>
<Row gutter="2rem">
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
<Col className="gutter-row" span={6}>
<div style={style}>col-6</div>
</Col>
</Row>
</>
);
export default App;
컬럼 오프셋 (Column offset)
offset으로 컬럼을 오른쪽으로 옮길 수 있어요. 예를 들어 offset = {4}를 사용하면 요소가 오른쪽으로 4 컬럼 너비만큼 이동해요.
import React from 'react';
import { Col, Row } from 'antd';
const App: React.FC = () => (
<>
<Row>
<Col span={8}>col-8</Col>
<Col span={8} offset={8}>
col-8
</Col>
</Row>
<Row>
<Col span={6} offset={6}>
col-6 col-offset-6
</Col>
<Col span={6} offset={6}>
col-6 col-offset-6
</Col>
</Row>
<Row>
<Col span={12} offset={6}>
col-12 col-offset-6
</Col>
</Row>
</>
);
export default App;
그리드 정렬 (Grid sort)
push와 pull 클래스를 사용하면 컬럼 순서를 쉽게 바꿀 수 있어요.
import React from 'react';
import { Col, Row } from 'antd';
const App: React.FC = () => (
<Row>
<Col span={18} push={6}>
col-18 col-push-6
</Col>
<Col span={6} pull={18}>
col-6 col-pull-18
</Col>
</Row>
);
export default App;
정판 (Typesetting)
자식 요소는 부모 노드의 정판 모드에 정의된 start, center, end, space-between, space-around, space-evenly 값에 따라 배치돼요.
import React from 'react';
import { Col, Divider, Row } from 'antd';
import { createStyles } from 'antd-style';
const useStyles = createStyles((props) => {
const { css } = props;
return {
rowContainer: css`
background-color: rgba(128, 128, 128, 0.08);
`,
};
});
const App: React.FC = () => {
const { styles } = useStyles();
return (
<>
<Divider titlePlacement="start">sub-element align left</Divider>
<Row className={styles.rowContainer} justify="start">
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
</Row>
<Divider titlePlacement="start">sub-element align center</Divider>
<Row className={styles.rowContainer} justify="center">
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
</Row>
<Divider titlePlacement="start">sub-element align right</Divider>
<Row className={styles.rowContainer} justify="end">
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
</Row>
<Divider titlePlacement="start">sub-element monospaced arrangement</Divider>
<Row className={styles.rowContainer} justify="space-between">
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
</Row>
<Divider titlePlacement="start">sub-element align full</Divider>
<Row className={styles.rowContainer} justify="space-around">
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
</Row>
<Divider titlePlacement="start">sub-element align evenly</Divider>
<Row className={styles.rowContainer} justify="space-evenly">
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
<Col span={4}>col-4</Col>
</Row>
</>
);
};
export default App;
정렬 (Alignment)
자식 요소를 세로로 정렬해요.
import React from 'react';
import { Col, Divider, Row } from 'antd';
import { createStyles } from 'antd-style';
const useStyles = createStyles((props) => {
const { css } = props;
return {
rowContainer: css`
background-color: rgba(128, 128, 128, 0.08);
`,
};
});
const DemoBox: React.FC<React.PropsWithChildren<{ value: number }>> = (props) => {
const { value, children } = props;
return <p className={`height-${value}`}>{children}</p>;
};
const App: React.FC = () => {
const { styles } = useStyles();
return (
<>
<Divider titlePlacement="start">Align Top</Divider>
<Row className={styles.rowContainer} justify="center" align="top">
<Col span={4}>
<DemoBox value={100}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={50}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={120}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={80}>col-4</DemoBox>
</Col>
</Row>
<Divider titlePlacement="start">Align Middle</Divider>
<Row className={styles.rowContainer} justify="space-around" align="middle">
<Col span={4}>
<DemoBox value={100}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={50}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={120}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={80}>col-4</DemoBox>
</Col>
</Row>
<Divider titlePlacement="start">Align Bottom</Divider>
<Row className={styles.rowContainer} justify="space-between" align="bottom">
<Col span={4}>
<DemoBox value={100}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={50}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={120}>col-4</DemoBox>
</Col>
<Col span={4}>
<DemoBox value={80}>col-4</DemoBox>
</Col>
</Row>
</>
);
};
export default App;
순서 (Order)
order로 요소 정렬을 바꿔요.
import React from 'react';
import { Col, Divider, Row } from 'antd';
import { createStyles } from 'antd-style';
const useStyles = createStyles((props) => {
const { css } = props;
return {
rowContainer: css`
background-color: rgba(128, 128, 128, 0.08);
`,
};
});
const App: React.FC = () => {
const { styles } = useStyles();
return (
<>
<Divider titlePlacement="start">Normal</Divider>
<Row className={styles.rowContainer}>
<Col span={6} order={4}>
1 col-order-4
</Col>
<Col span={6} order={3}>
2 col-order-3
</Col>
<Col span={6} order={2}>
3 col-order-2
</Col>
<Col span={6} order={1}>
4 col-order-1
</Col>
</Row>
<Divider titlePlacement="start">Responsive</Divider>
<Row className={styles.rowContainer}>
<Col span={6} xs={{ order: 1 }} sm={{ order: 2 }} md={{ order: 3 }} lg={{ order: 4 }}>
1 col-order-responsive
</Col>
<Col span={6} xs={{ order: 2 }} sm={{ order: 1 }} md={{ order: 4 }} lg={{ order: 3 }}>
2 col-order-responsive
</Col>
<Col span={6} xs={{ order: 3 }} sm={{ order: 4 }} md={{ order: 2 }} lg={{ order: 1 }}>
3 col-order-responsive
</Col>
<Col span={6} xs={{ order: 4 }} sm={{ order: 3 }} md={{ order: 1 }} lg={{ order: 2 }}>
4 col-order-responsive
</Col>
</Row>
</>
);
};
export default App;
Flex 늘리기 (Flex Stretch)
Col은 나머지를 채우는 flex prop을 제공해요.
import React from 'react';
import { Col, Divider, Row } from 'antd';
const App: React.FC = () => (
<>
<Divider titlePlacement="start">Percentage columns</Divider>
<Row>
<Col flex={2}>2 / 5</Col>
<Col flex={3}>3 / 5</Col>
</Row>
<Divider titlePlacement="start">Fill rest</Divider>
<Row>
<Col flex="100px">100px</Col>
<Col flex="auto">Fill Rest</Col>
</Row>
<Divider titlePlacement="start">Raw flex style</Divider>
<Row>
<Col flex="1 1 200px">1 1 200px</Col>
<Col flex="0 1 300px">0 1 300px</Col>
</Row>
<Row wrap={false}>
<Col flex="none">
<div style={{ padding: '0 16px' }}>none</div>
</Col>
<Col flex="auto">auto with no-wrap</Col>
</Row>
</>
);
export default App;
반응형 (Responsive)
Bootstrap의 반응형 디자인을 참고해 일곱 가지 크기를 프리셋으로 제공해요. xs sm md lg xl xxl xxxl.
import React from 'react';
import { Col, Row } from 'antd';
const App: React.FC = () => (
<Row>
<Col xs={2} sm={4} md={6} lg={8} xl={10}>
Col
</Col>
<Col xs={20} sm={16} md={12} lg={8} xl={4}>
Col
</Col>
<Col xs={2} sm={4} md={6} lg={8} xl={10}>
Col
</Col>
</Row>
);
export default App;
Flex 반응형 (Flex Responsive)
더 유연한 반응형 flex 비율을 지원해요. 브라우저가 지원하는 CSS Variables가 필요해요.
import React from 'react';
import { Col, Row } from 'antd';
const App: React.FC = () => (
<Row>
{Array.from({ length: 10 }).map((_, index) => {
const key = `col-${index}`;
return (
<Col
key={key}
xs={{ flex: '100%' }}
sm={{ flex: '50%' }}
md={{ flex: '40%' }}
lg={{ flex: '20%' }}
xl={{ flex: '10%' }}
>
Col
</Col>
);
})}
</Row>
);
export default App;
더 많은 반응형 (More responsive)
span pull push offset order 속성을 xs sm md lg xl xxl 속성 안에 넣어 사용할 수 있어요. 여기서 xs={6}은 xs={{span: 6}}과 같아요.
import React from 'react';
import { Col, Row } from 'antd';
const App: React.FC = () => (
<Row>
<Col xs={{ span: 5, offset: 1 }} lg={{ span: 6, offset: 2 }}>
Col
</Col>
<Col xs={{ span: 11, offset: 1 }} lg={{ span: 6, offset: 2 }}>
Col
</Col>
<Col xs={{ span: 5, offset: 1 }} lg={{ span: 6, offset: 2 }}>
Col
</Col>
</Row>
);
export default App;
놀이터 (Playground)
컬럼 수와 gutter를 조절해 볼 수 있는 간단한 놀이터예요.
import React, { useState } from 'react';
import { Col, Row, Slider } from 'antd';
import { createStyles } from 'antd-style';
const useStyles = createStyles((props) => {
const { css, cssVar } = props;
return {
colContainer: css`
border: 0;
padding-block: 0 !important;
background-color: transparent !important;
`,
box: css`
height: 120px;
font-size: ${cssVar.fontSize};
line-height: 120px;
background-color: #0092ff;
border-radius: ${cssVar.borderRadiusSM};
`,
code: css`
direction: ltr;
padding: ${cssVar.paddingXS} ${cssVar.padding};
font-size: ${cssVar.fontSize};
background-color: #f9f9f9;
border-radius: ${cssVar.borderRadius};
`,
};
});
const gutters: Record<PropertyKey, number> = {};
const vgutters: Record<PropertyKey, number> = {};
const colCounts: Record<PropertyKey, number> = {};
[8, 16, 24, 32, 40, 48].forEach((value, i) => {
gutters[i] = value;
});
[8, 16, 24, 32, 40, 48].forEach((value, i) => {
vgutters[i] = value;
});
[2, 3, 4, 6, 8, 12].forEach((value, i) => {
colCounts[i] = value;
});
const App: React.FC = () => {
const { styles } = useStyles();
const [gutterKey, setGutterKey] = useState(1);
const [vgutterKey, setVgutterKey] = useState(1);
const [colCountKey, setColCountKey] = useState(2);
const cols: React.ReactNode[] = [];
const colCount = colCounts[colCountKey];
let colCode = '';
for (let i = 0; i < colCount; i++) {
cols.push(
<Col className={styles.colContainer} key={i.toString()} span={24 / colCount}>
<div className={styles.box}>Column</div>
</Col>,
);
colCode += ` <Col span={${24 / colCount}} />\n`;
}
return (
<>
<span>Horizontal Gutter (px): </span>
<div style={{ width: '50%' }}>
<Slider
min={0}
max={Object.keys(gutters).length - 1}
value={gutterKey}
onChange={setGutterKey}
marks={gutters}
step={null}
tooltip={{ formatter: (value) => gutters[value as number] }}
/>
</div>
<span>Vertical Gutter (px): </span>
<div style={{ width: '50%' }}>
<Slider
min={0}
max={Object.keys(vgutters).length - 1}
value={vgutterKey}
onChange={setVgutterKey}
marks={vgutters}
step={null}
tooltip={{ formatter: (value) => vgutters[value as number] }}
/>
</div>
<span>Column Count:</span>
<div style={{ width: '50%', marginBottom: 48 }}>
<Slider
min={0}
max={Object.keys(colCounts).length - 1}
value={colCountKey}
onChange={setColCountKey}
marks={colCounts}
step={null}
tooltip={{ formatter: (value) => colCounts[value as number] }}
/>
</div>
<Row gutter={[gutters[gutterKey], vgutters[vgutterKey]]}>
{cols}
{cols}
</Row>
Another Row:
<Row gutter={[gutters[gutterKey], vgutters[vgutterKey]]}>{cols}</Row>
<pre
className={styles.code}
>{`<Row gutter={[${gutters[gutterKey]}, ${vgutters[vgutterKey]}]}>\n${colCode}\n${colCode}</Row>`}</pre>
<pre
className={styles.code}
>{`<Row gutter={[${gutters[gutterKey]}, ${vgutters[vgutterKey]}]}>\n${colCode}</Row>`}</pre>
</>
);
};
export default App;
useBreakpoint 훅 (useBreakpoint Hook)
useBreakpoint 훅으로 개인화된 레이아웃을 제공해요. xs는 화면이 최소 너비와 일치할 때만 적용돼요.
import React from 'react';
import { Grid, Tag } from 'antd';
const { useBreakpoint } = Grid;
const App: React.FC = () => {
const screens = useBreakpoint();
return (
<>
Current break point:{' '}
{Object.entries(screens)
.filter((screen) => !!screen[1])
.map((screen) => (
<Tag color="blue" key={screen[0]}>
{screen[0]}
</Tag>
))}
</>
);
};
export default App;
API
공통 props는 Common props를 참고해요.
Ant Design 그리드 레이아웃 컴포넌트가 요구를 충족하지 못한다면, 커뮤니티의 훌륭한 레이아웃 컴포넌트를 사용할 수 있어요.
Row
| 속성 (Property) | 설명 (Description) | 타입 (Type) | 기본값 (Default) | 버전 (Version) | 글로벌 설정 |
|---|---|---|---|---|---|
| align | 세로 정렬 | top | middle | bottom | stretch | {[key in 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'xxxl']: 'top' | 'middle' | 'bottom' | 'stretch'} |
top |
object: 4.24.0 | × |
| gutter | 그리드 사이 간격이에요. string CSS 단위이거나 { xs: 8, sm: 16, md: 24} 같은 객체일 수 있어요. 또는 배열을 사용해 가로·세로 간격을 동시에 적용할 수도 있어요. [horizontal, vertical] |
number | string | object | array | 0 | string: 5.28.0 | × |
| justify | 가로 배치 | start | end | center | space-around | space-between | space-evenly | {[key in 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'xxxl']: 'start' | 'end' | 'center' | 'space-around' | 'space-between' | 'space-evenly'} |
start |
object: 4.24.0 | × |
| wrap | 자동 줄바꿈 | boolean | true | 4.8.0 | × |
Col
| 속성 (Property) | 설명 (Description) | 타입 (Type) | 기본값 (Default) | 버전 (Version) | 글로벌 설정 |
|---|---|---|---|---|---|
| flex | Flex 레이아웃 스타일이에요. 숫자는 'flex: n n auto', 문자열은 직접 적용돼요. (순수 숫자 문자열 'n'은 'flex: n 1 0'.) | string | number | - | × | |
| offset | Col을 왼쪽에서 이동시킬 셀 수 | number | 0 | × | |
| order | 레스터 순서 | number | 0 | × | |
| pull | 레스터가 왼쪽으로 이동하는 셀 수 | number | 0 | × | |
| push | 레스터가 오른쪽으로 이동하는 셀 수 | number | 0 | × | |
| span | 점유할 레스터 셀 수예요. 0은 display: none에 해당해요. |
number | - | × | |
| xs | screen < 576px이며 기본 설정이기도 해요. span 값 또는 위 속성을 담은 객체일 수 있어요. |
number | object | - | × | |
| sm | screen ≥ 576px. span 값 또는 위 속성을 담은 객체일 수 있어요. |
number | object | - | × | |
| md | screen ≥ 768px. span 값 또는 위 속성을 담은 객체일 수 있어요. |
number | object | - | × | |
| lg | screen ≥ 992px. span 값 또는 위 속성을 담은 객체일 수 있어요. |
number | object | - | × | |
| xl | screen ≥ 1200px. span 값 또는 위 속성을 담은 객체일 수 있어요. |
number | object | - | × | |
| xxl | screen ≥ 1600px. span 값 또는 위 속성을 담은 객체일 수 있어요. |
number | object | - | × | |
| xxxl | screen ≥ 1920px. span 값 또는 위 속성을 담은 객체일 수 있어요. |
number | object | - | 6.3.0 | × |
테마 커스터마이즈로 screen[XS|SM|MD|LG|XL|XXL|XXXL]을 수정해 브레이크포인트 값을 바꿀 수 있어요. (5.1.0부터, 샌드박스 데모.)
반응형 그리드의 브레이크포인트는 BootStrap 4 media queries 규칙을 따릅니다. (occasionally part는 제외.)
디자인 토큰 (Design Token)
Grid의 컴포넌트 토큰 테이블은 공식 문서에서 확인할 수 있어요. (ComponentTokenTable)