ข้ามไปยังเนื้อหา

Containers & Padding

ใน CSS ทุก HTML element คือกล่องที่มี padding, margin, border, width และ height แต่ Flutter ไม่มี CSS box model แทนที่จะเป็นแบบนั้น มี widget เฉพาะทาง สำหรับแต่ละเรื่อง ตอนแรกฟังดูเหมือนยืดยาว แต่ทำให้เจตนาของ layout ชัดเจนและประกอบกันได้

widget สามตัวที่คุณจะหยิบมาใช้บ่อยที่สุดคือ Container (กล่องครบในตัวเดียว), Padding (เว้นระยะอย่างเดียว) และ SizedBox (ขนาดตายตัวหรือใช้เว้นช่องว่าง)

CSS propertyFlutter widget / property
padding: 16pxPadding(padding: EdgeInsets.all(16))
padding: 8px 16pxEdgeInsets.symmetric(vertical: 8, horizontal: 16)
padding: 4px 8px 12px 16pxEdgeInsets.only(top: 4, right: 8, bottom: 12, left: 16)
margin: 8pxห่อ parent ด้วย Padding หรือใช้ Container(margin: ...)
width: 200px; height: 100pxSizedBox(width: 200, height: 100)
width: 100%SizedBox(width: double.infinity)
background-color, border-radius, box-shadow, borderContainer(decoration: BoxDecoration(...))
width: 200px; background: blue; border-radius: 8pxContainer(width: 200, decoration: BoxDecoration(color: Colors.blue, borderRadius: ...))

Padding ใช้เมื่อคุณต้องการแค่เว้นระยะรอบ child เท่านั้น Padding เบากว่า Container เพราะไม่มีต้นทุนในการวาด (painting cost)

SizedBox ใช้เมื่อคุณต้องการขนาดตายตัว หรือใช้เป็นช่องว่างระหว่าง widget (SizedBox(height: 16) เป็นวิธีเว้นระยะแนวตั้งที่นิยมใช้กัน)

Container ใช้เมื่อคุณต้องการ visual property หลายอย่างพร้อมกัน เช่น color, padding, margin, border, border-radius หรือ shadow อย่าใช้ Container เพียงเพื่อใส่ padding เฉย ๆ ให้ใช้ Padding แทน

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: const Color(0xFFF5F5F5),
        appBar: AppBar(title: const Text('Containers & Padding')),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(16),   // Padding on ScrollView
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            spacing: 16,
            children: [
              // ------- Padding only -------
              const _Label('Padding — all sides 16px'),
              Padding(
                padding: const EdgeInsets.all(16),
                child: Container(color: Colors.blue[100],
                    child: const Text('Content with padding')),
              ),

              // ------- SizedBox as gap + fixed size -------
              const _Label('SizedBox — fixed 200x60'),
              Center(
                child: SizedBox(
                  width: 200, height: 60,
                  child: Container(color: Colors.green[200],
                      alignment: Alignment.center,
                      child: const Text('200 x 60')),
                ),
              ),

              // ------- Container — full box model -------
              const _Label('Container — color + border-radius + shadow'),
              Container(
                padding: const EdgeInsets.all(20),
                margin: const EdgeInsets.symmetric(horizontal: 8),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(16),
                  boxShadow: [
                    BoxShadow(color: Colors.black.withOpacity(0.08),
                        blurRadius: 10, offset: const Offset(0, 4)),
                  ],
                ),
                child: const Text('This card uses BoxDecoration'),
              ),

              // ------- EdgeInsets.only -------
              const _Label('EdgeInsets.only — asymmetric padding'),
              Container(
                color: Colors.orange[100],
                padding: const EdgeInsets.only(
                    top: 4, right: 8, bottom: 12, left: 24),
                child: const Text('top:4 right:8 bottom:12 left:24'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _Label extends StatelessWidget {
  final String text;
  const _Label(this.text);

  @override
  Widget build(BuildContext context) => Text(text,
      style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 12,
          color: Colors.grey));
}
widget ตัวไหนที่ควรใช้เมื่อคุณต้องการแค่ใส่ padding รอบ child โดยไม่มี styling เชิงภาพอื่น ๆ?
อะไรคือสิ่งที่เทียบเท่ากับ `width: 100%` ของ CSS ใน Flutter?
จะเกิดอะไรขึ้นถ้าคุณตั้งทั้ง `color` และ `decoration` บน `Container` ตัวเดียวกัน?
อะไรคือวิธีที่นิยมใน Flutter ในการเพิ่มช่องว่าง 16 พิกเซลระหว่าง child สองตัวของ Column?