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

Scoped Styles

ใน React คุณ scope style ให้กับ component โดยตั้งชื่อไฟล์เป็น Button.module.css แล้ว import มา — bundler จะ rewrite ชื่อ class ให้เป็น hash ที่ unique ตอน build ใน Astro คุณเขียน CSS ธรรมดาใน <style> block ในไฟล์ .astro เดียวกัน compiler จะเพิ่ม data attribute hash ที่ unique ให้ทุก selector และทุก HTML element ใน component นั้น ให้ผลลัพธ์เดียวกันโดยไม่ต้องตั้งค่าใดๆ

React
// Button.tsx + Button.module.css
// Button.module.css
.button { background: #6366f1; color: #fff; border-radius: 6px; padding: .5rem 1rem; border: none; cursor: pointer; }
.button:hover { background: #4f46e5; }
// Button.tsx
import styles from './Button.module.css';
export default function Button({ label }: { label: string }) {
return <button className={styles.button}>{label}</button>;
}
Astro
---
// Button.astro
const { label } = Astro.props;
---
<button class="button">{label}</button>
<style>
.button { background: #6366f1; color: #fff; border-radius: 6px; padding: .5rem 1rem; border: none; cursor: pointer; }
.button:hover { background: #4f46e5; }
</style>

สิ่งที่ Astro compiler สร้างขึ้นเบื้องหลัง:

<!-- compiled output — คุณไม่ต้องเขียนสิ่งนี้ด้วยตัวเอง -->
<button class="button astro-aBcD1234">Click me</button>
<style>
.button.astro-aBcD1234 { background: #6366f1; ... }
</style>

hash suffix (astro-aBcD1234) ถูก inject อัตโนมัติ rule .button ใน component อื่นจะได้รับ hash ที่แตกต่างกัน ดังนั้น style จึงไม่ชนกัน

<style> block รับ CSS มาตรฐาน — custom properties, media queries, pseudo-selectors, nesting, @keyframes ทุกอย่างที่ browser target รองรับ ไม่มี CSS-in-JS API ให้เรียนรู้เพิ่มเติม

React
// Card.module.css
.card { border: 1px solid #e2e8f0; border-radius: 8px; padding: 1rem; transition: transform .15s; }
.card:hover { transform: translateY(-2px); }
@media (max-width: 480px) { .card { padding: .75rem; } }
// Card.tsx
import styles from './Card.module.css';
export default function Card({ title }: { title: string }) {
return <div className={styles.card}><h2>{title}</h2></div>;
}
Astro
---
// Card.astro
const { title } = Astro.props;
---
<div class="card"><h2>{title}</h2></div>
<style>
.card { border: 1px solid #e2e8f0; border-radius: 8px; padding: 1rem; transition: transform .15s; }
.card:hover { transform: translateY(-2px); }
@media (max-width: 480px) { .card { padding: .75rem; } }
</style>
Astro
---
const items = ["Dashboard", "Projects", "Settings"];
---
<html lang="en">
  <head><meta charset="utf-8" /><title>Scoped styles</title></head>
  <body>
    <nav>
      {items.map(item => (
        <a href="#" class="nav-link">{item}</a>
      ))}
    </nav>
    <main>
      <div class="card">
        <h1>Scoped Styles Demo</h1>
        <p>The <code>.card</code> and <code>.nav-link</code> styles live in this file and are scoped here by the Astro compiler — they cannot bleed into other components.</p>
      </div>
    </main>
  </body>
</html>

<style>
  body { font-family: sans-serif; margin: 0; background: #f8fafc; }
  nav { background: #1e293b; padding: .75rem 1.5rem; display: flex; gap: 1rem; }
  .nav-link { color: #94a3b8; text-decoration: none; font-size: .875rem; }
  .nav-link:hover { color: #fff; }
  main { padding: 2rem; }
  .card { background: #fff; border: 1px solid #e2e8f0; border-radius: 10px; padding: 1.5rem; max-width: 480px; }
  .card h1 { font-size: 1.25rem; margin: 0 0 .75rem; color: #1e293b; }
  .card p { color: #64748b; line-height: 1.6; margin: 0; }
  code { background: #f1f5f9; padding: .1em .35em; border-radius: 4px; font-size: .875em; }
</style>
Astro ป้องกัน style ใน component หนึ่งไม่ให้กระทบ component อื่นได้อย่างไร?
ใช้ CSS feature ใดได้บ้างใน `<style>` block ของ Astro?
ใน Astro คุณเขียน `class="card"` แล้ว HTML attribute ที่ compile แล้วหน้าตาเป็นอย่างไร?
คุณต้องการ hover transition บน card ใน Astro ควรเขียนที่ไหน?