Back

ปูพื้นฐานการเขียนเว็บด้วย HTML, CSS และ JavaScriptBlur image

บทความนี้จะพาคุณเริ่มต้นสร้างหน้าเว็บทีละขั้น จาก HTML สำหรับวางโครงสร้างและเนื้อหา ต่อด้วย CSS สำหรับตกแต่งและจัดวางองค์ประกอบ แล้วเรียนรู้พื้นฐาน JavaScript ผ่านตัวอย่างบน React/Next.js เพื่อแสดงข้อมูลและเลือกเนื้อหาตามเงื่อนไข

เนื้อหาแบ่งเป็น 3 ส่วน โดยแต่ละส่วนต่อยอดจากสิ่งที่ได้เรียนรู้ก่อนหน้า:

  1. ส่วนที่ 1 — HTML: สร้างโครงสร้างหน้าเว็บด้วยหัวข้อ ลิงก์ รูปภาพ รายการ ตาราง และแบบฟอร์ม
  2. ส่วนที่ 2 — CSS: เรียนรู้การใส่สไตล์ทั้ง 3 แบบ การใช้ class การสร้างแถบนำทาง และการจัดวางด้วย Flexbox
  3. ส่วนที่ 3 — JavaScript กับ Next.js: ทำความรู้จัก React component และใช้พื้นฐาน JavaScript เพื่อแสดงข้อมูลบนหน้าเว็บ

ส่วนที่ 1: พื้นฐาน HTML#

1.1 HTML คืออะไร?#

HTML (HyperText Markup Language) เป็นภาษามาร์กอัปที่ใช้กำหนดโครงสร้างและความหมายของเนื้อหาบนหน้าเว็บ โดยนำองค์ประกอบต่าง ๆ ที่เรียกว่า element เช่น หัวข้อ ย่อหน้า และรูปภาพ มาประกอบกันเป็นหน้าเว็บ

1.2 เตรียมเครื่องมือและตั้งค่าโปรเจกต์#

ข้อกำหนดเบื้องต้น: ติดตั้ง VS Code จาก code.visualstudio.com ↗

VS Code เป็นโปรแกรมแก้ไขโค้ดที่เราจะใช้สร้างและแก้ไขไฟล์ตลอดบทความ เริ่มจากสร้างโฟลเดอร์สำหรับเก็บงาน แล้วเปิดโฟลเดอร์นั้นใน VS Code ด้วยคำสั่งด้านล่าง

การตั้งค่าโปรเจกต์

# สร้างโฟลเดอร์สำหรับโปรเจกต์
mkdir web-basics
cd web-basics

# สร้างโฟลเดอร์สำหรับไฟล์ HTML
mkdir 01_html
cd 01_html

# เปิด VS Code ในโฟลเดอร์ปัจจุบัน
code .
bash

1.3 โครงสร้างพื้นฐานของ HTML#

ใน VS Code ให้สร้างไฟล์ชื่อ index.html พิมพ์ html:5 แล้วกด Enter/Tab เพื่อสร้างโครงสร้าง HTML เริ่มต้น:

html:5

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Website</title>
</head>
<body>

</body>
</html>
html

โดยทั่วไป element ประกอบด้วยแท็กเปิด (opening tag) เนื้อหา (content) และแท็กปิด (closing tag) แต่บาง element เช่น <img> ไม่มีแท็กปิด ส่วนแอตทริบิวต์ (attribute) ใช้ระบุข้อมูลเพิ่มเติมในแท็กเปิด โดยมักเขียนเป็นคู่ของชื่อและค่า ดังภาพ:

Anatomy of an HTML element

องค์ประกอบพื้นฐานของ HTML

Elementคำอธิบาย
<!DOCTYPE html>ประกาศว่าเอกสารนี้เป็น HTML5
<html>รากของเอกสาร HTML
<head>บรรจุข้อมูลเมตาดาต้า (ไม่แสดงบนหน้าเว็บ)
<title>กำหนดชื่อหน้าเว็บ แสดงที่แถบชื่อเบราว์เซอร์
<body>บรรจุเนื้อหาที่แสดงบนหน้าเว็บ
<h1> - <h6>หัวข้อ 6 ระดับ โดย <h1> เป็นหัวข้อระดับหลัก
<p>ย่อหน้าข้อความ
<a href="URL">ลิงก์ไปยังหน้าเว็บอื่น
<img src="..." alt="...">แทรกรูปภาพ

1.4 แสดงตัวอย่างหน้าเว็บใน VS Code#

หากต้องการดูตัวอย่างหน้าเว็บโดยไม่ต้องเปิดเบราว์เซอร์แยก ให้คลิกขวาที่ไฟล์ index.html แล้วเลือก Open in Integrated Browser:

Open in Integrated Browser

จากนั้นจะเห็นตัวอย่างหน้าเว็บภายใน VS Code ดังภาพ:

Integrated Browser preview

1.5 หัวข้อและย่อหน้า#

แท็ก <h1> ถึง <h6> ใช้กำหนดลำดับของหัวข้อ (heading) เริ่มจาก <h1> สำหรับหัวข้อหลัก ไปจนถึง <h6> สำหรับหัวข้อย่อยระดับลึก ในตัวอย่างนี้เราจะใช้ <h1> เป็นชื่อหลักของหน้า และใช้ <h2> แบ่งเนื้อหาออกเป็นหมวด ส่วนแท็ก <p> ใช้เขียนข้อความแต่ละย่อหน้า

เพิ่มหัวข้อและย่อหน้าต่อไปนี้ภายใน <body> ของไฟล์ index.html:

<body>
  <h1>Karn Yongsiriwit</h1>
  <p>Welcome to my website</p>
  <h2>News</h2>
  <p>Read the latest news from our website</p>
  <h2>Events</h2>
  <p>We have many upcoming events</p>
</body>
html

Heading and paragraph

1.6 ลิงก์ (Anchor Tag)#

เมื่อมีเนื้อหาบนหน้าเว็บแล้ว เราสามารถใช้แท็ก <a> (anchor) สร้างลิงก์ไปยังหน้าอื่น โดยระบุปลายทางในแอตทริบิวต์ href ตัวอย่างนี้มีทั้งลิงก์ภายใน (internal link) ที่ใช้พาธ about.html เพื่อเปิดไฟล์ในโฟลเดอร์เดียวกัน และลิงก์ภายนอก (external link) ที่ใช้ URL เต็ม เช่น https://melivecode.com เพื่อเปิดเว็บไซต์อื่น

สร้างไฟล์ชื่อ about.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>About</title>
</head>
<body>
  <h1>About Me</h1>
</body>
</html>
html

ใน index.html เพิ่มลิงก์สำหรับหน้าเว็บภายในและภายนอก:

<!-- Internal link -->
<a href="about.html">About Us</a>

<!-- External link -->
<a href="https://melivecode.com">Visit MeLiveCode</a>
html

Link

1.7 รูปภาพ#

นอกจากข้อความและลิงก์แล้ว เรายังเพิ่มรูปภาพด้วยแท็ก <img> ได้ โดยระบุตำแหน่งรูปในแอตทริบิวต์ src ซึ่งอาจเป็นพาธของไฟล์ในโปรเจกต์ เช่น cat_meme.jpg หรือ URL ของรูปบนอินเทอร์เน็ต ส่วน alt ใช้เขียนข้อความอธิบายรูปสำหรับผู้ที่มองไม่เห็นภาพหรือเมื่อโหลดรูปไม่สำเร็จ และใช้ width กับ height กำหนดขนาดที่แสดง:

<!-- Local image -->
<img src="cat_meme.jpg" alt="A funny cat" width="100px" height="150px" />

<!-- Image from the internet -->
<img src="https://melivecode.com/img/logo.png" alt="A bear writing code" height="150px" />
html

Link and image

1.8 รายการ (Lists)#

เมื่อมีข้อมูลหลายรายการ ให้เลือกรูปแบบตามความหมายของข้อมูล หากลำดับไม่สำคัญ ใช้ <ul> เพื่อสร้างรายการแบบไม่มีลำดับ (unordered list) ซึ่งปกติแสดงเป็นจุดนำหน้า แต่หากเป็นขั้นตอนหรือข้อมูลที่ลำดับมีความหมาย ใช้ <ol> เพื่อสร้างรายการแบบมีลำดับ (ordered list) ซึ่งปกติแสดงเป็นตัวเลข ทั้งสองแบบใช้ <li> (list item) ครอบแต่ละรายการ:

<!-- Unordered list -->
<ul>
  <li>A new teacher joined the team</li>
  <li>Heavy rain in the city</li>
  <li>Weekend market opens downtown</li>
</ul>

<!-- Ordered list -->
<ol>
  <li>Welcome event</li>
  <li>National holiday</li>
  <li>Semester break</li>
</ol>
html
แท็กคำอธิบาย
<ul>รายการไม่มีลำดับ (bullet points)
<ol>รายการมีลำดับ (ตัวเลข)
<li>รายการย่อย

List

1.9 ตาราง (Tables)#

สำหรับข้อมูลที่ต้องอ่านเทียบกันเป็นแถวและคอลัมน์ ให้ใช้แท็ก <table> โดยสร้างแต่ละแถวด้วย <tr> (table row) ใช้ <th> (table header) สำหรับช่องหัวตาราง และใช้ <td> (table data) สำหรับช่องข้อมูล โดยปกติเบราว์เซอร์จะแสดงข้อความใน <th> เป็นตัวหนาและจัดกึ่งกลาง

สร้างไฟล์ชื่อ table.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Table</title>
</head>
<body>
  <table>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>City</th>
    </tr>
    <tr>
      <td>Karn Yong</td>
      <td>30</td>
      <td>Bangkok</td>
    </tr>
    <tr>
      <td>Parkpoom Beer</td>
      <td>25</td>
      <td>Chiang Mai</td>
    </tr>
  </table>
</body>
</html>
html
แท็กคำอธิบาย
<table>กำหนดขอบเขตของตาราง
<tr>แถวของตาราง (table row)
<th>ช่องหัวตาราง (table header)
<td>ช่องข้อมูล (table data)

คลิกขวาที่ไฟล์ table.html แล้วเลือก Open in Integrated Browser (ดูหัวข้อ 1.4) เพื่อดูผลลัพธ์:

Table

1.10 แบบฟอร์ม (Forms)#

แท็ก <form> ใช้จัดกลุ่มช่องรับข้อมูลจากผู้ใช้ เช่น ชื่อผู้ใช้และรหัสผ่าน พร้อมกำหนดปลายทางสำหรับส่งข้อมูลไปประมวลผล ตัวอย่างต่อไปนี้เป็นโครงสร้างหน้าเข้าสู่ระบบ

สร้างไฟล์ชื่อ login.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Login</title>
</head>
<body>
  <h1>Login</h1>
  <form action="login.php" method="POST">
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" />
    <br />
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" />
    <br />
    <input type="checkbox" id="remember" name="remember" />
    <label for="remember">Remember me</label>
    <br/>
    <input type="submit" value="Login" />
  </form>
</body>
</html>
html

Form

องค์ประกอบของแบบฟอร์ม

Elementวัตถุประสงค์
<form action="">ครอบองค์ประกอบของแบบฟอร์ม โดย action ระบุปลายทางที่รับข้อมูล
<label for="id">ระบุข้อความกำกับช่องรับข้อมูล และเชื่อมกับช่องนั้นผ่านค่า id
<input>สร้างช่องรับข้อมูลหรือปุ่มตามชนิด เช่น text, password, checkbox และ submit
id attributeระบุองค์ประกอบ เพื่อให้ for ของ label อ้างถึงได้
name attributeกำหนดชื่อที่ใช้ส่งค่าของช่องรับข้อมูล

หมายเหตุ: สำหรับ HTML elements และตัวอย่างเพิ่มเติม สามารถดูได้ที่ W3Schools HTML ↗


ส่วนที่ 2: พื้นฐาน CSS#

2.1 CSS คืออะไร?#

เมื่อ HTML กำหนดโครงสร้างและเนื้อหาแล้ว เราจะใช้ CSS (Cascading Style Sheets) จัดการรูปลักษณ์ของหน้าเว็บ เช่น สีพื้นหลัง แบบอักษร ระยะห่าง และตำแหน่งขององค์ประกอบ

2.2 การตั้งค่าโปรเจกต์#

# เข้าไปที่โฟลเดอร์โปรเจกต์
cd web-basics

# สร้างโฟลเดอร์สำหรับไฟล์ CSS
mkdir 02_css
cd 02_css

# เปิด VS Code ในโฟลเดอร์ปัจจุบัน
code .
bash

ใน VS Code สร้างไฟล์ชื่อ index.html พิมพ์ html:5 แล้วกด Enter/Tab เพื่อสร้างโครงสร้าง HTML เริ่มต้น:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Practice</title>
</head>
<body>

</body>
</html>
html

2.3 วิธีใส่ CSS มี 3 แบบ#

เราสามารถเพิ่ม CSS ให้หน้าเว็บได้ 3 วิธี ได้แก่ inline สำหรับกำหนดสไตล์เฉพาะองค์ประกอบ, internal สำหรับเขียนสไตล์ไว้ในหน้าเดียวกัน และ external สำหรับแยกสไตล์เป็นอีกไฟล์

Three ways to add CSS

1. Inline CSS

กำหนดสไตล์ให้ element โดยตรงผ่านแอตทริบิวต์ style ดังตัวอย่างที่เปลี่ยนสีพื้นหลังและสีหัวข้อ:

<body style="background-color: beige;">
  <h1 style="color: darkblue;">Hello World</h1>
</body>
html

2. Internal CSS (Style Element)

เขียนกฎ CSS ไว้ในแท็ก <style> ภายใน <head> เพื่อรวมสไตล์ของหน้านั้นไว้ในจุดเดียว:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Styled Page</title>
  <style>
    body {
      background-color: beige;
    }
    h1 {
      color: darkblue;
      font-size: 32px;
    }
  </style>
</head>
<body>
  <h1>Hello World</h1>
</body>
</html>
html

3. External CSS (แนะนำ)

แยก CSS ไว้ในไฟล์ style.css แล้วเชื่อมกับ HTML ด้วยแท็ก <link> วิธีนี้ช่วยให้แก้ไขสไตล์ได้สะดวกและใช้ไฟล์เดียวร่วมกันได้หลายหน้า เราจะใช้วิธีนี้ในตัวอย่างถัดไป

ไฟล์: style.css

body {
  background-color: beige;
  margin: 0;
}

h1 {
  color: darkblue;
}
css

ไฟล์: index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Styled Page</title>
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <h1>Hello World</h1>
</body>
</html>
html

CSS example

2.4 รูปแบบของ CSS Rule#

จากตัวอย่างก่อนหน้า กฎ CSS แต่ละชุดเริ่มด้วย selector เพื่อเลือกองค์ประกอบ แล้วกำหนดคู่ property: value ภายในวงเล็บปีกกา ดังนี้:

selector {
  property: value;
  property: value;
}
css

Anatomy of a CSS rule

ส่วนคำอธิบาย
selectorเลือก HTML elements ที่จะใช้สไตล์ (element, class, หรือ id)
propertyคุณสมบัติที่ต้องการกำหนด (background-color, color, font-size, margin, padding)
valueค่าของคุณสมบัตินั้น (aqua, #FF0000, 16px)

หมายเหตุ: สำหรับอ้างอิง CSS properties สามารถดูได้ที่ W3Schools CSS Reference ↗

2.5 CSS Classes และ Div Elements#

เมื่อหลายองค์ประกอบต้องใช้สไตล์เดียวกัน เราสามารถกำหนด class ให้กับองค์ประกอบเหล่านั้น แล้วใช้ CSS class selector เลือกตกแต่งพร้อมกันได้ ตัวอย่างนี้ใช้ class box กับ <div> สองกล่อง

ทำต่อในไฟล์เดิมจากหัวข้อก่อนหน้า โดย เพิ่ม โค้ดด้านล่างเข้าไป ส่วนคอมเมนต์ ...existing... ใช้แทนโค้ดเดิมที่ต้องเก็บไว้ ไม่ต้องคัดลอกคอมเมนต์นี้ไปแทนเนื้อหาเดิม

ไฟล์: style.css

/* ...existing styles... */

.box {
  border: 2px solid brown;
  width: 200px;
  padding: 10px;
  margin: 10px;
}
css

ไฟล์: index.html

<body>
  <!-- ...existing content... -->

  <div class="box">
    <h1>Box 1</h1>
    <p>This is the content of box 1</p>
  </div>
  <div class="box">
    <h1>Box 2</h1>
    <p>This is the content of box 2</p>
  </div>
</body>
html

CSS classes and div

Conceptคำอธิบาย
<div>คอนเทนเนอร์ทั่วไปสำหรับรวม elements เข้าด้วยกัน
.classnameCSS class selector (เริ่มต้นด้วยจุด)
#idnameCSS ID selector (เริ่มต้นด้วยเครื่องหมาย #)

2.6 แถบนำทาง (Navigation Bar)#

ต่อไปเราจะนำ <ul> และ <li> มาสร้างแถบนำทาง โดย เพิ่ม CSS ลงในไฟล์เดิม และวางรายการลิงก์ไว้ตอนต้นของ <body> ส่วนคอมเมนต์ ...existing... ใช้แทนโค้ดเดิมที่ต้องเก็บไว้

ไฟล์: style.css

/* ...existing styles... */

.navMenu {
  list-style-type: none;
  margin: 0;
  padding: 0;
  background-color: darkgreen;
  overflow: hidden;
}

.navItem {
  float: left;
}

.navItem a {
  color: white;
  text-decoration: none;
  display: block;
  padding: 14px 16px;
  text-align: center;
}

.navItem a:hover {
  background-color: #115511;
}
css

ไฟล์: index.html

<body>
  <!-- Add the navigation bar at the top of the body -->
  <ul class="navMenu">
    <li class="navItem"><a href="index.html">Home</a></li>
    <li class="navItem"><a href="about.html">About Us</a></li>
    <li class="navItem"><a href="contact.html">Contact</a></li>
  </ul>

  <!-- ...existing content... -->
</body>
html

Navigation bar

คำอธิบายคุณสมบัติ CSS

PropertyValueคำอธิบาย
list-style-typenoneลบ bullet points ออกจากรายการ
margin0ลบระยะห่างภายนอก
padding0ลบระยะห่างภายใน
background-colordarkgreenกำหนดสีพื้นหลัง
overflowhiddenครอบ elements ที่ลอยอยู่ภายใน parent
floatleftวางรายการแนวนอน
text-decorationnoneลบเส้นใต้ลิงก์
displayblockทำให้ทั้งพื้นที่คลิกได้

2.7 Flexbox Layout#

หลังจากจัดแถบนำทางด้วย float แล้ว เราจะลองใช้ Flexbox เพื่อจัดเรียงการ์ด Flexbox เป็นระบบจัดวางของ CSS ที่เรียงองค์ประกอบเป็นแถวหรือคอลัมน์ได้ เมื่อกำหนด display: flex องค์ประกอบนั้นจะเป็น flex container และองค์ประกอบลูกโดยตรงจะเป็น flex items ซึ่งเราสามารถกำหนดการแบ่งพื้นที่ การจัดกึ่งกลาง และระยะห่างได้

Flexbox layout

Responsive คือการออกแบบให้หน้าเว็บปรับการแสดงผลตามขนาดหน้าจอ ในตัวอย่างนี้ flex-wrap: wrap ช่วยให้การ์ดขึ้นบรรทัดใหม่เมื่อพื้นที่ในแถวไม่พอ

สร้างไฟล์ใหม่ สองไฟล์ในโฟลเดอร์เดิม ชื่อ flexbox.css และ flexbox.html สำหรับทดลองจัดวางการ์ดตามตัวอย่างด้านล่าง

ไฟล์: flexbox.css

body {
  background-color: beige;
  margin: 0;
}

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 20px;
  padding: 20px;
}

.card {
  width: 200px;                  /* set an equal width for every card */
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 10px;
  text-align: center;
  background-color: white;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
  /* no margin needed — the container uses gap for spacing */
}

.card img {
  width: 100%;
  height: 140px;                 /* height is required for object-fit to work */
  object-fit: cover;
  border-radius: 4px;
}
css

ไฟล์: flexbox.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Flexbox Cards</title>
  <link rel="stylesheet" href="flexbox.css" />
</head>
<body>
  <h1>Popular Attractions</h1>
  <div class="container">
    <div class="card">
      <img src="https://www.melivecode.com/attractions/1.jpg" alt="Phi Phi Islands" />
      <h2>Phi Phi Islands</h2>
    </div>
    <div class="card">
      <img src="https://www.melivecode.com/attractions/2.jpg" alt="Eiffel Tower" />
      <h2>Eiffel Tower</h2>
    </div>
    <div class="card">
      <img src="https://www.melivecode.com/attractions/3.jpg" alt="Times Square" />
      <h2>Times Square</h2>
    </div>
    <div class="card">
      <img src="https://www.melivecode.com/attractions/4.jpg" alt="Mount Fuji" />
      <h2>Mount Fuji</h2>
    </div>
  </div>
</body>
</html>
html

เปิดไฟล์ flexbox.html ในเบราว์เซอร์ แล้วลองย่อและขยายหน้าต่างเพื่อสังเกตว่าการ์ดจัดเรียงใหม่อย่างไรเมื่อพื้นที่เปลี่ยนไป

Flexbox cards

คุณสมบัติ Flexbox

Propertyคำอธิบาย
display: flexทำให้ element เป็น flex container
flex-wrap: wrapอนุญาตให้ items ขึ้นบรรทัดใหม่
justify-content: centerจัด items กึ่งกลางตามแกนหลัก ซึ่งเป็นแนวนอนในตัวอย่างนี้
gapเพิ่มระยะห่างระหว่าง flex items

หมายเหตุ: สำหรับคำอธิบาย Flexbox อย่างละเอียด ดูได้ที่ CSS-Tricks Flexbox Guide ↗


ส่วนที่ 3: JavaScript กับ Next.js#

3.1 Next.js คืออะไร?#

  • React.js เป็นไลบรารี JavaScript สำหรับสร้างส่วนติดต่อผู้ใช้ โดยแบ่งหน้าเว็บเป็นส่วนย่อยที่เรียกว่า component
  • Next.js เป็นเฟรมเวิร์กที่ต่อยอดจาก React ช่วยจัดโครงสร้างเว็บแอปพลิเคชัน ในส่วนนี้เราจะใช้เป็นพื้นฐานสำหรับทดลองเขียน JavaScript และแสดงผลผ่าน React
  • Node.js เป็นสภาพแวดล้อมสำหรับรัน JavaScript นอกเบราว์เซอร์ ซึ่งเราจะใช้รันเครื่องมือและเซิร์ฟเวอร์ระหว่างพัฒนาโปรเจกต์

3.2 การติดตั้ง Node.js#

ข้อกำหนดเบื้องต้น: ติดตั้ง Node.js (LTS) จาก nodejs.org ↗

บน Linux (Ubuntu) แนะนำให้ติดตั้งผ่าน nvm (Node Version Manager):

# ดาวน์โหลดและติดตั้ง nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh | bash

# โหลด nvm เข้า shell ปัจจุบัน (แทนการเปิด terminal ใหม่)
\. "$HOME/.nvm/nvm.sh"

# ดาวน์โหลดและติดตั้ง Node.js
nvm install 24

# ตรวจสอบเวอร์ชัน Node.js
node -v # ควรแสดง "v24.20.0"

# ตรวจสอบเวอร์ชัน npm
npm -v # ควรแสดง "11.19.0"
bash

3.3 สร้างโปรเจกต์ Next.js#

# เข้าไปที่โฟลเดอร์โปรเจกต์
cd web-basics

# สร้างโปรเจกต์ Next.js ใหม่ (--js บังคับใช้ JavaScript แทน TypeScript)
npx create-next-app@16 03_js_nextjs --js

# ครั้งแรกจะถามให้ติดตั้งแพ็กเกจ ให้พิมพ์ y แล้วกด Enter:
# Need to install the following packages:
# create-next-app@16.3.4
# Ok to proceed? (y) y

# หมายเหตุ: Next.js 16 จะไม่ถามตัวเลือกทีละข้อเหมือนเวอร์ชันก่อน
# แต่จะใช้ค่าเริ่มต้นให้เลย ได้แก่ ESLint, Tailwind CSS, App Router,
# ไม่มีโฟลเดอร์ src/ และ import alias "@/*"

# เข้าไปในโปรเจกต์
cd 03_js_nextjs

# เปิด VS Code ในโฟลเดอร์ปัจจุบัน
code .
bash

เมื่อเปิดโปรเจกต์ใน VS Code ด้วย code . แล้ว ให้เริ่มเซิร์ฟเวอร์สำหรับพัฒนา (development server) ตามขั้นตอนต่อไปนี้ เพื่อเปิดดูหน้าเว็บระหว่างเขียนโค้ด

1. เปิด Terminal ใน VS Code — จากเมนู Terminal → New Terminal (หรือกดคีย์ลัด Ctrl+Shift+`)

เปิด New Terminal จากเมนู Terminal ใน VS Code

2. เลือก Command Prompt (สำหรับ Windows) — หาก Terminal เปิดขึ้นมาเป็น PowerShell ให้กดลูกศร ∨ ข้างปุ่ม + มุมขวาบนของ Terminal แล้วเลือก Command Prompt เพื่อให้คำสั่งทำงานตรงกับตัวอย่างในบทความ

เลือก Command Prompt จากรายการ profile ของ Terminal

3. รัน npm run dev — พิมพ์คำสั่งต่อไปนี้แล้วกด Enter

npm run dev
bash

เมื่อ server พร้อมใช้งานจะแสดงลิงก์ Local: http://localhost:3000 กด Ctrl ค้างแล้วคลิกที่ลิงก์ VS Code จะเปิดเบราว์เซอร์ในตัว (Simple Browser) แสดงหน้าแอปขึ้นมาทันทีโดยไม่ต้องออกจาก VS Code

ผลลัพธ์หลังรัน npm run dev แสดงลิงก์ localhost:3000 และหน้าแอปในเบราว์เซอร์ของ VS Code

3.4 ส่วนเสริม VS Code ที่แนะนำ#

ติดตั้งส่วนเสริม ES7+ React/Redux/React-Native snippets เพื่อใช้คำย่อช่วยสร้างโค้ด React ใน VS Code และลดการพิมพ์โครงสร้างที่ใช้ซ้ำ

3.5 โครงสร้าง React Component#

ในโปรเจกต์ Next.js ที่ใช้ App Router เราจะเขียนหน้าเว็บเป็น React component ภายในโฟลเดอร์ app เริ่มจากแก้ไข app/page.js ซึ่งเป็นหน้าหลัก ให้แสดงข้อความต้อนรับตามตัวอย่าง

ไฟล์: app/page.js

เคล็ดลับ: ใช้คำย่อ rfc จากส่วนเสริม ES7+ React snippets แล้วกด Enter เพื่อสร้างโครง React component จากนั้นปรับโค้ดให้ตรงกับตัวอย่างด้านล่าง

rfc snippet

export default function Page() {
  return (
    <div>
      <div className='box'>
        <h1>Hello World, Next.js</h1>
        <p>Welcome to React!</p>
      </div>
    </div>
  )
}
javascript

Hello World React

แนวคิดสำคัญ

Conceptคำอธิบาย
export defaultส่งออก component หลักของไฟล์เพื่อนำไปใช้งาน
function Component()ประกาศฟังก์ชันที่ทำหน้าที่เป็น React component
return (...)คืนค่า JSX ที่อธิบายส่วนติดต่อผู้ใช้
classNameระบุ CSS class ให้กับองค์ประกอบใน JSX
JSXส่วนขยายไวยากรณ์ของ JavaScript สำหรับเขียนมาร์กอัปที่มีหน้าตาคล้าย HTML

หมายเหตุ: เมื่อเขียน JSX ให้ใช้ className แทนแอตทริบิวต์ class ที่คุ้นเคยจาก HTML เพื่อเชื่อมองค์ประกอบกับ CSS class

3.6 การเพิ่ม CSS#

ไฟล์: app/style.css

.box {
  border: 2px solid brown;
  width: 200px;
  padding: 10px;
  margin: 10px;
  background-color: beige;
}
css

ไฟล์: app/layout.js

import './style.css'

export const metadata = {
  title: 'Next.js Tutorial',
  description: 'Learn JavaScript with Next.js',
}

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}
javascript

React with CSS

พื้นฐาน JavaScript ใน React/Next.js — เมื่อสร้าง component และเพิ่ม CSS ได้แล้ว เราจะเริ่มนำข้อมูลมาแสดงบนหน้าเว็บ ตั้งแต่ตัวแปรไปจนถึงการกรองข้อมูล แต่ละหัวข้อให้สร้างไฟล์ page.js ในโฟลเดอร์ย่อยภายใต้ app/ แล้วเปิด URL ที่ระบุขณะเซิร์ฟเวอร์ยังทำงาน

3.7 ตัวแปร (Variables)#

สร้างไฟล์ app/01_var/page.js — เข้าถึงที่ http://localhost:3000/01_var ↗

export default function VarPage() {
  const name = "Karn";
  let age = 25;
  const isStudent = true;

  return (
    <div>
      <h1>Variables</h1>
      <p>Name: {name}</p>
      <p>Age: {age}</p>
      <p>Student: {isStudent ? "Yes" : "No"}</p>
    </div>
  );
}
javascript

Variables

Keywordการใช้งาน
varรูปแบบเดิมที่มีขอบเขตต่างจาก let และ const; ในตัวอย่างนี้ให้เลือกใช้สองแบบหลัง
letใช้เมื่อต้องกำหนดค่าใหม่ให้ตัวแปรภายหลัง
constใช้เมื่อไม่ต้องกำหนดค่าใหม่ให้ตัวแปร แต่ยังแก้ไขสมาชิกของอาร์เรย์หรือคุณสมบัติของออบเจกต์ได้

3.8 อาร์เรย์ (Arrays)#

สร้างไฟล์ app/02_array/page.js — เข้าถึงที่ http://localhost:3000/02_array ↗

อาร์เรย์ใช้เก็บข้อมูลหลายรายการไว้ด้วยกัน ในตัวอย่างนี้เราใช้เมธอด map() แปลงสมาชิกแต่ละตัวเป็น JSX element แล้วนำรายการที่ได้มาแสดงบนหน้าเว็บ:

Rendering a list with map()

export default function ArrayPage() {
  const fruits = ["Orange", "Banana", "Mango", "Strawberry"];

  return (
    <div>
      <h1>Arrays</h1>
      <ul>
        {fruits.map((fruit, index) => (
          <li key={index}>{fruit}</li>
        ))}
      </ul>
    </div>
  );
}
javascript

Arrays

หมายเหตุ: แต่ละรายการที่สร้างด้วย map() ควรมี prop key ที่คงที่และไม่ซ้ำกันในกลุ่ม เพื่อให้ React ระบุรายการเดิมได้เมื่อข้อมูลเปลี่ยนลำดับ มีการเพิ่ม หรือลบรายการ

3.9 ออบเจกต์ (Objects)#

สร้างไฟล์ app/03_object/page.js — เข้าถึงที่ http://localhost:3000/03_object ↗

export default function ObjectPage() {
  const user = {
    name: "Karn Yongsiriwit",
    role: "Developer",
    country: "Thailand"
  };

  return (
    <div>
      <h1>Objects</h1>
      <p>Name: {user.name}</p>
      <p>Role: {user.role}</p>
      <p>Country: {user.country}</p>
    </div>
  );
}
javascript

Objects

ออบเจกต์ใช้เก็บข้อมูลที่เกี่ยวข้องกันเป็นคู่ชื่อและค่า (key-value) เช่น ชื่อ บทบาท และประเทศของผู้ใช้ เราอ่านค่าของแต่ละคุณสมบัติได้ด้วย dot notation เช่น user.name แล้วใส่ไว้ใน {} เพื่อแสดงใน JSX

3.10 อาร์เรย์ของออบเจกต์ (Array of Objects)#

สร้างไฟล์ app/04_array_objects/page.js — เข้าถึงที่ http://localhost:3000/04_array_objects ↗

export default function ArrayObjectsPage() {
  const attractions = [
    { id: 1, name: "Phi Phi Islands", country: "Thailand" },
    { id: 2, name: "Eiffel Tower", country: "France" },
    { id: 3, name: "Times Square", country: "USA" },
    { id: 4, name: "Mount Fuji", country: "Japan" }
  ];

  return (
    <div>
      <h1>Array of Objects</h1>
      {attractions.map((attraction) => (
        <div key={attraction.id} style={{ border: "1px solid #ccc", margin: "10px", padding: "10px" }}>
          <h2>{attraction.name}</h2>
          <p>Country: {attraction.country}</p>
        </div>
      ))}
    </div>
  );
}
javascript

Array of Objects

เมื่อนำอาร์เรย์และออบเจกต์มาใช้ร่วมกัน เราจะเก็บข้อมูลหลายรายการที่แต่ละรายการมีหลายคุณสมบัติได้ ตัวอย่างนี้เก็บสถานที่ท่องเที่ยวเป็นอาร์เรย์ของออบเจกต์ แล้วใช้ map() สร้างกล่องแสดงชื่อและประเทศของแต่ละสถานที่ โดยใช้ id เป็น key

3.11 ฟังก์ชัน (Functions)#

สร้างไฟล์ app/05_function/page.js — เข้าถึงที่ http://localhost:3000/05_function ↗

export default function FunctionPage() {
  // Function Declaration — add two numbers
  function add(a, b) {
    return a + b;
  }

  // Function Expression — assign a function to a variable
  const square = function (n) {
    return n * n;
  };

  // Arrow Function — multiply two numbers
  const multiply = (a, b) => {
    return a * b;
  };

  // Arrow Function (implicit return) — a short one-liner
  const subtract = (a, b) => a - b;

  // check whether the person is an adult
  const isAdult = (age) => {
    return age >= 18;
  };

  // build a greeting message
  const greet = (name, timeOfDay) => {
    return `Good ${timeOfDay}, ${name}!`;
  };

  return (
    <div>
      <h1>Functions</h1>
      <h2>Basic Calculations</h2>
      <p>5 + 3 = {add(5, 3)}</p>
      <p>7 × 7 = {square(7)}</p>
      <p>4 × 6 = {multiply(4, 6)}</p>
      <p>10 - 4 = {subtract(10, 4)}</p>

      <h2>Conditional Logic</h2>
      <p>Age 20 is adult: {isAdult(20) ? "Yes" : "No"}</p>
      <p>Age 15 is adult: {isAdult(15) ? "Yes" : "No"}</p>

      <h2>Template Strings</h2>
      <p>{greet("Karn", "morning")}</p>
      <p>{greet("Somchai", "evening")}</p>
    </div>
  );
}
javascript

Functions

รูปแบบฟังก์ชัน

TypeSyntaxUse Case
Function Declarationfunction name() {}ประกาศฟังก์ชันที่เรียกใช้ก่อนบรรทัดประกาศได้ภายในขอบเขตเดียวกัน
Function Expressionconst name = function() {}เก็บฟังก์ชันไว้ในตัวแปรเพื่อเรียกใช้ภายหลัง
Arrow Functionconst name = () => {}เขียนฟังก์ชันด้วยรูปแบบกระชับ เช่น ฟังก์ชันที่ส่งให้ map()
Arrow (Implicit Return)const name = () => valueคืนค่าจากนิพจน์โดยไม่ต้องเขียนวงเล็บปีกกาหรือ return

การตั้งชื่อฟังก์ชัน

ConventionRuleตัวอย่างที่แนะนำตัวอย่างที่ไม่ตรงแนวทาง
camelCaseขึ้นต้นคำแรกด้วยตัวพิมพ์เล็ก และขึ้นต้นคำถัดไปด้วยตัวพิมพ์ใหญ่getUserData, calculateTotal, isValidGetUserData, get_user_data
Verb-firstเริ่มด้วยคำกริยาที่อธิบายการกระทำfetchUser, saveData, deleteItemuser, data, item
Booleansใช้คำนำหน้า is, has, can, shouldisLoggedIn, hasPermission, canEditlogged, permission, editable

ตัวอย่างเพิ่มเติม: ฟังก์ชันกับ map()

เราสามารถแยกงานที่ใช้ซ้ำออกเป็นฟังก์ชัน แล้วเรียกใช้ระหว่างแสดงรายการด้วย map() ได้ ตัวอย่างนี้แยกการคำนวณส่วนลดและการจัดรูปแบบราคาออกจากส่วนที่สร้างหน้าตาของรายการสินค้า:

export default function FunctionMapPage() {
  const products = [
    { id: 1, name: "Laptop", price: 25000 },
    { id: 2, name: "Mouse", price: 500 },
    { id: 3, name: "Keyboard", price: 1500 }
  ];

  // calculate the price after a 10% discount
  const calculateDiscount = (price) => {
    return price * 0.9;
  };

  // format as currency
  const formatCurrency = (amount) => {
    return `฿${amount.toLocaleString()}`;
  };

  return (
    <div>
      <h1>Functions with Arrays</h1>
      <h2>Product Prices (after 10% discount)</h2>
      {products.map((product) => (
        <div key={product.id} style={{ border: "1px solid #ccc", margin: "10px", padding: "10px" }}>
          <h3>{product.name}</h3>
          <p>Original price: {formatCurrency(product.price)}</p>
          <p>Discounted price: {formatCurrency(calculateDiscount(product.price))}</p>
        </div>
      ))}
    </div>
  );
}
javascript

Functions with Arrays

เคล็ดลับ: ลองแยกงานแต่ละอย่างเป็นฟังก์ชันเล็ก ๆ ที่มีหน้าที่ชัดเจน เช่น คำนวณราคาหรือจัดรูปแบบข้อความ วิธีนี้ช่วยให้นำโค้ดกลับมาใช้ซ้ำและอ่าน component ได้ง่ายขึ้น

3.12 การแสดงผลตามเงื่อนไข (Conditional Rendering)#

สร้างไฟล์ app/06_condition/page.js — เข้าถึงที่ http://localhost:3000/06_condition ↗

นอกจากแสดงข้อมูลแล้ว เรายังเลือกเนื้อหาตามเงื่อนไขได้ ตัวอย่างนี้ใช้ && เพื่อแสดงข้อความเมื่อเงื่อนไขเป็นจริง และใช้ ternary ? : เพื่อเลือกแสดงผลอย่างใดอย่างหนึ่งจากสองกรณี

export default function ConditionPage() {
  const isLoggedIn = true;
  const score = 75;

  return (
    <div>
      <h1>Conditional Rendering</h1>

      {/* && — render only when the condition is true */}
      {isLoggedIn && <p>Welcome back!</p>}

      {/* ternary — choose between two cases */}
      <p>Status: {isLoggedIn ? "Online" : "Offline"}</p>
      <p>Result: {score >= 50 ? "Pass" : "Fail"}</p>
    </div>
  );
}
javascript

Conditional Rendering

PatternSyntaxใช้เมื่อ
Logical AND{cond && <p>...</p>}แสดง element เฉพาะตอนเงื่อนไขเป็นจริง
Ternary{cond ? A : B}เลือกแสดงระหว่างสองกรณี

หมายเหตุ: ภายใน {} ของ JSX ต้องเป็นนิพจน์ จึงเขียนคำสั่ง if/else ลงไปโดยตรงไม่ได้ ให้ใช้ && หรือ ternary หรือใช้ if/else เตรียมค่าก่อนถึง return

3.13 การกรองและค้นหาข้อมูล (filter และ find)#

สร้างไฟล์ app/07_filter_find/page.js — เข้าถึงที่ http://localhost:3000/07_filter_find ↗

เมื่อต้องการแสดงข้อมูลเฉพาะบางรายการ ให้ใช้ filter() เพื่อสร้าง อาร์เรย์ใหม่ ที่มีเฉพาะรายการตรงเงื่อนไข แล้วใช้ map() แสดงผลต่อได้ ส่วน find() ใช้ค้นหา รายการแรก ที่ตรงเงื่อนไข โดยจะได้ undefined หากไม่พบรายการนั้น

export default function FilterFindPage() {
  const products = [
    { id: 1, name: "Laptop", price: 25000 },
    { id: 2, name: "Mouse", price: 500 },
    { id: 3, name: "Keyboard", price: 1500 },
    { id: 4, name: "Monitor", price: 6000 }
  ];

  // filter — keep only products priced at 2000 or less
  const cheapProducts = products.filter((product) => product.price <= 2000);

  // find — get the first product whose id equals 3
  const selected = products.find((product) => product.id === 3);

  return (
    <div>
      <h1>Filter and Find</h1>

      <h2>Products under 2,000</h2>
      <ul>
        {cheapProducts.map((product) => (
          <li key={product.id}>{product.name} - {product.price}</li>
        ))}
      </ul>

      <h2>Selected Product</h2>
      <p>{selected.name} - {selected.price}</p>
    </div>
  );
}
javascript

Filter and Find

Methodคืนค่าใช้เมื่อ
filter()อาร์เรย์ใหม่ (อาจว่างหรือมีหนึ่งรายการขึ้นไป)ต้องการทุกรายการที่ตรงเงื่อนไข
find()รายการเดียว (หรือ undefined)ต้องการรายการแรกที่ตรงเงื่อนไข

เคล็ดลับ: ใช้ filter() กรองรายการที่ต้องการก่อน แล้วใช้ map() แปลงเป็น JSX สำหรับแสดงผล ส่วนค่าที่ได้จาก find() ควรตรวจสอบว่าพบข้อมูลก่อนอ่านคุณสมบัติ เช่น selected.name

3.14 สารบัญ#

เมื่อทำครบทุกหัวข้อแล้ว ให้แก้ไข app/page.js เป็นหน้าสารบัญ โดยใช้ Link สร้างลิงก์ไปยังบทเรียนแต่ละหน้า เพื่อกลับมาทบทวนได้สะดวก:

import Link from 'next/link'

export default function Home() {
  return (
    <div style={{ padding: '20px' }}>
      <h1>JavaScript Lessons</h1>
      <ul>
        <li><Link href="/01_var">Variables</Link></li>
        <li><Link href="/02_array">Arrays</Link></li>
        <li><Link href="/03_object">Objects</Link></li>
        <li><Link href="/04_array_objects">Array of Objects</Link></li>
        <li><Link href="/05_function">Functions</Link></li>
        <li><Link href="/06_condition">Conditional Rendering</Link></li>
        <li><Link href="/07_filter_find">Filter and Find</Link></li>
      </ul>
    </div>
  )
}
javascript

Table of contents


สรุป#

ส่วนที่ 1: HTML#

  • HTML ใช้กำหนดโครงสร้างและความหมายของเนื้อหาบนหน้าเว็บ
  • องค์ประกอบพื้นฐาน ได้แก่ หัวข้อ ย่อหน้า ลิงก์ รูปภาพ รายการ ตาราง และแบบฟอร์ม
  • เลือกแท็กให้ตรงกับความหมายของเนื้อหา เพื่อช่วยให้ผู้ใช้และเครื่องมือช่วยการเข้าถึงเข้าใจหน้าเว็บได้ดีขึ้น

ส่วนที่ 2: CSS#

  • CSS ใช้ตกแต่งและจัดวางองค์ประกอบบนหน้าเว็บ
  • เพิ่มสไตล์ได้ 3 วิธี คือ inline, internal และ external
  • แยก CSS เป็นไฟล์ภายนอกเพื่อจัดการสไตล์และใช้ร่วมกันหลายหน้าได้สะดวก
  • ใช้ Flexbox จัดเรียงองค์ประกอบและให้รายการขึ้นบรรทัดใหม่ตามพื้นที่ที่มี

ส่วนที่ 3: JavaScript กับ Next.js#

  • ใช้ React component บน Next.js เพื่อสร้างหน้าเว็บและแสดงข้อมูลด้วย JSX
  • ประกาศตัวแปรด้วย const เมื่อไม่ต้องกำหนดค่าใหม่ และใช้ let เมื่อต้องกำหนดค่าใหม่ภายหลัง
  • ใช้อาร์เรย์เก็บข้อมูลหลายรายการ และใช้ออบเจกต์เก็บคุณสมบัติเป็นคู่ key-value
  • รวมทั้งสองแบบเป็นอาร์เรย์ของออบเจกต์ เมื่อแต่ละรายการมีหลายคุณสมบัติ
  • แยกงานที่ใช้ซ้ำเป็นฟังก์ชัน ทั้งแบบปกติและ arrow function
  • ใช้ map() สร้างรายการ, filter() กรองข้อมูล, find() ค้นหารายการ และ conditional rendering เลือกเนื้อหาตามเงื่อนไข

บทความถัดไป: เราจะต่อยอดพื้นฐานเหล่านี้ด้วย React และ Next.js ให้ลึกขึ้น ทั้งการส่งข้อมูลผ่าน props การจัดการ state และ hooks การดึงข้อมูลจาก API และการกำหนดเส้นทางหน้าเว็บ (routing)

แหล่งข้อมูลเพิ่มเติม#

ปูพื้นฐานการเขียนเว็บด้วย HTML, CSS และ JavaScript
Author กานต์ ยงศิริวิทย์ / Karn Yongsiriwit
Published at September 8, 2026

Loading comments...

Comments 0