สรุปเนื้อหา Tailwind CSS Workshopในงาน LINE DEV CONF 2022

Puwadon Sricharoen
LINE Developers Thailand
13 min readSep 26, 2022

เนื่องจาก Workshop ที่ผ่านมาเรามีเพียง 30 ที่นั่งกับเวลา 50 นาที บทความนี้ถือเป็นเวอร์ชั่นเต็ม ที่จะพาทุกคนไปรู้จักกับ Utility Class และ Tailwind CSS รวมถึงพาทำ Workshop แบบละเอียดทีละขั้นตอน

Utility-first CSS framework packed with Tailwind CSS

ทำความรู้จัก Utility Class และ Tailwind CSS

Utility Class คือ การแยกคุณสมบัติของ CSS แต่ละคำสั่งออกมาเป็นคลาสย่อยๆ หรือ 1 Class 1 คุณสมบัติ และ Tailwind CSS ก็คือ CSS framework ที่จะรวบรวม Utility classes ให้เราได้ใช้งาน โค้ดด้านล่างคือตัวอย่างของ Utility Class

.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.text-xs {
font-size: .75rem;
}
.text-sm{
font-size: .875rem;
}
.bg-white {
background-color: #fff;
}
.bg-gray-900 {
background-color: #1a202c;
}

เมื่อนำ Utility Class มาใช้งานก็จะมีหน้าตาคล้ายกับวิธีการเขียน style เข้าไปที่ HTML Tag (Inline Styles) แต่จะอยู่ใน class attribute แทน

<button class="h-12 bg-blue-500 text-white rounded-lg shadow">
Getting Started
</button>

หนึ่งในเหตุผลสำคัญที่เราเลือกใช้ Tailwind CSS เมื่อเราทำงานร่วมกันมากกว่า 1 คนขึ้นไปหรือทีม การเขียน Utility Class จะช่วยให้พวกเราพอจะเห็นผลลัพธ์ของ Element นั้นได้เลย เหมือนกับตัวอย่างโค้ดปุ่ม Getting Started ด้านบน ถ้าคุ้นเคยแล้วก็จะจินตนาการได้ว่า ปุ่มสูง 48px พื้นหลังสีน้ำเงิน มีเงาขอบ ตัวหนังสือสีขาวและมีขอบโค้งมนเล็กน้อย

นอกจากนั้น Tailwind CSS ยังเพิ่มความสะดวกให้จัดการ Responsive Layout, Hover and focus states, Dark Mode, รวมถึงสามารถปรับแต่ง Style เพิ่มเติมได้อีกด้วย และส่วนเสริมต่างๆ (extension) ที่ช่วยให้เราใช้งาน Tailwind CSS บน IDE ได้สะดวกสบายขึ้นไปอีก

ความคิดเห็นส่วนตัว: ถ้าใครใช้ Visual Studio Code อยู่แล้ว ผมขอแนะนำ Tailwind CSS IntelliSense ที่จะช่วย autocomplete, syntax highlighting and linting ตรวจสอบความผิดพลาดได้ทันที

Tailwind CSS IntelliSense

รู้จักกับ Tailwind CSS ก่อนเริ่ม Workshop

  • Elements คือ ชิ้นส่วนของ HTML เช่น <div>, <p>, <h1>, <input> และอื่นๆ
  • Parent element คือ Elements ที่มี child elements ข้างใน ซึ่งจะมี CSS ที่ต้องใส่ไว้กับ parent เพื่อให้ส่งผลถึง child elements ตัวอย่างเช่น flex-wrap: wrap;
  • Child elements คือ Elements ที่อยู่ภายใต้ parent element ซึ่งก็จะมี CSS ที่ทำให้ตัว child เองแสดงผลต่างจาก styles ที่ถูกบังคับมาจาก parent elements ได้เช่นกัน ตัวอย่างเช่น align-self: flex-start;
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>

จัดทิศทางด้วย flex

สิ่งแรกที่เราจะทำก่อนเสมอ คือ การกำหนดทิศทางของ elements ว่าจะเรียงไปในทิศทางไหน แนวนอน แนวตั้ง จัดกึ่งกลาง ขยาย child elements ไปชิดขอบ หรือรูปแบบอื่นๆ

  • flex flex-row เพื่อให้ child elements เรียงกันในแนวนอน หรือถ้าใส่เฉพาะ flex ก็จะแสดงผลในแนวนอนเช่นกัน เพราะจะ flex มี flex-row เป็นค่าเริ่มต้นเสมอ
  • flex flex-col เพื่อให้ child elements เรียงกันในแนวตั้ง
  • flex justify-center เพื่อให้ child elements อยู่ตรงกลางของ parent element (จำเป็นมี flex ด้วยเสมอ)
  • flex justify-between เพื่อให้ child elements กระจายเต็มความกว้างของ parent element (จำเป็นมี flex ด้วยเสมอ)
  • flex items-center เพื่อให้ child elements อยู่กึ่งกลาง(แนวตั้ง) ของ parent element (จำเป็นมี flex ด้วยเสมอ)

ตัวอย่างที่ยกมานี้ เป็นเพียงส่วนหนึ่งที่เราจะใช้สำหรับทำ Workshop เท่านั้น ที่จริงแล้ว Flex ยังมีความสามารถที่เก่งกว่านี้อีก เช่น flex-wrap | shrink | items-baseline

Margin และ Padding ด้วย m-{size} | p-{size}

จำเป็นต้องทำความเข้าใจ Default spacing scale ของ Tailwind CSS ก่อน จากตารางด้านล่าง ส่วนตัวผมจะเรียกตัวเลขในคอลัมน์ Name ว่า Point สังเกตุว่าถ้านำ Point คูณด้วย 4 จะได้ค่า px พอดี ตัวอย่างเช่น

  • p-2 เท่ากับ padding: 16px;
  • pt-5 เท่ากับ padding-top: 20px;
  • mb-10 เท่ากับ margin-bottom: 40px;
Tailwind CSS: Default spacing scale

Default spacing scale ยังไม่หมดเท่านี้ Tailwind CSS เตรียมไว้ให้เราใช้งานสูงสุดถึง 96 หรือ 24rem หรือ 384px

วิธีกำหนดระยะขอบ (Margin) ใน Tailwind CSS ด้วย m-{size}

  • m-4 เท่ากับ เว้นระยะขอบทุกด้าน 16px
  • m-8 เท่ากับ เว้นระยะขอบทุกด้าน 32px
  • mx-5 เท่ากับ เว้นระยะขอบเฉพาะด้านซ้ายและขวา 20px
  • my-2 เท่ากับ เว้นระยะขอบเฉพาะด้านบนและล่าง 8px
  • และยังสามารถกำหนดทิศทางของการเว้นระยะขอบที่ต้องการ ด้วย ml-{size} | mt-{size} | mb-{size} | mr-{size}
กำหนดทิศทางของการเว้นระยะขอบ (Margin) ได้ตามต้องการ

วิธีขยายระยะขอบ (Padding) ก็จะใช้หลักการเดียวกับการเว้นระยะขอบ (Margin) เพียงแค่เปลี่ยนมาใช้ p-{size} ตัวอย่างเช่น p-4 | px-4 | py-3 | pl-2 | pb-3

กำหนดทิศทางของการขยายระยะขอบ (Padding) ได้ตามต้องการ

Default spacing scale นี้ยังสามารถใช้งานได้กับ Width, Height ได้อีกด้วย ตัวอย่างเช่น w-12 เท่ากับความกว้าง 48px หรือ h-10 เท่ากับความสูง 40px

ขนาดตัวอักษร text-{size}

เบื้องต้น Tailwind CSS เตรียมขนาดฟอนต์ให้เลือกใช้อยู่หลากหลายขนาด ตั้งแต่ 12px ไปจนถึง 128px โดยจะใช้ {size} เป็น keyword แทน และจะมีคลาส text-base จะเป็นค่าเริ่มต้นเสมอถ้า element นั้นไม่ได้กำหนดขนาดตัวอักษรเอาไว้

<p class="text-sm">The quick brown</p>   /* 14px */
<p class="text-base">The quick brown</p> /* 16px */
<p class="text-lg">The quick brown</p> /* 18px */
<p class="text-xl">The quick brown</p> /* 20px */
<p class="text-2xl">The quick brown</p> /* 24px */

สีตัวอักษรและสีพื้นหลัง text-{color} | bg-{color}

ระบบสีของ Tailwind CSS ถือเป็นเสน่ห์ที่ทำให้พวกเราอยากเปลี่ยนมาใช้ นอกจากความหลากหลายของจำนวนสีแล้ว แต่ละสีก็จะมีอีก 10 เฉด นี่ยังไม่รวมความโปร่งใส่ (Opacity) ที่เรากำหนดได้ด้วย ทำให้การใช้งานค่อนข้างยืดหยุ่นมาก

Tailwind CSS: Default colors palette

เพียงแค่ใส่ text-{color}-{shade} สำหรับสีตัวอักษร หรือ bg-{color}-{shade} สำหรับพื้นหลัง และยังสามารถใช้กับเส้นขอบได้ด้วย ตัวอย่างเช่น border border-rose-600, divide-y divide-blue-200

<p class="text-blue-300">The quick brown</p>
<p class="text-blue-600">The quick brown</p>
<p class="text-blue-900">The quick brown</p>
<div class="bg-red-500">Content</div>
<div class="bg-orange-500">Content</div>
<div class="bg-green-500">Content</div>

จัดการตำแหน่งด้วย fixed | absolute | relative

เมื่อต้องการให้ element ลอยทับกัน เราจะใช้ fixed สำหรับยึดตำแหน่งกับหน้าจอ หรือ absolute เพื่อยึดตำแหน่งกับ parent element และต้องกำหนดตำแหน่งด้วย top-{size} | right-{size} | bottom-{size} | left-{size} ตัวอย่างเช่น

  • absolute left-0 top-0 จะทำให้ Element ลอยชิดขอบซ้ายบนของ parent element
  • absolute bottom-2 right-0 จะทำให้ Element ลอยอยู่ขวาล่างของ parent element และมีระยะห่างจากขอบล่าง 8px
  • fixed top-0 right-4 จะทำให้ Element ลอยอยู่บนขวาของหน้าจอ และมีระยะห่างจากขอบขวา 16px
จัดการตำแหน่งด้วย absolute และ relative

หรือในกรณีที่ต้องการให้ Element ขยายจนชิดขอบทั้งสองด้านหรือทั้งหมด สามารถใช้ inset-{size} | inset-x-{size} | inset-y-{size} แทนได้ ตัวอย่างเช่น

  • inset-0 แทน top-0 bottom-0 left-0 right-0
  • inset-x-0 แทน left-0 right-0
  • inset-y-0 แทน top-0 bottom-0
ใช้ inset-{size} เพื่อขยายขนาดของ element ที่ต้องการ

เงา, เส้นขอบ, เส้นขั้น

  • shadow หรือ shadow-xl หรือ shadow-2xl ใส่เงาขอบให้กับ element ที่ต้องการ
ใส่เงาขอบด้วย shadow | shadow-xl | shadow-2xl
  • rounded หรือ rounded-lg ทำให้ขอบโค้งมน หรือตัดเป็นวงกลมด้วย rounded-full ให้กับ element ที่ต้องการ
กำหนดให้ขอบโค้งมนด้วย rounded | rounded-lg
  • border หรือ border-2 หรือ border-4 ใส่เส้นขอบและกำหนดความหนาของเส้น หรือ border-0 เพื่อลบเส้นขอบออกจาก element ที่ต้องการ
ใส่เส้นขอบและกำหนดความหนาของเส้นด้วย border | border-2
  • divide-x ใส่เส้นขั้นระหว่าง elements ในแนวนอน
  • divide-y ใส่เส้นขั้นระหว่าง elements ในแนวตั้ง

เริ่มทำ Workshop!

เราเตรียม Repository (Vue 3 + Tailwind CSS 3.1.8 + Vite) สำหรับทดลองเขียน Tailwind CSS แบบรวดเร็ว ซึ่งจะมี UI ให้ลองทำทั้งหมด 3 หน้า Home, SignUp และ Setting โดยเราพยายามแยกชิ้นส่วนออกเป็น Components ให้ได้มากที่สุด และไม่ต้องกังวลหากใครไม่คุ้นเคยกับ Vue มาก่อน เพราะใน Workshop นี้เราอยากให้ทุกคนได้โฟกัสกับ CSS เท่านั้น ถ้าพร้อมแล้ว ติดตั้งและลองทำตามทีละขั้นตอนได้เลย…

$ git clone https://github.com/jimmy18dev/LINE-DEVCONF-2022-tailwind-workshop.git
$ cd LINE-DEVCONF-2022-tailwind-workshop
$ npm i && npm run dev

เมื่อรัน npm run dev ขึ้นดังภาพด้านบน ก็ถือว่าติดตั้งและรันสำเร็จแล้ว ในระหว่าง Implement เราขอแนะนำให้เปิด Responsive Design Mode (ได้ทั้ง Google Chrome และ Safari) จะช่วยให้เห็นภาพเดียวกับบทความนี้

Responsive Design Mode บน Google Chrome
Responsive Design Mode บน Safari

1. หน้าหลัก (Home)

ความท้าท้ายของหน้านี้ คือ การขยายพื้นที่สีขาวให้เต็มจอ และผลักปุ่ม Get Started มาอยู่ด้านล่างเสมอ นอกจากนั้นเป็นการจัดการระยะห่างและขนาดตัวอักษรให้ตรงตามแบบ

Step 1: เริ่มระบายสีให้เห็นขอบเขตแต่ละส่วนชัดเจนขึ้น ด้วย bg-{color}-{shade} (เป็นวิธีที่ผมใช้บ่อย) หรือยังไม่ชัดก็สามารถเพิ่มระยะห่าง mb-1 เข้าไปได้อีก

./src/views/Home.vue<div class="bg-blue-200">
<div class="bg-blue-200">
<img
src="../assets/images/cover.jpg"
alt="Fashion Up Your Look"
>
<h1 class="bg-green-300">Fashion Up Your Look</h1>
<p class="bg-orange-400">Welcome to the world's most...</p>
</div>
<Button class="bg-blue-400">Get Started</Button>
</div>
ระบายสีให้เห็นขอบเขตแต่ละส่วนชัดเจนขึ้น

Step 2: กำหนดทิศทางของการแสดงผลด้วย flex flex-col (แนวตั้ง) และระยะห่างของแต่ละส่วนด้วย p-4 และ mb-5

./src/views/Home.vue<div class="bg-blue-200 flex flex-col p-4">
<div class="bg-blue-200 flex flex-col">
<img
class="mb-5"
src="../assets/images/cover.jpg"
alt="Fashion Up Your Look"
>
<h1 class="bg-green-300 mb-5">Fashion Up Your Look</h1>
<p class="bg-orange-400">Welcome to the world's most...</p>
</div>
<Button class="bg-blue-400">Get Started</Button>
</div>
flex-col ทำให้ elements เรียงกันในแนวตั้ง

Step 3: ขยาย element ชั้นนอกสุดให้เต็มจอด้วย fixed top-0 left-0 w-full h-full

./src/views/Home.vue<div class="bg-blue-200 flex flex-col p-4 fixed top-0 left-0 w-full h-full">
<div class="bg-blue-200 flex flex-col">
<img
class="mb-5"
src="../assets/images/cover.jpg"
alt="Fashion Up Your Look"
>
<h1 class="bg-green-300 mb-5">Fashion Up Your Look</h1>
<p class="bg-orange-400">Welcome to the world's most...</p>
</div>
<Button class="bg-blue-400">Get Started</Button>
</div>
fixed ต้องใช้คู่กับการกำหนดตำแหน่ง เช่น top-0 left-0

Step 4: ผลักปุ่ม Get Started ลงไปด้านล่างสุด โดยใส่ mb-auto ที่ element ส่วนบน หรือ mt-auto ที่ตัว <Button> ก็จะให้ผลลัพธ์เหมือนกัน และใส่สีและขนาดตัวอักษรที่ <h1> และ <p> ให้ตรงตามแบบ

./src/views/Home.vue<div class="bg-white flex flex-col p-4 fixed top-0 left-0 w-full h-full">
<div class="flex flex-col mb-auto">
<img
class="mb-5 rounded-lg shadow"
src="../assets/images/cover.jpg"
alt="Fashion Up Your Look"
>
<h1 class="text-2xl text-gray-900 mb-5">Fashion Up Your Look</h1>
<p class="text-lg text-slate-500">Welcome to the world's most...</p>
</div>
<Button class="bg-blue-400">Get Started</Button>
</div>
mb-auto จะผลักปุ่มลงไปอยู่สุดขอบล่าง

Step 5: เปลี่ยน top-0 left-0 w-full h-full เป็น inset-0 หนึ่งในความง่ายดายที่ Tailwind CSS เตรียมไว้ให้ใช้งาน และอีกจุดสังเกตุเราสามารถใช้ my-5 ที่ <h1> เพื่อให้เกิดระยะห่างทั้งด้านบนและล่างของ element ได้เช่นกัน

./src/views/Home.vue<div class="bg-white flex flex-col p-4 fixed inset-0">
<div class="flex flex-col mb-auto">
<img
class="rounded-lg shadow"
src="../assets/images/cover.jpg"
alt="Fashion Up Your Look"
>
<h1 class="text-2xl text-gray-900 my-5">Fashion Up Your Look</h1>
<p class="text-lg text-slate-500">Welcome to the world's most...</p>
</div>
<Button>Get Started</Button>
</div>
my-{size} ช่วยสร้างระยะห่างทั้งบนและล่างของ element ที่ต้องการ

Step 6: ส่วนสุดท้ายของหน้านี้คือ <Button> ใส่ความสูง สีพื้นหลัง สีตัวอักษร และเงาให้ตรงตามแบบ ก็ถือว่าเสร็จสมบูรณ์แล้ว

./src/components/Button.vue<button class="w-full h-12 bg-blue-500 text-lg text-white rounded-lg shadow font-bold">
<slot></slot>
</button>
สวยงามตามแบบ

2. หน้าลงทะเบียน (SignUp)

ความท้าทายของหน้านี้ คือ ไอคอนที่เข้าไปอยู่บน Input text

เมื่อดูจากโค้ดจะเห็นว่าเราแบ่งออกเป็น 3 ส่วน คือ Head, Form และ Button ซึ่ง <Button> มีหน้าตาถูกต้องตามแบบแล้ว เพราะเราใช้ Component เดียวกับหน้า Home เมื่อสักครู่

Step 1: เริ่มด้วยการระบายสีให้แต่ละส่วนให้ดูง่ายขึ้น

./src/views/SignUp.vue<div class="bg-blue-200 flex flex-col">
<h1 class="bg-green-200">Create an account</h1>
<div class="bg-orange-300 flex flex-col">
<InputText
label="Fullname"
placeholder="First name and Last name"
/>
<InputText
label="Email"
placeholder="Enter email address"
/>
<InputText
label="Password"
placeholder="Enter password"
/>
</div>
<Button>Register</Button>
</div>

Step 2: ขยายพื้นที่ฟอร์มให้เต็มจอด้วย fixed inset-0 (เหมือนกับหน้า Home) กำหนดทิศทางการแสดงผลของ elements และระยะห่าง margin, padding ให้ตรงตามแบบ

./src/views/SignUp.vue<div class="bg-white flex flex-col p-4 fixed inset-0">
<h1 class="text-2xl text-gray-900 text-center my-5">Create an account</h1>
<div class="flex flex-col mb-auto">
<InputText
label="Fullname"
placeholder="First name and Last name"
/>
<InputText
label="Email"
placeholder="Enter email address"
/>
<InputText
label="Password"
placeholder="Enter password"
/>
</div>
<Button>Register</Button>
</div>

Step 3: เมื่อดูโค้ดใน <InputText> จะประกอบไปด้วย 3 ส่วน คือ Label, Icon, และ input สังเกตุว่าเราวางไอคอนให้อยู่ใน <div> เดียวกับ <input> เพื่อให้สามารถวางไอคอนทับบน <input> อีกที ถ้าลองระบายสีเข้าไปจะเห็นว่าทั้ง 3 ส่วน เรียงกันเป็นแนวตั้งอยู่ในตอนนี้

./src/components/InputText.vue<div class="bg-blue-100 mb-5">
<Label class="bg-blue-200">{{ label }}</Label>
<div class="bg-green-100">
<div v-if="type" class="bg-orange-200">
<Icon :type="type" />
</div>
<input
class="bg-green-300"
:type="type"
:placeholder="placeholder"
>
</div>
</div>
ทั้ง 3 ส่วน เรียงกันเป็นแนวตั้งอยู่ในตอนนี้

Step 4: กำหนดความสูงของ input ไว้ที่ h-12 ขยายระยะของด้วย px-4 ตามด้วยเส้นขอบ ขนาดตัวอักษร สีตัวอักษร ขอบโค้งมนและเงาขอบให้ตรงตามแบบ

./src/components/InputText.vue<div class="mb-5">
<Label>{{ label }}</Label>
<div class="bg-green-100">
<div v-if="type" class="bg-orange-200">
<Icon :type="type" />
</div>
<input class="bg-white w-full h-12 border border-gray-300 px-4 rounded-lg text-lg text-gray-900" :type="type" :placeholder="placeholder">
</div>
</div>

Step 5: วิธีทำให้ไอคอนลอยอยู่บนพื้นที่ที่ต้องการก็คือ absolute ซึ่งต้องใส่ relative ไว้ที่ parent element และใส่ absolute ที่ไอคอน และต้องกำหนดตำแหน่งและขนาดด้วย top-0 left-0 inset-y-0 w-12

./src/components/InputText.vue<div class="mb-5">
<Label>{{ label }}</Label>
<div class="relative">
<div v-if="type" class="bg-orange-200 absolute top-0 left-0 inset-y-0 w-12">
<Icon :type="type" />
</div>
<input class="bg-white w-full h-12 border border-gray-300 px-4 rounded-lg text-lg text-gray-900" :type="type" :placeholder="placeholder">
</div>
</div>
พื้นที่สีส้มมีขนาด 48 x 48px

จะเห็นว่าพื้นที่สีส้มเป็นสี่เหลี่ยมจัตรัสพอดี เพราะเราใช้ inset-y-0 และ w-12 เมื่อแปลง w-12 จะเท่ากับ width: 48px; และ inset-y-0 จะขยายพื้นที่เป้าหมายให้ชิดขอบทั้งบนและล่างของ parent element ซึ่งคือ <Input> ที่กำหนดความสูงไว้ที่ h-12 หรือเท่ากับ height: 48px; ทำให้พื้นที่สีส้มมีขนาด 48 x 48px

Step 6: ถึงตรงนี้เราจะได้ไอคอนที่ลอยอยู่บน <Input> แล้ว เราจะกำหนดให้ไอคอนแสดงจุดกึ่งกลางของที่สีส้ม (48 x 48px) ด้วย flex justify-center items-center

./src/components/InputText.vue<div class="mb-5">
<Label>{{ label }}</Label>
<div class="relative">
<div v-if="type" class="absolute top-0 left-0 inset-y-0 w-12 flex justify-center items-center text-slate-500">
<Icon :type="type" />
</div>
<input class="bg-white w-full h-12 border border-gray-300 pr-4 pl-12 rounded-lg text-lg text-gray-900" :type="type" :placeholder="placeholder">
</div>
</div>

สุดท้ายใส่ Style ให้กับ <Label> ให้ตรงตามแบบด้วย mb-3 text-gray-900 font-bold

./src/components/Label.vue<div class="mb-3 text-gray-900 font-bold">
<slot></slot>
</div>
สวยงามตามแบบ

3. หน้าตั้งค่า (Setting)

ความท้าทายของหน้านี้ คือ การจัดกลุ่ม <ToggleMenu> เป็น <Section> และลูกเล่นของเส้นขั้นระหว่างเมนูที่จะมีระยะห่างด้านซ้ายขวาคนละเงื่อนไขกัน

Step 1: ระบายสี bg-blue-200, bg-orange-100 เพิ่มระยะห่าง mb-1 ให้เห็นแต่ละส่วนชัดเจนขึ้น และกำหนดทิศทางของการแสดงผลเป็นแนวตั้งด้วย flex flex-col

<div class="bg-blue-200 flex flex-col">
<Profile class="bg-orange-100 mb-1" />
<Section class="bg-green-200 mb-1">
<ToggleMenu on label="Notification sound" />
<ToggleMenu on label="Hide my likes" />
<ToggleMenu label="Share your information" />
<ToggleMenu label="Personal Hotspot" />
</Section>
<Section class="bg-blue-300 mb-1">
<ToggleMenu on label="Send Auto-Reply" />
<ToggleMenu label="Email Notifications" />
<ToggleMenu label="Newsletter" />
</Section>
</div>
เมื่อระบายสีจะเห็นแต่ส่วนชัดเจนขึ้น

Step 2: เริ่มต้นที่ <Profile> แสดงผลเป็นแนวนอนด้วย flex และแสดงรูปโปรไฟล์เป็นวงกลมด้วย rounded-full จากนั้นกำหนดสีตัวอักษร ขนาดอักษร และระยะห่างให้ตรงตามแบบ

<div class="flex items-center p-4">
<img
class="w-12 h-12 rounded-full mr-4"
src="@/assets/images/avatar.jpg"
alt="Maxwell"
>
<div class="text-2xl text-gray-900">Hello, Maxwell</div>
</div>
แสดงรูปโปรไฟล์เป็นวงกลมด้วย rounded-full

Step 3: จากโค้ด เราใช้ <Section> เพื่อจัดกลุ่มของ <ToggleMenu> ได้สะดวกขึ้น จากแบบ Section จะมีพื้นหลังสีขาว มีระยะห่างจากขอบจอ ขอบโค้งมันและมีเงาขอบเล็กน้อย

<div class="flex flex-col bg-white rounded-lg shadow mx-4 mb-4">
<slot></slot>
</div>
<Section> เพื่อช่วยจัดกลุ่ม <ToggleMenu> ง่ายขึ้น

Step 4: เมื่อลบสีออกจาก <Section> จะทำให้เห็นสีขาว ขอบโค้งมน เงาขอบ และระยะห่างชัดเจนขึ้น

<div class="flex flex-col">
<Profile />
<Section>
<ToggleMenu on label="Notification sound" />
<ToggleMenu on label="Hide my likes" />
<ToggleMenu label="Share your information" />
<ToggleMenu label="Personal Hotspot" />
</Section>
<Section>
<ToggleMenu on label="Send Auto-Reply" />
<ToggleMenu label="Email Notifications" />
<ToggleMenu label="Newsletter" />
</Section>
</div>

Step 5: ภายใน <ToggleMenu> ประกอบด้วย 2 ส่วน คือ Label และ Switch แสดงผลอยู่ในแนวนอน flex ผลักทั้งสองส่วนให้ชิดขอบ justify-between ความสูง h-12 จัดให้อยู่กึ่งกลาง items-center และเส้นขอบล่าง border-b border-gray-200

จากแบบจะเห็นว่า <ToggleMenu> ตัวสุดท้ายของ <Section> นั้นๆ ไม่มีเส้นขอบล่าง ซึ่งเราจะใช้ last-child selector เพื่อจับตัวสุดท้ายและกำหนด Style ตามต้องการ ซึ่งใน Tailwind CSS ก็มี last: ให้ใช้ จากตัวอย่างนี้เราลองกำหนด last:bg-blue-100 เพื่อให้ตัวสุดท้ายเปลี่ยนเป็นสีฟ้า

<div class="flex justify-between items-center h-12 border-b border-gray-200 last:bg-blue-100">
<div>{{ label }}</div>
<ToggleSwitch :on="on" />
</div>
ใช้ last:bg-blue-100 เพื่อจับ element สุดท้ายและใส่พื้นหลังสีฟ้า

จากภาพตัวอย่าง ถ้าซูมเข้าไปจะเห็นว่า <ToggleMenu> ที่เป็นสีฟ้า จะยังมีเส้นขอบล่างขนาด 1px อยู่

Step 6: ลบเส้นของล่างให้กับ <ToggleMenu> ตัวสุดท้ายด้วย last:border-b-0 เมื่อสังเกตุจากแบบจะเห็นว่า <ToggleMenu> แต่ละตัวจะมีเส้นขอบล่างที่แสดงผลต่างกันเล็กน้อย ไม่ชนกับขอบซ้าย ml-4 แต่ทางขวาจะชนกับขอบขาว pr-4 พอดี

<div class="flex justify-between items-center h-12 border-b border-gray-200 last:border-b-0 pr-4 ml-4">
<div class="text-lg text-gray-900">{{ label }}</div>
<ToggleSwitch :on="on" />
</div>
ใช้ last:border-b-0 เพื่อลบเส้นขอบให้กับ element สุดท้าย

Step 7: จาก Step 6 ที่ต้องหาตัวสุดท้ายเพิ่มลบเส้นขอบล่างออก last:border-b-0 ทาง Tailwind CSS มี divide ให้ใช้งาน ทำหน้าที่ใส่เส้นขั้นระหว่าง Elements สามารถใช้ได้ทั้งแนวตั้ง divide-x และแนวนอน divide-y ทำให้เราลบคำสั่งที่เกี่ยวกับเส้นขอบออกได้ทั้งหมด

<div class="flex justify-between items-center h-12 pr-4 ml-4">
<div class="text-lg text-gray-900">{{ label }}</div>
<ToggleSwitch :on="on" />
</div>

เพิ่มเส้นขั้น divide-y และกำหนดสีเส้นขั้น divide-gray-200 ที่ <Section> เพราะเป็น parent element ของ <ToggleMenu>

<div class="flex flex-col bg-white rounded-lg shadow mx-4 mb-4 divide-y divide-gray-200">
<slot></slot>
</div>
สวยงามตามแบบ

สำหรับ Workshop ที่เราเตรียมาก็มีเพียงเท่านั้น สามารถดูตัวอย่างโค้ดเวอร์ชั่นเต็มที่เขียน Tailwind CSS เสร็จแล้ว ได้ที่ goto-tailwindcss branch

ครอบครัว Tailwind CSS ยินดีต้อนรับ

พวกเราประหลาดใจกันมากที่มีผู้คนสนใจ Tailwind CSS กันมากขนาดนี้ (ตั๋วเต็มเร็วมาก) ต้องขอขอบคุณทุกคนที่ให้ความสนใจ ทั้งตัว Workshop ในงาน LINE THAILAND DEVELOPER CONFERENCE 2022 รวมถึงบทความนี้ด้วย

บรรยากาศห้อง Workshop ในงาน LINE THAILAND DEVELOPER CONFERENCE 2022

ถ้าลองทำตาม Workshop และเริ่มสนุกก็ต้องขอบอกว่านี่เป็นส่วนเล็กน้อยที่ Tailwind CSS ทำได้ ยังมีอีกหลายความสามารถที่จะช่วยให้พวกเราพัฒนา UI ได้สะดวกสบายกว่านี้ สำหรับใครที่กำลังจะนำ Tailwind CSS ไปใช้กับทีม ผมขอแนะนำให้อดทนกับการเปลี่ยนแปลงให้ได้ เมื่อทุกคนในทีมคุ้นเคยกับ Tailwind CSS แล้ว ผมเชื่อว่าทุกคนจะประทับใจแน่นอน (หวังว่าจะเป็นแบบนั้น 😅)

บรรยากาศห้อง Workshop ในงาน LINE THAILAND DEVELOPER CONFERENCE 2022

ใครอยากมาร่วมงานกับเรา อยากลองสัมผัสประสบการณ์ใหม่ ลองจิ้มตำแหน่ง Solution Engineer มาได้เลยครับ ได้เขียน Vue + Tailwind CSS แน่นอน!

สุดท้าย! เราอยากได้ความคิดเห็นจากทุกๆคน เพื่อให้พวกเรานำไปปรับปรุง Workshops และเนื้อหาของบทความต่อๆไป ให้ตรงความต้องการของทุกคนมาขึ้นไปอีกครับผม ♥️

--

--

Puwadon Sricharoen
LINE Developers Thailand

I’m an optimistic person. Love to travel to a new places and enjoy to spending my free time and vacation day to pursue my hobbies.