LINE Flex Message คือรูปแบบข้อความที่มีความยืดหยุ่นสูงที่สุดใน LINE Messaging API อนุญาตให้ Developer ออกแบบ Layout ที่ซับซ้อนได้เหมือน HTML/CSS แต่เขียนอยู่ในรูปแบบของ JSON Object
บทความนี้จะไม่อธิบายพื้นฐานการยิง API แต่จะเจาะลึกที่ “Structure & Hierarchy” ของ JSON Payload ซึ่งเป็นจุดที่ Developer มักทำผิดพลาดบ่อยที่สุด จนทำให้ข้อความไม่แสดงผล (Silent Error) หรือแสดงผลผิดเพี้ยน
1. The Architecture: โครงสร้างลำดับชั้น (Hierarchy)
ความเข้าใจผิดแรกคือการสับสนระหว่าง Container และ Component โครงสร้างของ Flex Message มีลำดับชั้นที่เข้มงวด ดังแผนภาพโครงสร้างข้อมูลด้านล่าง:
JSON Root Object
└── type: "flex"
└── contents: {Container}
│
├── Type A: "bubble" (กล่องข้อความเดียว)
│ ├── styles
│ ├── header (Box)
│ ├── hero (Image/Video)
│ ├── body (Box) *Required
│ └── footer (Box)
│
└── Type B: "carousel" (สไลด์แนวนอน)
└── contents: [ Bubble, Bubble, ... ]
Visualizing The Bubble Block
หนึ่ง Bubble จะถูกแบ่งออกเป็น 4 Blocks หลักตามแนวตั้ง (Vertical Stack) เสมอ ไม่สามารถสลับตำแหน่งได้:
+-------------------------------------------+
| HEADER (Block) |
| - เหมาะสำหรับ Title / หัวข้อ |
+-------------------------------------------+
| HERO (Block) |
| - พื้นที่รูปภาพขนาดใหญ่ (Cover Image) |
| - Aspect Ratio ปรับได้ |
+-------------------------------------------+
| BODY (Block) |
| - เนื้อหาหลัก (Main Content) |
| - รองรับ Nested Box (ซ้อน Layout) |
+-------------------------------------------+
| FOOTER (Block) |
| - พื้นที่สำหรับปุ่ม Action / Copyright |
+-------------------------------------------+
2. The Layout Engine: Box และ Direction
หัวใจสำคัญของการจัด Layout คือ “Box” ซึ่งทำหน้าที่เหมือน <div> ใน HTML โดย Box จะมี Property สำคัญที่สุดคือ layout ซึ่งกำหนดทิศทางการเรียงตัวของ Child Components (contents Array)
2.1 Vertical Box (Stacking)
layout: "vertical" คือค่า Default ของ Block ส่วนใหญ่ (Header, Body, Footer) คอมโพเนนต์ลูกจะเรียงต่อกันจากบนลงล่าง
JSON Structure:
{
"type": "box",
"layout": "vertical",
"contents": [ A, B, C ]
}
Visual Result:
+-------+
| A |
+-------+
| B |
+-------+
| C |
+-------+
2.2 Horizontal Box (Row)
layout: "horizontal" ใช้เมื่อต้องการจัดวางของให้อยู่บรรทัดเดียวกัน (เช่น รูปโปรไฟล์คู่กับชื่อ หรือ ราคาคู่กับปุ่มซื้อ)
JSON Structure:
{
"type": "box",
"layout": "horizontal",
"contents": [ A, B, C ]
}
Visual Result:
+-------+ +-------+ +-------+
| A | | B | | C |
+-------+ +-------+ +-------+
3. Deep Dive: เทคนิคการจัด Layout ที่มักเขียนผิด
ข้อผิดพลาด 80% ของการเขียน Flex Message เกิดจากการจัดการพื้นที่ (Spacing) และสัดส่วน (Flex Ratio) ใน Horizontal Box ไม่ถูกต้อง
Scenario: การทำ Layout แบบ “Label : Value”
ต้องการแสดงรายการข้อมูล เช่น “Status : Pending” โดยต้องการให้คำว่า Status ชิดซ้าย และ Pending ชิดขวา หรือแบ่งพื้นที่กันคนละ 30:70
Code ที่ถูกต้อง (Correct JSON Logic):
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "Status",
"flex": 2, <-- กินพื้นที่ 2 ส่วน
"color": "#aaaaaa"
},
{
"type": "text",
"text": "Pending",
"flex": 8, <-- กินพื้นที่ 8 ส่วน
"align": "end", <-- จัดชิดขวาภายในพื้นที่ตัวเอง
"weight": "bold"
}
]
}
Logic การคำนวณพื้นที่:
| Component | Flex Value | Calculation | Visual Width |
|---|---|---|---|
| Text (Status) | 2 | 2 / (2+8) = 20% | [Status..] |
| Text (Pending) | 8 | 8 / (2+8) = 80% | [.......Pending] |
4. Debugging: วิเคราะห์ Error จาก JSON Structure
เมื่อ LINE Server ตอบกลับมาว่า 400 Bad Request มักเกิดจาก Syntax Error เหล่านี้:
4.1 Nested Array Trap (กับดักวงเล็บ)
ใน Box, property ชื่อ contents ต้องเป็น Array [] เสมอ แม้จะมีไอเท็มเดียวก็ตาม
❌ ผิด (Invalid):
"contents": {
"type": "text",
"text": "Hello"
}
✅ ถูก (Valid):
"contents": [
{
"type": "text",
"text": "Hello"
}
]
4.2 Layout Mismatch
ปัญหา: ใส่ Text ลงใน contents ของ Bubble โดยตรงไม่ได้
คำอธิบาย: Root ของ Bubble ต้องแบ่งเป็น Block (Header, Hero, Body, Footer) ก่อน แล้วใน Block นั้นถึงจะเป็น Box ที่ใส่ Text ได้
Strict Hierarchy Rule:
Bubble
└── Body (Block)
└── Box (Container)
└── contents [ Text, Image, Button ] (Components)
5. Reference Guide: Properties ที่ต้องจำ
ตารางสรุป Property สำคัญที่ใช้ควบคุม Layout โดยไม่ต้องจำทุกตัว
| Property | ใช้กับ (Scope) | หน้าที่ (Function) |
|---|---|---|
flex |
Component ใน Box | กำหนดอัตราส่วนความกว้าง/สูง (เหมือน CSS Flexbox flex-grow) ค่า default คือ 1 |
spacing |
Box (Parent) | กำหนดระยะห่างระหว่าง Child Components (sm, md, lg) |
margin |
Component (Child) | กำหนดระยะห่างด้านบน (Top Margin) ของตัวเองเทียบกับตัวก่อนหน้า |
align |
Text / Box | จัดตำแหน่งแนวนอน (start, center, end) |
gravity |
Text / Box | จัดตำแหน่งแนวตั้ง (top, center, bottom) *ใช้ใน Box ที่มีความสูงเหลือ |