Flexible Template은 CSS Flexbox(CSS Flexible Box) 권고안을 기반으로 보다 정교하게 레이아웃을 구성할 수 있다. CSS Flexbox 권고안의 'Flex container'는 Flexible Template의 박스 컴포넌트에 해당하고, 'Flex item'은 Flexible Template의 컴포넌트에 해당한다.
이 문서에서는 전체 레이아웃을 조정하고 박스 하위에 추가된 컴포넌트의 크기와 위치를 설정하는 방법을 설명한다. JSON 스키마에 대한 자세한 내용은 Flexible Template 문서를 참고한다.
박스의 주축 방향을 결정함으로써 박스 하위에 추가된 컴포넌트(자식 요소)의 배치 방향을 결정할 수 있다. 박스 내 컴포넌트 배치 방향은 3가지 레이아웃 타입으로 지정할 수 있다.
박스 내 컴포넌트의 배치 방향은 box의 layout 속성에 의해 지정된다.
| 레이아웃 타입 ( layout 속성값) | 설명 |
|---|---|
| horizontal | 박스 내 컴포넌트를 수평으로 배치한다. 박스 내 컴포넌트의 배치 방향은 bubble의 direction 속성으로 지정된다.이러한 레이아웃 타입으로 된 박스를 수평 박스(horizontal box)라고 한다. |
| vertical | 박스 내 컴포넌트를 수직으로 배치한다. 이러한 레이아웃 타입으로 된 박스를 수직 박스(vertical box)라고 한다. |
| baseline | 박스 내 컴포넌트를 수평 박스와 같은 방향으로 배치한다. 수평 박스와의 차이점에 대한 자세한 내용은 베이스라인 박스의 특징을 참고한다. 이러한 레이아웃 타입으로 된 박스를 베이스라인 박스(baseline box)라고 한다. |
박스 하위에 추가할 수 있는 컴포넌트는 박스 타입에 따라 달라진다.
| 수평 박스 | 수직 박스 | 베이스라인 박스 | |
|---|---|---|---|
| 박스(box) | O | O | X |
| 버튼(button) | O | O | X |
| 이미지(image) | O | O | X |
| 아이콘(icon) | X | X | O |
| 텍스트(text) | O | O | O |
| 스팬(span) ※ 텍스트 하위에 추가 가능 | X | X | X |
| 구분선(separator) | O | O | X |
| 필러(filler) | O | O | O |
베이스라인 박스(baseline box)는 수평 박스와 동일한 방식으로 동작한다. 하지만 다음과 같은 경우에는 수평 박스와 동작하는 방식이 다르다.
수직 정렬은 텍스트의 기준선에 맞춰 고정된다. 또한 문자열 크기가 다른 텍스트도 텍스트의 기준선에 맞춰 정렬된다.
Icon 컴포넌트의 기준선 또한 해당 이미지 파일의 하단에 맞춰진다.

다음 속성은 베이스라인 박스에서 사용할 수 없다.
gravity 속성offsetBottom 속성(향후 지원 예정)position 속성을 relative 로 설정한 컴포넌트의 너비 또는 높이는 각 컴포넌트의 flex 속성에 의해 결정된다.
수평 박스에서 컴포넌트의 flex 속성이 1 이상으로 설정되면, 해당 값을 기준으로 컴포넌트에 여백이 분배된다. 수평 박스 내 컴포넌트의 flex 속성 기본값은 1 이다.
예를 들어, 수평 박스 내 컴포넌트 2개의 flex 속성값이 각각 2 와 3 이면, 여백(이 예시에서는 박스의 너비)이 2:3 비율로 각 컴포넌트에 분배된다.

위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "horizontal", "contents": [ { "type": "text", "text": "The work site begins to move; the work site is coming in sight; the work is going on. Expand business communications with us!", "wrap": true, "color": "#ff0000", "flex": 2 }, { "type": "text", "text": "The work site begins to move; the work site is coming in sight; the work is going on. Expand business communications with us!", "wrap": true, "color": "#0000ff", "flex": 3 } ] }}flex 속성값이 0 이면, 컴포넌트의 너비가 해당 컴포넌트의 전체 크기로 유지된다. 다만 컴포넌트의 너비가 상위 박스 너비를 초과하면, 초과된 영역은 표시되지 않는다.
아래 예시에는 flex 속성이 각각 0, 2, 3 으로 지정된 3개의 컴포넌트가 있다. 첫 번째 컴포넌트의 flex 속성은 0 이므로 컴포넌트에 설정된 ‘Hello’ 문자열을 표시할 수 있는 너비가 우선 확보된다. 이후 여백(상위 박스의 너비에서 첫 번째 컴포넌트의 너비를 제외한 부분)이 2:3 비율로 분할되어 두 번째와 세 번째 컴포넌트에 할당된다.

위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "horizontal", "contents": [ { "type": "text", "text": "Hello", "color": "#00ff00", "flex": 0 }, { "type": "text", "text": "The work site begins to move; the work site is coming in sight; the work is going on. Expand business communications with us!", "wrap": true, "color": "#ff0000", "flex": 2 }, { "type": "text", "text": "The work site begins to move; the work site is coming in sight; the work is going on. Expand business communications with us!", "wrap": true, "color": "#0000ff", "flex": 3 } ] }}CSS Flexbox의
flex와의 대응 관계
- 수평 박스의
flex속성은 CSS Flexbox의flex에 다음과 같이 대응된다.
flex = 0은 CSS Flexbox의flex: 0 0 auto에 대응flex = 0을 초과하면, CSS Flexbox의flex: X 0 0에 대응(여기서 X는flex값)
수직 박스에서 컴포넌트의 flex 속성값을 1 이상으로 지정하면, 해당 값을 기준으로 컴포넌트에 여백이 분배된다. 수직 박스 내 컴포넌트의 flex 속성 기본값은 0 이다.

위 예시에서 각 컴포넌트는 아래 규칙에 따라 배치된다.
2 와 3)을 기준으로 2:3 으로 분할되어 각 컴포넌트에 할당된다.위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "horizontal", "contents": [ { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "wrap": true, "text": "TEXT\nTEXT\nTEXT\nTEXT\nTEXT" } ], "backgroundColor": "#c0c0c0" }, { "type": "box", "layout": "vertical", "contents": [ { "type": "separator", "color": "#ff0000" }, { "type": "text", "text": "flex=2", "flex": 2 }, { "type": "separator", "color": "#ff0000" }, { "type": "text", "text": "flex=3", "flex": 3 }, { "type": "separator", "color": "#ff0000" } ] } ] }}CSS Flexbox의
flex와의 대응 관계
- 수직 박스의
flex속성은 CSS Flexbox의flex에 다음과 같이 대응한다.
flex = 0은 CSS Flexbox의flex: 0 0 auto에 대응flex = 0을 초과하면, CSS Flexbox의flex: X 0 auto에 대응(여기서 X는flex값)
박스의 너비는 width 속성으로 지정한다. %(상위 컴포넌트의 너비를 기준으로 한 비율) 또는 픽셀 단위로 지정할 수 있다.
단, 수평 박스 또는 베이스라인 박스에서 width 속성을 지정하면 flex 속성이 0 으로 설정된다.
width속성을 픽셀 단위로 지정하는 경우
- 버블의 너비는 표시되는 화면의 크기에 따라 달라진다. 전체 버블의 레이아웃을 조정하기 위해
width속성을 픽셀 단위로 지정하면 기기에 따라 의도하지 않은 레이아웃으로 표시될 수 있다. 화면 크기로 인한 레이아웃 변형을 최소화하려면flex속성 사용을 권장한다.
박스의 높이는 height 속성으로 지정한다. %(상위 컴포넌트의 높이를 기준으로 한 비율) 또는 픽셀 단위로 지정할 수 있다.
단, 수직 박스에서 height 속성을 지정하면 flex 속성이 0 으로 설정된다.
버튼과 이미지 등의 컴포넌트 크기는 flex와 다른 속성으로 지정할 수 있다. JSON 스키마에 대한 자세한 내용은 Flexible Template 문서를 참고한다.
박스에 여백이 있으면, 각 컴포넌트를 수직/수평으로 정렬하도록 지정할 수 있다.
수직 박스의 수평 정렬(교차축 방향)은 align 속성으로 지정한다. 아래의 속성값 중 하나를 지정하면 된다.
start: 왼쪽 정렬(기본값)center: 가운데 정렬end: 오른쪽 정렬
위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "text": "align=start", "align": "start" }, { "type": "separator", "color": "#ff0000" }, { "type": "text", "text": "align=center", "align": "center" }, { "type": "separator", "color": "#ff0000" }, { "type": "text", "text": "align=end", "align": "end" } ] }}수평 박스의 수직 정렬(교차축 방향)은 gravity 속성으로 지정한다. 아래의 속성값 중 하나를 지정하면 된다.
top: 위쪽 정렬(기본값)center: 가운데 정렬bottom: 아래쪽 정렬참고
- 이 속성은 베이스라인 박스에서는 적용되지 않는다.

위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "horizontal", "contents": [ { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "wrap": true, "text": "TEXT\nTEXT\nTEXT\nTEXT\nTEXT" } ], "backgroundColor": "#c0c0c0" }, { "type": "text", "text": "top", "gravity": "top" }, { "type": "text", "text": "center", "gravity": "center" }, { "type": "text", "text": "bottom", "gravity": "bottom" } ] }}박스의 패딩(안쪽 여백)은 paddingAll, paddingTop, paddingBottom, paddingStart, paddingEnd 속성으로 지정한다. 박스 패딩은 박스의 경계선과 하위 컴포넌트 사이 여백의 크기를 의미한다. 패딩의 값은 %(박스 너비를 기준으로 한 비율) 또는 픽셀 단위로 지정하거나, none, xs, sm, md, lg, xl, xxl 중 하나로 지정할 수 있다. 값을 none 으로 지정하면 여백이 생기지 않으며, 그 외의 값들은 열거된 순으로 여백의 크기가 커진다.
paddingAll 속성 외에 추가로 paddingTop, paddingBottom, paddingStart, paddingEnd 속성에도 값을 지정할 경우paddingAll 속성에 지정한 값은 무시된다.

위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "horizontal", "contents": [ { "type": "box", "layout": "horizontal", "contents": [ { "type": "text", "text": "hello, world" } ], "backgroundColor": "#ffffff" } ], "backgroundColor": "#ffd2d2", "paddingTop": "20px", "paddingAll": "80px", "paddingStart": "40px" }}위 Flexible Template 예시에서 긴 문자열을 입력하면 아래와 같은 레이아웃이 된다.

하위에 컴포넌트가 있는 박스에 spacing 속성을 지정하면 하위 컴포넌트들 사이 간격을 지정할 수 있다. none, xs, sm, md, lg, xl, xxl 중 하나의 값으로 지정한다. 값을 none 으로 지정하면 간격이 생기지 않으며, 그 외의 값들은 열거된 순으로 간격의 크기가 커진다.
아래 Flexible Template에서는 3개의 수직 박스가 수평 박스에 동일한 간격(md)으로 배치되어 있다.

위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "horizontal", "spacing": "md", "contents": [ { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "text": "TEXT1" } ], "backgroundColor": "#80ffff" }, { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "text": "TEXT2" } ], "backgroundColor": "#80ffff" }, { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "text": "TEXT3" } ], "backgroundColor": "#80ffff" } ] }}※ 특정 컴포넌트만 간격이 적용되지 않게 하려면 해당 컴포넌트에 margin 속성을 지정하면 된다.
컴포넌트에 margin 속성을 지정하면 바로 앞에 있는 컴포넌트와의 간격을 설정할 수 있다. none, xs, sm, md, lg, xl, xxl 중 하나의 값을 지정한다. 값을 none 으로 지정하면 간격이 생기지 않으며, 그 외의 값들은 열거된 순으로 간격의 크기가 커진다.
참고
margin속성은 상위 컴포넌트의spacing속성보다 우선한다. 또한 박스 내에서 가장 앞에 있는 컴포넌트에margin속성을 지정하면 레이아웃에 간격이 발생하지 않는다.
아래 Flexible Template에서는 수평 박스 안에 3개의 수직 박스가 추가되어 있다. 수평 박스의 spacing 속성은 md 로 설정되어 있으며, 세 번째 수직 박스의 margin 속성은 xxl 로 설정되어 있다.

위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "horizontal", "spacing": "md", "contents": [ { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "text": "TEXT1" } ], "backgroundColor": "#80ffff" }, { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "text": "TEXT2" } ], "backgroundColor": "#80ffff" }, { "type": "box", "layout": "vertical", "contents": [ { "type": "text", "text": "TEXT3" } ], "backgroundColor": "#80ffff", "margin": "xxl" } ] }}컴포넌트의 배치는 아래의 속성을 지정하여 조정할 수도 있다.
position 속성position 속성 설정에 따라 달라진다. 또한 블록 바로 아래에 있는 박스에는 absolute 를 지정할 수 없다.offsetTop 속성, offsetBottom 속성, offsetStart 속성, offsetEnd 속성none, xs, sm, md, lg, xl, or xxl 중 하나의 값을 지정할 수 있다.아래 Flexible Template은 오프셋의 효과를 설명하기 위해 ‘TARGET’ 문자열이 있는 수평 상자의 속성을 변경하는 예시이다.

위 Flexible Template은 아래의 JSON 데이터를 사용하여 구현할 수 있다.
{ "type": "bubble", "body": { "type": "box", "layout": "vertical", "contents": [ { "type": "box", "layout": "horizontal", "contents": [ { "type": "text", "text": "REFERENCE BOX\n1\n2\n3", "align": "center", "wrap": true } ], "backgroundColor": "#80ffff" }, { "type": "box", "layout": "horizontal", "contents": [ { "type": "text", "text": "TARGET" } ], "backgroundColor": "#ff8080" } ] }}원래 위치 기준으로 컴포넌트 배치를 조정하려면 position 속성을 relative 로 지정해 놓고 아래와 같이 오프셋 속성을 지정하면 된다. CSS Positioned Layout Module Level 3의 Relative positioning과 유사한 개념으로 위치를 지정하는 것으로 이해하면 된다.
| 속성 | 설명 |
|---|---|
offsetBottom | 원래 위치에서 아래로 이동하는 거리를 지정한다. |
offsetStart | 원래 위치에서 왼쪽으로 이동하는 거리를 지정한다. |
offsetEnd | 원래 위치에서 오른쪽으로 이동하는 거리를 지정한다. |
offsetTop | 원래 위치에서 위쪽으로 이동하는 거리를 지정한다. |
다음은 ‘TARGET’ 문자열이 있는 위의 수평 상자 예시에서 offset을 아래 값으로 변경했을 때의 결과이다.
| 속성 | 값 |
|---|---|
position | relative |
offsetTop | 10px |
offsetBottom | - |
offsetStart | 40px |
offsetEnd | - |
첫 번째 이미지가 값을 변경하기 전, 두 번째 이미지는 값을 변경하고 난 후의 버블이다.

컴포넌트를 상위 컴포넌트 테두리를 기준으로 배치하려면 position 속성을 absolute 로 지정해놓고 아래와 같이 오프셋 속성을 지정하면 된다. CSS Positioned Layout Module Level 3의 Absolute positioning과 유사한 개념으로 위치를 지정하는 것으로 이해하면 된다.
| 속성 | 설명 |
|---|---|
offsetTop | 상위 컴포넌트의 상단에서 해당 컴포넌트의 상단까지의 상대 위치를 지정한다. |
offsetBottom | 상위 컴포넌트의 하단에서 해당 컴포넌트의 하단까지의 상대 위치를 지정한다. |
offsetStart | 상위 컴포넌트의 왼쪽 가장자리에서 해당 컴포넌트의 왼쪽 가장자리까지의 상대 위치를 지정한다. |
offsetEnd | 상위 컴포넌트의 오른쪽 가장자리에서 해당 컴포넌트의 오른쪽 가장자리까지의 상대 위치를 지정한다. |
참고
offset속성을 지정하지 않으면 해당 컴포넌트의 위치가 기기에 따라 달라질 수 있다. 따라서 오프셋을 수직(offsetTop또는offsetBottom) 및 수평(offsetStart또는offsetEnd)으로 명확히 지정하는 것을 권장한다.
다음은 ‘TARGET’ 문자열이 있는 위의 수평 상자 예시에서 offset을 아래 값으로 변경했을 때의 결과이다.
| 속성 | 값 |
|---|---|
position | absolute |
offsetTop | 10px |
offsetBottom | 20px |
offsetStart | 40px |
offsetEnd | 80px |
첫 번째 이미지가 값을 변경하기 전, 두 번째 이미지는 값을 변경하고 난 후의 버블이다.

position 속성값이 absolute 로 설정된 박스는 상위 컴포넌트(부모 요소)의 크기에 영향을 주거나 받지 않는다. 따라서 컴포넌트의 크기가 상위 컴포넌트보다 커지면 해당 컴포넌트의 일부가 표시되지 않는다. 만약 상위 컴포넌트의 영향(여백)을 받아 해당 컴포넌트의 크기가 커져 있었다면, 해당 컴포넌트에 설정되어 있는 원래 크기로 돌아가게 된다.
다음은 ‘REFERENCE BOX’ 문자열이 있는 수평 상자의 position 속성을 absolute 로 설정했을 때의 결과이다.
| 속성 | 값 |
|---|---|
position | absolute |
첫 번째 이미지가 값을 변경하기 전, 두 번째 이미지는 값을 변경하고 난 후의 버블이다

‘REFERENCE BOX’의 크기는 상위 컴포넌트(수직 박스)의 크기에 영향을 주거나 받지 않은 것을 확인할 수 있다. 따라서 상위 컴포넌트 영역을 초과하는 부분(숫자 ‘2'와 ‘3’이 적혀 있는 행)은 표시되지 않는다. 또한 기존에 상위 컴포넌트(여백)의 영향으로 커져 있었던 좌우의 여백은 원래의 크기(‘REFERENCE BOX’의 너비)로 돌아가게 된다.
모든 컴포넌트는 JSON 데이터의 순서에 따라 그려진다. 따라서 JSON 데이터에서 처음에 작성한 컴포넌트는 버블 가장 뒤쪽에 그려지고, 마지막에 작성한 컴포넌트는 버블의 가장 앞쪽에 그려진다.
그려지는 순서를 변경하려면 JSON 데이터의 컴포넌트 순서를 변경해야 한다.