README
นี่เป็นการสะท้อนการเรียนรู้จากการทำ Project ใน FCC หลักสูตร Responsive Web Design Project 1 Tribute Page
โดยผมจะนำการ User Story แต่ละข้อของ Project มา Breakdown ว่าเราจะต้องใช้ความรู้ในเรื่องใดบ้างเพื่อทำให้ Project สำเร็จลุล่วง
ใน Project Tribute Page นี้มี User Story อยู่ 9 ข้อได้แก่
- Your tribute page should have an element with a corresponding
id="main"
, which contains all other elements - You should see an element with an
id
oftitle
, which contains a string (i.e. text), that describes the subject of the tribute page (e.g. "Dr. Norman Borlaug") - You should see either a figure or a div element with an id of
img-div
- Within the
img-div
element, you should see an img element with a correspondingid="image
" - Within the
img-div
element, you should see an element with a correspondingid="img-caption"
that contains textual content describing the image shown inimg-div
- You should see an element with a corresponding
id="tribute-info"
, which contains textual content describing the subject of the tribute page - You should see an a element with a corresponding
id="tribute-link"
, which links to an outside site, that contains additional information about the subject of the tribute page. HINT: You must give your element an attribute of target and set it to _blank in order for your link to open in a new tab - Your
#image
should use max-width and height properties to resize responsively, relative to the width of its parent element, without exceeding its original size - Your
img
element should be centered within its parent element
ตัวอย่าง webpage ที่เสร็จสมบูรณ์โดย FCC Tribute Page
Reflect #1
เรามาเริ่มกันที่ข้อแรก
- My tribute page should have an element with a corresponding
id="main"
, which contains all other elements.
ข้อนี้บอกว่าหน้าตา web page ของเราต้องมี element ที่มี id="main"
โดย element นี้ต้องเป็น element ที่คลุม element อื่น ๆ ทั้งหมด
ปัญหาข้อนี้ทำให้เราต้องกลับมาทำความเข้าใจความรู้พื้นฐานของภาษา HTML โดยผมจะตั้งคำถามไปเรื่อย ๆ โดยหวังว่าหากผมทราบและเข้าใจคำตอบของคำถามต่อไปนี้ ความรู้ความเข้าใจของผมน่าจะอยู่ในระดับที่ "ทำเป็น" ไม่ใช่แค่ "ทำได้"
ต่อไปนี้ผมจะสมมติว่าตัวเองนั้นไม่รู้อะไรในเรื่องของภาษา HTML เลย ดังนั้นคำถามแรกที่ผมต้องถามก็คือ
HTML (Hypertext Markup Language) คืออะไร ?
ผมสรุปได้ดังนี้
HTML เป็นภาษาที่ใช้กำหนดโครงสร้างภาพรวมของ website เป็นเหมือนโครงกระดูกของ website และข้อความที่เราพิมพ์ลงไปจะถูกตีความ (interpret) ผ่านโปรแกรม web browser ต่าง ๆ เช่น Google chrome, IE, Firefox ให้กลายมาเป็นหน้า webpage ที่เราเห็นกันในทุก ๆ website
Syntax ของ HTML หน้าตาเป็นอย่างไร ?
วิธีการอย่างหนึ่งที่ผมเห็นในการเรียนภาษาต่าง ๆ ที่ผมเห็นบ่อย ๆ คือการดู code โดยตรงและค่อย ๆ ถอดองค์ประกอบของมันออกมา
ภาพจาก MDN Web Docs
ตัวอย่างภาษา HTML อย่างง่าย ๆ คือ
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello!</title>
</head>
<body>
Hello, world!
</body>
<html>
เมื่อเรา run ข้อความข้างต้นผ่าน web browser ผลลัพธ์จะออกมาเป็นดังนี้
เรามาดูกันว่า code ข้างบนที่เราเขียนกันไปนั้นมีอะไรบ้าง
-
<!DOCTYPE html>
ข้อความในบรรทัดนี้คือการประกาศ (declare) ต่อ web browser ว่าเรากำลังเขียน HTML version ล่าสุด คือ HTML:HTML5 - บรรทัดต่อ ๆ มาเราจะเห็นข้อความที่ถูกคลุมด้วย <> เจ้าเครื่องหมายนี้เราเรียกว่า Tag ส่วนข้อความภายใน Tag เราจะเรียกว่า element โดยเขียนได้ในรูป
<element>
- เช่น
<head>
หมายความว่า มันคือ Tag ที่มี element เป็น head นั่นเอง -
<title>Hello!</title>
จากบรรทัดนี้เราจะสังเกตเห็นได้ว่ามี Tag อยู่ 2 Tag คือ-
<title>
<< อันนี้เรียกว่า opening tag -
</title>
<< อันนี้เรียกว่า closing tag (มี / นำหน้า element)
-
- จึงสรุปได้ว่า Syntax ของภาษา HTML จะเริ่มต้นด้วย opening tag และ closing tag เสมอ (แต่ก็มีข้อยกเว้นสำหรับ tags บางประเภท)
- ในบรรทัดที่ 2
<html lang="en">
จะเห็นว่าใน tag นอกจากจะมี html เป็น element แล้ว ยังมีข้อความlang="en"
ซึ่งข้อความหลัง element นี้เราเรียกว่า attributes โดย attribute จะมีหน้าที่เพิ่มลักษณะบางอย่างลงไปใน element ให้มีความเฉพาะเจาะจงยิ่งขึ้น เช่นlang="en"
ก็หมายความว่า web page นี้จะใช้ภาษาอังกฤษเป็นภาษาหลักนั่นเอง - จาก code ด้านบนเราจะสามารถเห็น element อีก 2 อย่างคือ head element และ body element โดยมีความแตกต่างดังนี้
- head element - element ต่าง ๆ ที่ถูกคลุมด้วย head element จะไม่ปรากฎให้เห็นในหน้า web page แต่จะไปปรากฎในส่วนอื่น ๆ แทน เช่น ข้อความใน
title
element ก็จะไปปรากฎบน tab ของ web browser - body element - element ต่าง ๆ ที่ถูกคลุมด้วย body element จะปรากฎให้เห็นในหน้า web page เช่น ข้อความ “Hello, world!" ก็จะปรากฎให้เห็นบนหน้า web page
- head element - element ต่าง ๆ ที่ถูกคลุมด้วย head element จะไม่ปรากฎให้เห็นในหน้า web page แต่จะไปปรากฎในส่วนอื่น ๆ แทน เช่น ข้อความใน
DOM (Document Object Model)
เมื่อเราเปิด HTML บนหน้า web browser ตัว web browser จะมอง HTML แบบ DOM คือมอง HTML เป็นลักษณะคล้ายต้นไม้ที่แตกกิ่งก้านสาขาออกมาตาม HTML โดย DOM จะช่วยบ่งบอกลำดับชั้นของ element ได้ ซึ่งจะมีประโยชน์ในภายหลังโดยเฉพาะการทำความเข้าใจในเรื่อง CSS และ Java Script
Reflect #2
จนถึงตอนนี้เราก็จะค่อนข้างเข้าใจโครงสร้างคร่าว ๆ ของ HTML แล้ว เมื่อกลับไปดูที่ User Story #1 กำหนดให้ต้องมี element ที่มี id="main"
โดย element นี้ต้องเป็น element ที่คลุม element อื่น ๆ ทั้งหมด
ซึ่งตอนนี้เราก็รู้แล้วว่า id="main"
ก็คือ attribute ดังนั้นเราก็แค่สร้าง element ที่มี attribute คือ id="main"
นั่นเอง
คำถามต่อมาก็คือควรจะใช้ element อะไร? และที่สำคัญคือ HTML มี element อะไรให้เลือกใช้บ้าง ?
ประเภทของ element มีอะไรบ้าง
element ในภาษา HTML มีหลายประเภท ขึ้นอยู่ว่าเราอยากให้ web page ออกมามีหน้าตาเป็นอย่างไร มี heading, list, มีข้อความที่เป็นตัวหนา ฯลฯ เป็นต้น
สามารถดูรายละเอียดประเภทของ element ต่าง ๆ ได้ที่นี่
HTML elements reference - HTML: HyperText Markup Language | MDN
Reflect #3
กลับมาคำถามที่ว่าเราควรจะใช้ element ไหนตามโจทย์ User Story #1 ซึ่งเมื่อดูตามตัวอย่างที่ FCC ให้มาและพิจารณาจากโจทย์ข้ออื่น ๆ แล้วนั้นจะพบว่าใน webpage ต้องมีข้อมูลค่อนข้างหลากหลายประเภททั้ง text, image ดังนั้น element ที่ผมต้องการคือ element ที่สามารถคลุม element อื่น ๆ ได้ด้วยไม่ว่า element นั้นจะเป็น text หรือ image หรืออะไรก็ตาม
ผมจึงเลือกใช้ element ประเภท Content sectioning โดย element ประเภทนี้จะมีหน้าที่ช่วยจัดการ content ต่าง ๆ ให้เป็นสัดส่วน โดยผมเลือกใช้ <main>
เพราะว่าเป็น element ที่สามารถคลุมเนื้อหาหลัก ๆ ได้ครบถ้วนคล้าย <body>
ในกรณีนี้ผมเลือกใช้ <main>
เพราะมีความยืดหยุ่นในการใช้งานมากกว่า
ผลลัพธ์จึงออกมาดังนี้
<main id="main">
</main>
คำถามต่อมาคือ id="main"
เป็น attribute ที่บ่งบอกถึงอะไรกันแน่
id
ย่อมาจาก identifier มีลักษณะเป็น global attribute ซึ่งสามารถใช้กับ element ได้ทุกประเภท (มีข้อยกเว้นเล็กน้อยแต่จะยังไม่พูดถึง)
id
ถูกใช้เพื่อเชื่อมโยง element เข้ากับส่วนอื่น ๆ เช่น CSS
แล้วมันจะเชื่อมโยงกับ CSS ได้อย่างไรล่ะ ?
ว่าก็ว่า CSS คืออะไรกันนะ
CSS (Cascading Style Sheets) คืออะไร ?
CSS เป็นภาษาที่เราจะใช้ในการตกแต่งหน้าตาของ website เช่น สี, ขนาดของ font, การจัดลำดับตัวอักษร และอื่น ๆ อีกมากมายที่เราทำได้ใน CSS
Syntax ของ CSS หน้าตาเป็นอย่างไร ?
div.bold-text {
font-weight: 700;
}
*ภาพจาก The Odin Project
- Syntax ของ CSS เบื้องต้นประกอบไปด้วย 3 ส่วนหลัก ๆ selector, property และ value
Selector
- ใน webpage ของเรานั้นมักจะ element มากมายหลายส่วน เช่น heading main footer นอกจากนั้นยังมีส่วนที่เป็น content อื่น ๆ อีกเช่น text image video
- เพื่อความสวยงามแล้วเราคงไม่อยากที่จะให้หน้า webpage มีสีเดียวหรือมี font ขนาดเดียวกันหมดทั้งหน้า ซึ่ง selector จะสามารถเข้ามาทำหน้าที่แก้ไขปัญหาตรงนี้
- selector มีหน้าที่ในการอ้างอิง (refer) ถึง element ในส่วนของ HTML ที่ CSS จะมีผล หมายความว่าเราสามารถกำหนดได้ว่า element ไหนจะมีหน้าตาอย่างไรได้นั่นเอง (และมันก็จะไม่ส่งผลต่อ element อื่น ๆ ด้วย เจ๋งไปเลยใช่มั้ยล่ะ)
- Selector มีหลากหลายประเภทตามแต่ลักษณะการใช้งาน ในที่นี้จะยกตัวอย่างที่พบเจอและใช้งานบ่อย ๆ ดังนี้
- Universal selector
- Type selector
- Class selectors
- ID selector
- Grouping selector
- Chaining Selector
- Descendent combinator
Universal Selector
- Universal selector จะทำการกำหนดทุก element ในหน้า webpage เช่น
*{
color: purple;
}
-
*
คือ Universal selector - ดังนั้นหมายความว่าทุก element จะมี
color: purple;
นั่นเอง
Type selector
- Type selector หรือเรียกอีกอย่างว่า element selector จะทำการกำหนด element ประเภทนั้นทั้งหมด เช่น
HTML
<!-- index.html -->
<header>
<p>Sukit Blog<p>
</header>
<main>
<h1>Welcome to my block</h1>
<p>This is my projects</p>
</main>
<footer>
<p>footer part<p>
</footer>
CSS
/* styles.css */
header {
background-color: black;
}
main {
background-color: lightgrey;
}
h1 {
color: blue;
}
p {
color: red;
}
footer {
background-color: lightgreen;
}
ผลลัพท์ก็จะออกมาเป็น
- เราจะเห็นจาก CSS ว่ามีการใช้ Type selector เช่น
<header>
ถูกกำหนดให้มีbackground-color
เป็นblack
ฉะนั้นส่วนที่เป็น<header>
จึงปรากฎสีพื้นหลังเป็นสีดำ -
<main>
และ<footer>
ก็มีการกำหนดbackground-color
เช่นเดียวกันทำให้ทั้ง<header>
<main>
และ<footer>
มีสีที่แตกต่างกันตามภาพตัวอย่าง -
<p>
เป็น element ที่ใช้ในการแสดงข้อความแบบ paragraph ถูกกำหนดให้ color เป็น red ดังนั้นไม่ว่า<p>
จะอยู่ตรงไหนของหน้า webpage จะเป็นมีสีแดงเสมอ สังเกตได้จากไม่ว่าจะเป็น<p>
ใน<head>
<main>
หรือ<footer>
ก็ล้วนมีสีแดงนั่นเอง
Class Selectors
- Class selector จะทำการกำหนด element ที่มี class attribute อยู่ใน element นั้น ๆ นี่คือตัวอย่างการใส่ class attribute ลงใน element ของ HTML
- การใช้ Class Selector ใน CSS จะเริ่มต้นด้วยเครื่องหมาย . นำหน้า
<div class="cancel-text">
Are you sure?
</div>
<div class="agree-text">
Done
</div>
.cancel-text {
color: red;
}
.agree-text {
color: green;
}
ผลลัพธ์จะออกมาเป็น
- จาก HTML เราจะเห็นได้ว่าใน
<div>
อันแรกจะมี attributeclass="cancel-text"
ซึ่งเมื่อดู CSS ควบคู่กันก็จะเห็นได้ว่ามีการกำหนดให้ class.cancel-text
มีcolor
เป็นred
เราจึงเห็นข้อความ “Are you sure?" เป็นสีแดง - ในส่วนของ
<div>
อันที่สอง มี attributeclass="agree-text"
ซึ่งแตกต่างจาก<div>
อันแรก เมื่อดู CSS จะเห็นได้ว่ามีการกำหนดให้.agree-text
มีcolor
เป็นgreen
เราจึงเห็นข้อความ “Done" เป็นสีเขียว - Class selector จึงมีประโยชน์ในกรณีที่เราต้องการให้ element ประเภทเดียวกันมีล property และ value แตกต่างกัน เหมือนตัวอย่างข้างบนที่มี element เป็น
<div>
เหมือนกันแต่มีสีแตกต่างกันนั่นเอง - ใน 1 element มี class ได้หลาย class โดยใช้ whitespace (เคาะ space bar 1 ครั้ง) เช่น
<div class="messagebox">
This is an informational note.
</div>
<div class="messagebox warning">
This note shows a warning.
</div>
<div class="messagebox danger">
This note shows danger!
</div>
- จะเห็นว่าใน
<div>
อันแรกจะมี class เดียว นั่นก็คือmessagebox
-
<div>
อันที่ 2 จะมี 2 class คือmessagebox
และwarning
-
<div>
อันที่ 3 ก็เช่นเดียวกัน มี 2 class คือmessagebox
และdanger
ID Selector
- ID Selector มีคุณสมบัติคล้ายคลึงกับ Class Selector วิธีการใช้ก็คล้ายคลึงกันโดยการนำ ID attribute ใส่ลงไปใน element
- การใช้ ID Selector ใน CSS จะเริ่มต้นด้วยเครื่องหมาย # นำหน้า
<!-- index.html -->
<div id="title">My profile</div>
/* styles.css */
#title {
color: white;
background-color: red;
}
ผลลัพธ์จะออกมาเป็น
- ผลลัพธ์จะมีความคล้ายคลึงกับการใช้ Class selector เป็นอย่างมาก
- แต่ก็ยังมีส่วนที่แตกต่างกันอยู่คือ ใน 1 element จะมี ID ได้แค่อันเดียว ในขณะที่มี Class ได้หลายอัน
- แม้ว่า Class กับ ID จะมีความคล้ายคลึงกันในฐานะ Selector ของ CSS แต่ในฐานะที่เป็น attribute ใน HTML จะสามารถใช้งานได้หลากหลายกว่า (จะพูดถึงภายหลัง)
ลองนึกภาพเวลาเราทำ webpage แล้วมี element class id ต่าง ๆ จำนวนมาก การจะมานั่งกำหนด property และ value ของแต่ละ element หรือ class ทีละอัน คงมีอาการปวดหลัง ตาแห้ง กันบ้าง selector ต่อไปนี้จะมีส่วนช่วยในการจัดการกับปัญหาดังกล่าว
Grouping Selector
- Grouping Selector จะเข้ามาช่วยในกรณีที่เรามี element หลาย ๆ element ที่มีลักษณะเหมือนกัน
- ตัวอย่างเช่น
.read {
color: white;
background-color: black;
}
.unread {
color: white;
background-color: black;
}
- จากตัวอย่างดังกล่าวเราจะเห็นได้ว่า .read กับ .unread มี property และ value เหมือนกัน แต่ที่ต้องเขียนแยกกันเพราะเป็นคนละ class ในกรณีนี้เราสามารถใช้ grouping selector โดยใช้เครื่องหมาย , คั่น ดังตัวอย่างข้างล่าง
.read,
.unread {
color: white;
background-color: black;
}
.read {
/* property อื่น ๆ ที่ไม่อยากให้เหมือนกัน */
}
.unread {
/* property อื่น ๆ ที่ไม่อยากให้เหมือนกัน */
}
- การใช้ grouping selector สามารถใช้ในรูป
class,class
element,element
ก็ได้ - แหล่งอ้างอิงบางแหล่งเรียกการใช้เครื่องหมาย , ใน selector ลักษณะนี้ว่า Selector list
Chaining Selector
- Chaining Selector สามารถใช้ในกรณีที่ 1 element มีหลาย class สามารถดูได้จากตัวอย่างต่อไปนี้
<!-- index.html -->
<div class="messagebox">
This is an informational message.
</div>
<div class="messagebox warning">
This message shows a warning.
</div>
<div class="messagebox danger">
This message shows danger!
</div>
<div class="danger">
This won't get styled — it also needs to have the messagebox class
</div>
- จะเห็นว่าใน
<div>
อันแรกจะมี class เดียว นั่นก็คือmessagebox
-
<div>
อันที่ 2 จะมี 2 class คือmessagebox
และwarning
-
<div>
อันที่ 3 ก็เช่นเดียวกัน มี 2 class คือmessagebox
และdanger
- ทีนี้หากเราต้องการกำหนด style ให้
messagebox
มีลักษณะเป็นกรอบล้อมรอบสามารถทำได้ดังนี้
/* styles.css */
.messagebox {
border: 4px solid #666;
padding: .5em;
margin: 10px;
}
ก็จะได้ผลลัพธ์ประมาณนี้
- เราจะเห็นได้ว่าทุก
<div>
ที่มี classmessagebox
จะมีขอบขึ้นมาล้อมรอบแล้ว - ต่อมาเราอยากให้ขอบของ class
messagebox
warning
และmessagebox
danger
มีตัวอักษรตัวหนาและมีสีที่แตกต่างออกไป สามารถใช้ chaining selector โดยเขียนได้ในรูป.classname1.classname2
โดยไม่ต้องมี whitespace คั่น
/* styles.css */
.messagebox {
border: 4px solid #666;
padding: .5em;
margin: 10px;
}
.messagebox.warning {
border-color: orange;
font-weight: bold;
}
.messagebox.danger {
border-color: red;
font-weight: bold;
}
ผลลัพธ์ก็จะออกมาดังนี้
Descendant Combinator
- Combinator เป็น selector ที่รวม (combine) selector อื่น ๆ ไว้ด้วยกัน มีประโยชน์หลากหลาย
- Combinator มีหลายประเภท แต่ในที่นี้จะกล่าวถึงแค่ Descendent combinator อย่างเดียว เพราะพบได้พบและใช้งานบ่อย
- เราสามารถเขียน descendent combinator ได้โดยใช้ whitespace คั่นกลางระหว่าง element เช่น
.classname1 .classname2
- การทำงานของ descendent combinator จะมีกระบวนการดังนี้
- จะกำหนด style ให้กับ element ที่มี
class="classname2"
- โดย element ที่มี
classname2
นี้ต้องเป็นลูก (child) ของ element ที่มีclass="classname1"
เท่านั้น
- จะกำหนด style ให้กับ element ที่มี
<!-- index.html -->
<div class="box">
<div class="content">
This is .content in .box
</div>
</div>
<div class="contents">This is .content but not in .box</div>
/* styles.css */
.box {
border: 4px solid #666;
padding: .5em;
margin: 10px;
}
.box .content {
color: red;
ผลลัพธ์ที่ได้ก็คือ
- จะเห็นได้ว่าใน
<div class="box">
คลุม<div class="content">
ไว้อยู่ ในกรณีนี้เราถือว่า<div class="content">
เป็น child element ของclass="box"
- เมื่อเราเขียนใน CSS โดยกำหนด selector เป็น
.box .content
ให้มีcolor: red;
ข้อความ “This is .content in .box" จึงมีสีแดงตามหลักการทำงานของ descendent combinator - ส่วน
<div class="content">
ที่มีข้อความ “This is .content but not in box" ไม่ได้เป็น child element ในclass="box"
ข้อความดังกล่าวจึงไม่มีสีแดง หรือก็คือไม่ได้ถูกกำหนดใน.box .content
นั่นเอง - Descendent combinator ใช้ได้ทั้งกับ element ทั่ว ๆ ไป และ class
หลังจากร่ายเรื่อง Selector มาพอเข้าใจ ต่อไปเราไปดูส่วนอื่น ๆ ของ CSS กันบ้าง
Property
*ภาพจาก The Odin Project
หลังจากเราเข้าใจการทำงานของ selector แล้ว ต่อไปคือการทำความเข้าใจเรื่อง property
- property จะเป็นตัวกำหนดลักษณะ หรือ style เช่น
color: blue
หรือtext-align: center
- property ใน CSS มีจำนวนมากเกินจะนับ สามารถศึกษาเพิ่มเติมได้ที่นี่ https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference
- properties ที่เจอบ่อยและควรรู้มีดังนี้
-
color
: สีของข้อความ (text) -
text-align
: จัดตำแหน่ง element เช่น ชิดซ้าย ตรงกลาง ชิดขวา -
background-color
: สีของ background -
width
: ขนาดความกว้าง -
height
: ขนาดความยาว -
padding
: ขนาดพื้นที่ภายใน element -
margin
: ขนาดพื้นที่ภายนอก element -
font-family
: ชนิดของ font -
font-size
: ขนาดของ font -
border
: ขนาด สี ของเส้นขอบ
-
- เราจะเห็นภาพของแต่ละ property มากขึ้นในภายหลัง
Value
*ภาพจาก The Odin Project
- value เป็นค่าที่เราใช้กำหนด property อีกที เช่น
color: red
คือการกำหนด propertycolor
ให้มีค่า(value) เป็นred
หรือสีแดงนั่นเอง - เราจะศึกษาเรื่องของ value ในแต่ละ property อีกทีในภายหลัง
Reflect #4
หลังจากเราไปศึกษาลักษณะเบื้องต้นของ CSS ไปพอสมควรแล้วกลับมาดู code ของเราต่อ
<main id="main">
</main>
สรุป สิ่งที่เราเข้าใจสิ่งที่เราเขียนลงไปตอนนี้
- เราใช้
<main>
เป็น element หลักให้คลุมเนื้อหาทั้งหมดใน webpage - เราใช้
id="main"
เพื่อน่าจะได้ใช้ ID Selector ในภายหลัง -
<main>
กับid="main"
แม้จะมีคำว่า main เหมือนกันแต่ไม่เกี่ยวข้องกัน อันแรกเป็นประเภทของ element ส่วนอันที่สอง main เป็นเพียงชื่อที่เราตั้งให้ attribute ID
ข้อนี้เป็นก้าวแรกในการทำ project ดังนั้นเนื้อหาอาจจะเยอะหน่อย แต่ในข้อต่อ ๆ ไปก็จะง่ายขึ้นครับ
Reference
FreeCodeCamp
MDN Web Docs
The Odin Project
CS50’s Web Programming with Python and JavaScript By Havard University
หรือจะสนับสนุนผมก็ทำได้ผ่านช่องทางข้างล่างนี้ครับ
https://www.buymeacoffee.com/sukitbunsiv
Top comments (0)