[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"academy-blogs-th-1-1-all-tailwind-css-component-system-apply-directive-ep7-all--*":3,"academy-blog-translations-07n2giqabaejy8h":74},{"data":4,"page":73,"perPage":73,"totalItems":73,"totalPages":73},[5],{"alt":6,"collectionId":7,"collectionName":8,"content":9,"cover_image":10,"cover_image_path":11,"created":12,"created_by":13,"expand":14,"id":67,"keywords":68,"locale":44,"published_at":69,"scheduled_at":13,"school_blog":65,"short_description":70,"slug":71,"status":63,"title":6,"updated":72,"updated_by":13,"views":66},"EP 7: หยุดเขียนซ้ำ! สร้าง Component ด้วย @apply และ Custom CSS","sclblg987654321","school_blog_translations","\u003Cp>หลายคนที่เริ่มใช้ Tailwind CSS มักจะเจอปัญหาเดียวกัน คือ HTML ที่ดูยาวเยิ่นฟ่าเฟื่อง และการต้องเขียนคลาสเดิมๆ ซ้ำไปซ้ำมา เช่น เขียนปุ่มสีน้ำเงินแล้วต้องใส่ \u003Ccode>px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors\u003C\u002Fcode> ทุกครั้ง\u003C\u002Fp>\u003Cp>แต่คุณรู้ไหมว่า Tailwind CSS มีเครื่องมือที่ทรงพลังในการแก้ปัญหานี้? วันนี้เราจะมาเรียนรู้การใช้ \u003Ccode>@apply\u003C\u002Fcode> และเทคนิคการสร้าง Component ที่จะทำให้คุณเขียนโค้ดได้เร็วขึ้น บำรุงรักษาง่ายขึ้น และยังคงความยืดหยุ่นของ Tailwind CSS ไว้ได้\u003C\u002Fp>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>ทำความเข้าใจ @apply Directive\u003C\u002Fh2>\u003Cp>\u003Ccode>@apply\u003C\u002Fcode> เป็นเครื่องมือพิเศษของ Tailwind CSS ที่ให้เราเอาคลาส utility หลายๆ ตัวมารวมเป็นคลาสเดียว ทำให้เราสามารถสร้าง Component ที่ใช้ซ้ำได้\u003C\u002Fp>\u003Ch3>หลักการพื้นฐานของ @apply\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* สร้างปุ่มพื้นฐานด้วย @apply *\u002F\n.btn {\n  @apply px-6 py-3 font-semibold rounded-lg transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2;\n}\n\n.btn-primary {\n  @apply bg-blue-500 text-white hover:bg-blue-600 focus:ring-blue-500;\n}\n\n.btn-secondary {\n  @apply bg-gray-200 text-gray-800 hover:bg-gray-300 focus:ring-gray-500;\n}\n\n.btn-danger {\n  @apply bg-red-500 text-white hover:bg-red-600 focus:ring-red-500;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-html\">&lt;!-- ใช้งานในHTML --&gt;\n&lt;button class=\"btn btn-primary\"&gt;ปุ่มหลัก&lt;\u002Fbutton&gt;\n&lt;button class=\"btn btn-secondary\"&gt;ปุ่มรอง&lt;\u002Fbutton&gt;\n&lt;button class=\"btn btn-danger\"&gt;ปุ่มลบ&lt;\u002Fbutton&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>ข้อดีของการใช้ @apply\u003C\u002Fh3>\u003Cul>\u003Cli>\u003Cstrong>HTML สะอาดขึ้น:\u003C\u002Fstrong> ลดความยาวของ class attributes\u003C\u002Fli>\u003Cli>\u003Cstrong>บำรุงรักษาง่าย:\u003C\u002Fstrong> แก้ไขที่เดียวได้ผลทุกที่\u003C\u002Fli>\u003Cli>\u003Cstrong>สร้าง Design System:\u003C\u002Fstrong> มีมาตรฐานที่ชัดเจน\u003C\u002Fli>\u003Cli>\u003Cstrong>ยังคงความยืดหยุ่น:\u003C\u002Fstrong> สามารถใส่ utility classes เพิ่มได้\u003C\u002Fli>\u003C\u002Ful>\u003Ch3>เมื่อไหร่ควรใช้ @apply\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* ✅ ดี - Pattern ที่ใช้ซ้ำบ่อย *\u002F\n.card {\n  @apply bg-white rounded-lg shadow-md p-6 border border-gray-200;\n}\n\n.input-field {\n  @apply w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500;\n}\n\n\u002F* ❌ ไม่ดี - ใช้แค่ที่เดียว *\u002F\n.unique-element {\n  @apply text-red-500 font-bold;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>การสร้าง Component System แบบมืออาชีพ\u003C\u002Fh2>\u003Ch3>Button Components\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* Base Button *\u002F\n.btn {\n  @apply inline-flex items-center justify-center px-4 py-2 font-medium rounded-md transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed;\n}\n\n\u002F* Button Sizes *\u002F\n.btn-sm {\n  @apply px-3 py-1.5 text-sm;\n}\n\n.btn-md {\n  @apply px-4 py-2 text-base;\n}\n\n.btn-lg {\n  @apply px-6 py-3 text-lg;\n}\n\n\u002F* Button Variants *\u002F\n.btn-solid {\n  @apply shadow-sm;\n}\n\n.btn-outline {\n  @apply border-2 bg-transparent;\n}\n\n\u002F* Button Colors *\u002F\n.btn-blue {\n  @apply bg-blue-500 text-white hover:bg-blue-600 focus:ring-blue-500;\n}\n\n.btn-blue.btn-outline {\n  @apply border-blue-500 text-blue-500 hover:bg-blue-500 hover:text-white;\n}\n\n.btn-green {\n  @apply bg-green-500 text-white hover:bg-green-600 focus:ring-green-500;\n}\n\n.btn-green.btn-outline {\n  @apply border-green-500 text-green-500 hover:bg-green-500 hover:text-white;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-html\">&lt;!-- การใช้งาน Button System --&gt;\n&lt;div class=\"space-y-4\"&gt;\n  &lt;!-- ขนาดต่างๆ --&gt;\n  &lt;div class=\"space-x-2\"&gt;\n    &lt;button class=\"btn btn-sm btn-solid btn-blue\"&gt;เล็ก&lt;\u002Fbutton&gt;\n    &lt;button class=\"btn btn-md btn-solid btn-blue\"&gt;ปกติ&lt;\u002Fbutton&gt;\n    &lt;button class=\"btn btn-lg btn-solid btn-blue\"&gt;ใหญ่&lt;\u002Fbutton&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;!-- รูปแบบต่างๆ --&gt;\n  &lt;div class=\"space-x-2\"&gt;\n    &lt;button class=\"btn btn-md btn-solid btn-blue\"&gt;Solid&lt;\u002Fbutton&gt;\n    &lt;button class=\"btn btn-md btn-outline btn-blue\"&gt;Outline&lt;\u002Fbutton&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;!-- สีต่างๆ --&gt;\n  &lt;div class=\"space-x-2\"&gt;\n    &lt;button class=\"btn btn-md btn-solid btn-blue\"&gt;น้ำเงิน&lt;\u002Fbutton&gt;\n    &lt;button class=\"btn btn-md btn-solid btn-green\"&gt;เขียว&lt;\u002Fbutton&gt;\n  &lt;\u002Fdiv&gt;\n&lt;\u002Fdiv&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>Card Components\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* Base Card *\u002F\n.card {\n  @apply bg-white rounded-lg shadow-md overflow-hidden;\n}\n\n.card-hover {\n  @apply transition-all duration-300 hover:shadow-lg hover:-translate-y-1;\n}\n\n.card-bordered {\n  @apply border border-gray-200;\n}\n\n\u002F* Card Parts *\u002F\n.card-header {\n  @apply px-6 py-4 border-b border-gray-200 bg-gray-50;\n}\n\n.card-body {\n  @apply px-6 py-4;\n}\n\n.card-footer {\n  @apply px-6 py-4 border-t border-gray-200 bg-gray-50;\n}\n\n.card-image {\n  @apply w-full h-48 object-cover;\n}\n\n.card-title {\n  @apply text-xl font-semibold text-gray-800 mb-2;\n}\n\n.card-text {\n  @apply text-gray-600 leading-relaxed;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-html\">&lt;!-- การใช้งาน Card System --&gt;\n&lt;div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\"&gt;\n  &lt;!-- Card แบบมี Header --&gt;\n  &lt;div class=\"card card-hover card-bordered\"&gt;\n    &lt;div class=\"card-header\"&gt;\n      &lt;h3 class=\"card-title\"&gt;หัวข้อบทความ&lt;\u002Fh3&gt;\n    &lt;\u002Fdiv&gt;\n    &lt;div class=\"card-body\"&gt;\n      &lt;p class=\"card-text\"&gt;\n        เนื้อหาของบทความที่น่าสนใจและมีประโยชน์สำหรับผู้อ่าน\n      &lt;\u002Fp&gt;\n    &lt;\u002Fdiv&gt;\n    &lt;div class=\"card-footer\"&gt;\n      &lt;button class=\"btn btn-sm btn-solid btn-blue\"&gt;อ่านต่อ&lt;\u002Fbutton&gt;\n    &lt;\u002Fdiv&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;!-- Card แบบมีรูปภาพ --&gt;\n  &lt;div class=\"card card-hover\"&gt;\n    &lt;img class=\"card-image\" src=\"https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1518837695005-2083093ee35b?w=400\" alt=\"Card image\" loading=\"lazy\"&gt;\n    &lt;div class=\"card-body\"&gt;\n      &lt;h3 class=\"card-title\"&gt;ชื่อสินค้า&lt;\u002Fh3&gt;\n      &lt;p class=\"card-text\"&gt;รายละเอียดสินค้าที่น่าสนใจ&lt;\u002Fp&gt;\n      &lt;div class=\"mt-4 flex items-center justify-between\"&gt;\n        &lt;span class=\"text-2xl font-bold text-blue-600\"&gt;฿1,999&lt;\u002Fspan&gt;\n        &lt;button class=\"btn btn-sm btn-solid btn-green\"&gt;ซื้อเลย&lt;\u002Fbutton&gt;\n      &lt;\u002Fdiv&gt;\n    &lt;\u002Fdiv&gt;\n  &lt;\u002Fdiv&gt;\n&lt;\u002Fdiv&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>Form Components\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* Form Elements *\u002F\n.form-group {\n  @apply mb-4;\n}\n\n.form-label {\n  @apply block text-sm font-medium text-gray-700 mb-2;\n}\n\n.form-input {\n  @apply w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors;\n}\n\n.form-input.error {\n  @apply border-red-300 focus:ring-red-500 focus:border-red-500;\n}\n\n.form-textarea {\n  @apply form-input resize-vertical min-h-[100px];\n}\n\n.form-select {\n  @apply form-input appearance-none bg-no-repeat bg-right pr-10;\n  background-image: url(\"data:image\u002Fsvg+xml,%3csvg xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'\u002F%3e%3c\u002Fsvg%3e\");\n}\n\n.form-error {\n  @apply text-sm text-red-600 mt-1;\n}\n\n.form-help {\n  @apply text-sm text-gray-500 mt-1;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cpre>\u003Ccode class=\"language-html\">&lt;!-- การใช้งาน Form System --&gt;\n&lt;form class=\"max-w-lg mx-auto space-y-6\"&gt;\n  &lt;div class=\"form-group\"&gt;\n    &lt;label class=\"form-label\" for=\"name\"&gt;ชื่อ-นามสกุล&lt;\u002Flabel&gt;\n    &lt;input class=\"form-input\" type=\"text\" id=\"name\" placeholder=\"กรอกชื่อของคุณ\"&gt;\n    &lt;p class=\"form-help\"&gt;กรุณากรอกชื่อจริงของคุณ&lt;\u002Fp&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;div class=\"form-group\"&gt;\n    &lt;label class=\"form-label\" for=\"email\"&gt;อีเมล&lt;\u002Flabel&gt;\n    &lt;input class=\"form-input error\" type=\"email\" id=\"email\" placeholder=\"your@email.com\"&gt;\n    &lt;p class=\"form-error\"&gt;กรุณากรอกอีเมลที่ถูกต้อง&lt;\u002Fp&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;div class=\"form-group\"&gt;\n    &lt;label class=\"form-label\" for=\"country\"&gt;ประเทศ&lt;\u002Flabel&gt;\n    &lt;select class=\"form-select\" id=\"country\"&gt;\n      &lt;option&gt;เลือกประเทศ&lt;\u002Foption&gt;\n      &lt;option&gt;ไทย&lt;\u002Foption&gt;\n      &lt;option&gt;สิงคโปร์&lt;\u002Foption&gt;\n      &lt;option&gt;มาเลเซีย&lt;\u002Foption&gt;\n    &lt;\u002Fselect&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;div class=\"form-group\"&gt;\n    &lt;label class=\"form-label\" for=\"message\"&gt;ข้อความ&lt;\u002Flabel&gt;\n    &lt;textarea class=\"form-textarea\" id=\"message\" placeholder=\"เขียนข้อความของคุณ...\"&gt;&lt;\u002Ftextarea&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;button class=\"btn btn-lg btn-solid btn-blue w-full\"&gt;ส่งข้อมูล&lt;\u002Fbutton&gt;\n&lt;\u002Fform&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>การจัดการ Custom Utilities และ Components\u003C\u002Fh2>\u003Ch3>การใช้ @layer อย่างถูกต้อง\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">@layer base {\n  \u002F* Reset และ Base Styles *\u002F\n  html {\n    @apply scroll-smooth;\n  }\n  \n  body {\n    @apply font-sans text-gray-900 leading-relaxed;\n  }\n}\n\n@layer components {\n  \u002F* Component Classes *\u002F\n  .btn {\n    @apply px-4 py-2 font-medium rounded-lg transition-all duration-200;\n  }\n  \n  .card {\n    @apply bg-white rounded-lg shadow-md overflow-hidden;\n  }\n  \n  .glass-effect {\n    @apply backdrop-blur-sm bg-white\u002F80 border border-white\u002F20;\n  }\n}\n\n@layer utilities {\n  \u002F* Custom Utilities *\u002F\n  .scroll-snap-x {\n    scroll-snap-type: x mandatory;\n  }\n  \n  .scroll-snap-start {\n    scroll-snap-align: start;\n  }\n  \n  .text-shadow {\n    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>การสร้าง Responsive Components\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* Responsive Card *\u002F\n.card-responsive {\n  @apply bg-white rounded-lg shadow-md overflow-hidden;\n  @apply flex flex-col md:flex-row;\n}\n\n.card-responsive .card-image {\n  @apply w-full md:w-1\u002F3 h-48 md:h-auto object-cover;\n}\n\n.card-responsive .card-content {\n  @apply p-6 flex-1;\n}\n\n.card-responsive .card-title {\n  @apply text-xl font-semibold mb-2 md:text-2xl;\n}\n\n.card-responsive .card-text {\n  @apply text-gray-600 text-sm md:text-base;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>Best Practices สำหรับ Component Development\u003C\u002Fh2>\u003Ch3>1. การตั้งชื่อ Component\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* ✅ ดี - ชื่อที่สื่อความหมาย *\u002F\n.btn-primary { }\n.card-product { }\n.form-input-error { }\n.navbar-mobile { }\n\n\u002F* ❌ ไม่ดี - ชื่อที่คลุมเครือ *\u002F\n.blue-button { }\n.box1 { }\n.input2 { }\n.nav { }\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>2. การจัดระเบียบโครงสร้าง\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* จัดเรียงตามลำดับความสำคัญ *\u002F\n\n\u002F* 1. Base Components *\u002F\n.btn { }\n.card { }\n.form-input { }\n\n\u002F* 2. Component Variants *\u002F\n.btn-primary { }\n.btn-secondary { }\n.card-hover { }\n.card-bordered { }\n\n\u002F* 3. Component Modifiers *\u002F\n.btn-sm { }\n.btn-lg { }\n\n\u002F* 4. State Classes *\u002F\n.btn:disabled { }\n.form-input.error { }\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>3. Performance Tips\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* ✅ ดี - ใช้ @apply เฉพาะที่จำเป็น *\u002F\n.frequently-used-button {\n  @apply px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors;\n}\n\n\u002F* ❌ ไม่ดี - ใช้ @apply กับทุกอย่าง *\u002F\n.one-time-use {\n  @apply text-red-500 font-bold; \u002F* ควรใช้ utility classes ตรงๆ *\u002F\n}\n\n\u002F* ✅ ดี - Combine กับ utility classes *\u002F\n.special-card {\n  @apply card;\n  \u002F* เพิ่ม utility classes ตามต้องการ *\u002F\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>Common Pitfalls และวิธีแก้ไข\u003C\u002Fh2>\u003Ch3>1. การใช้ @apply กับ Pseudo-classes ผิด\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* ❌ ไม่ทำงาน *\u002F\n.btn {\n  @apply px-4 py-2 bg-blue-500:hover;\n}\n\n\u002F* ✅ ถูกต้อง *\u002F\n.btn {\n  @apply px-4 py-2 bg-blue-500 hover:bg-blue-600;\n}\n\n\u002F* ✅ หรือแยกออกมา *\u002F\n.btn {\n  @apply px-4 py-2 bg-blue-500;\n}\n\n.btn:hover {\n  @apply bg-blue-600;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>2. การใช้ !important ผิด\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* ❌ ไม่ดี *\u002F\n.btn {\n  @apply px-4 py-2 !bg-blue-500;\n}\n\n\u002F* ✅ ดี - ใช้ specificity *\u002F\n.btn.btn-important {\n  @apply bg-blue-500;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>3. Bundle Size Considerations\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-css\">\u002F* ⚠️ ระวัง - อาจทำให้ bundle ใหญ่ *\u002F\n.every-single-element {\n  @apply p-4 m-2 bg-white rounded shadow;\n}\n\n\u002F* ✅ ดี - ใช้เฉพาะที่จำเป็น *\u002F\n.common-card {\n  @apply p-4 m-2 bg-white rounded shadow;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>การทำงานร่วมกับ JavaScript Frameworks\u003C\u002Fh2>\u003Ch3>React Integration\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-plaintext language-jsx\">\u002F\u002F components\u002FButton.jsx\nimport clsx from 'clsx';\n\nconst Button = ({ \n  variant = 'primary',\n  size = 'md', \n  children, \n  className,\n  ...props \n}) =&gt; {\n  return (\n    &lt;button \n      className={clsx(\n        'btn',\n        `btn-${variant}`,\n        `btn-${size}`,\n        className\n      )}\n      {...props}\n    &gt;\n      {children}\n    &lt;\u002Fbutton&gt;\n  );\n};\n\n\u002F\u002F การใช้งาน\n&lt;Button variant=\"primary\" size=\"lg\" className=\"shadow-lg\"&gt;\n  คลิกที่นี่\n&lt;\u002FButton&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>Vue.js Integration\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-plaintext language-vue\">&lt;!-- components\u002FCard.vue --&gt;\n&lt;template&gt;\n  &lt;div :class=\"cardClasses\"&gt;\n    &lt;img v-if=\"image\" class=\"card-image\" :src=\"image\" :alt=\"title\" loading=\"lazy\"&gt;\n    &lt;div class=\"card-body\"&gt;\n      &lt;h3 v-if=\"title\" class=\"card-title\"&gt;{{ title }}&lt;\u002Fh3&gt;\n      &lt;p v-if=\"description\" class=\"card-text\"&gt;{{ description }}&lt;\u002Fp&gt;\n      &lt;slot&gt;&lt;\u002Fslot&gt;\n    &lt;\u002Fdiv&gt;\n  &lt;\u002Fdiv&gt;\n&lt;\u002Ftemplate&gt;\n\n&lt;script&gt;\nexport default {\n  props: {\n    variant: {\n      type: String,\n      default: 'default'\n    },\n    hover: {\n      type: Boolean,\n      default: false\n    },\n    image: String,\n    title: String,\n    description: String\n  },\n  computed: {\n    cardClasses() {\n      return [\n        'card',\n        this.hover &amp;&amp; 'card-hover',\n        `card-${this.variant}`\n      ].filter(Boolean);\n    }\n  }\n}\n&lt;\u002Fscript&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>Configuration และ Development Workflow\u003C\u002Fh2>\u003Ch3>Tailwind Config สำหรับ Component System\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-javascript\">\u002F\u002F tailwind.config.js\nmodule.exports = {\n  content: [\n    '.\u002Fsrc\u002F**\u002F*.{html,js,jsx,ts,tsx,vue}',\n    '.\u002Fcomponents\u002F**\u002F*.{html,js,jsx,ts,tsx,vue}'\n  ],\n  theme: {\n    extend: {\n      colors: {\n        primary: {\n          50: '#eff6ff',\n          500: '#3b82f6',\n          600: '#2563eb',\n          700: '#1d4ed8',\n        }\n      },\n      spacing: {\n        '18': '4.5rem',\n      }\n    }\n  },\n  plugins: [\n    require('@tailwindcss\u002Fforms'),\n  ]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch3>Build Script Setup\u003C\u002Fh3>\u003Cpre>\u003Ccode class=\"language-plaintext language-json\">{\n  \"scripts\": {\n    \"dev\": \"tailwindcss -i .\u002Fsrc\u002Finput.css -o .\u002Fdist\u002Foutput.css --watch\",\n    \"build\": \"tailwindcss -i .\u002Fsrc\u002Finput.css -o .\u002Fdist\u002Foutput.css --minify\"\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch2>การ Document Components\u003C\u002Fh2>\u003Cpre>\u003Ccode class=\"language-css\">\u002F**\n * Button Component\n * \n * Usage:\n * &lt;button class=\"btn btn-primary btn-lg\"&gt;Click me&lt;\u002Fbutton&gt;\n * \n * Variants: primary, secondary, green\n * Sizes: sm, md, lg\n * States: disabled\n *\u002F\n.btn {\n  @apply inline-flex items-center justify-center px-4 py-2 font-medium rounded-lg;\n  @apply transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2;\n  @apply disabled:opacity-50 disabled:cursor-not-allowed;\n}\n\n\u002F**\n * Card Component\n * \n * Usage:\n * &lt;div class=\"card card-hover\"&gt;\n *   &lt;div class=\"card-body\"&gt;\n *     &lt;h3 class=\"card-title\"&gt;Title&lt;\u002Fh3&gt;\n *     &lt;p class=\"card-text\"&gt;Content&lt;\u002Fp&gt;\n *   &lt;\u002Fdiv&gt;\n * &lt;\u002Fdiv&gt;\n * \n * Modifiers: hover, bordered\n *\u002F\n.card {\n  @apply bg-white rounded-lg shadow-md overflow-hidden;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Cp>&nbsp;\u003C\u002Fp>\u003Chr>\u003Cp>&nbsp;\u003C\u002Fp>\u003Ch3>สรุป\u003C\u002Fh3>\u003Cp>การสร้าง Component System ด้วย \u003Ccode>@apply\u003C\u002Fcode> และ Custom CSS ใน Tailwind CSS เป็นเทคนิคที่ทรงพลังที่ช่วยให้เราสามารถ:\u003C\u002Fp>\u003Ch4>ประโยชน์หลัก:\u003C\u002Fh4>\u003Cul>\u003Cli>\u003Cstrong>เขียนโค้ดเร็วขึ้น:\u003C\u002Fstrong> ใช้ Component ที่พร้อมใช้งาน\u003C\u002Fli>\u003Cli>\u003Cstrong>HTML สะอาด:\u003C\u002Fstrong> ลดความยาวของ class attributes\u003C\u002Fli>\u003Cli>\u003Cstrong>บำรุงรักษาง่าย:\u003C\u002Fstrong> แก้ไขที่เดียวได้ผลทุกที่\u003C\u002Fli>\u003Cli>\u003Cstrong>สร้าง Design System:\u003C\u002Fstrong> มีมาตรฐานที่ชัดเจน\u003C\u002Fli>\u003Cli>\u003Cstrong>ยืดหยุ่น:\u003C\u002Fstrong> ยังคงใช้ utility classes เพิ่มได้\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>หลักการสำคัญ:\u003C\u002Fh4>\u003Cul>\u003Cli>ใช้ \u003Ccode>@apply\u003C\u002Fcode> เฉพาะ Pattern ที่ใช้ซ้ำบ่อย\u003C\u002Fli>\u003Cli>ตั้งชื่อ Component ให้สื่อความหมาย\u003C\u002Fli>\u003Cli>จัดระเบียบด้วย \u003Ccode>@layer\u003C\u002Fcode> ที่ถูกต้อง\u003C\u002Fli>\u003Cli>คำนึงถึง Performance และ Bundle Size\u003C\u002Fli>\u003Cli>Document Component ให้ครบถ้วน\u003C\u002Fli>\u003C\u002Ful>\u003Ch4>ข้อควรระวัง:\u003C\u002Fh4>\u003Cul>\u003Cli>อย่าใช้ \u003Ccode>@apply\u003C\u002Fcode> กับทุกอย่าง\u003C\u002Fli>\u003Cli>ระวัง Bundle Size เมื่อสร้าง Component มากเกินไป\u003C\u002Fli>\u003Cli>ทดสอบ Browser Compatibility สำหรับ CSS properties ที่ใหม่\u003C\u002Fli>\u003Cli>จัดลำดับ CSS imports ให้ถูกต้อง\u003C\u002Fli>\u003C\u002Ful>\u003Cp>ในตอนถัดไป EP 8 เราจะมาเรียนรู้เรื่อง Customization ขั้นสูง การปรับแต่ง Tailwind ให้เป็นของตัวเอง สร้าง Custom Theme และใช้งาน Plugin ต่างๆ ที่จะทำให้ Tailwind CSS ของเราพิเศษและตอบโจทย์โปรเจ็กต์ได้อย่างสมบูรณ์แบบ!\u003C\u002Fp>\u003Cp>พร้อมหยุดเขียนโค้ดซ้ำๆ แล้วหรือยัง? ติดตาม Superdev School เพื่อเรียนรู้เทคนิคการพัฒนาเว็บไซต์แบบมืออาชีพ และอย่าลืมลองสร้าง Component System ของตัวเองดูนะครับ!\u003C\u002Fp>\u003Cp>\u003Cstrong>อ่านบทความ Series อื่นๆ\u003C\u002Fstrong>\u003C\u002Fp>\u003Cul>\u003Cli>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdev.school\u002Fblogs\u002Fcategories\u002FGolang\">\u003Cstrong>Golang The Series\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdev.school\u002Fblogs\u002Fcategories\u002FJS2GO\">\u003Cstrong>JS2GO\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fli>\u003Cli>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdev.school\u002Fblogs\u002Fcategories\u002FTailwind%20CSS\">\u003Cstrong>10 Ep ที่จะให้คุณเป็นมือโปร Tailwind CSS ในชั่วข้ามคืน\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>🔵 Facebook: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.facebook.com\u002Fsuperdev.school.th\">\u003Cstrong>Superdev School &nbsp;(Superdev)\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>\u003Cp>\u003Cstrong>📸 Instagram: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.instagram.com\u002Fsuperdevschool\u002F\">\u003Cstrong>superdevschool\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>\u003Cp>\u003Cstrong>🎬 TikTok: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.tiktok.com\u002F@superdevschool\">\u003Cstrong>superdevschool\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>\u003Cp class=\"\" data-start=\"5978\" data-end=\"6095\">\u003Cstrong>🌐 Website: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\u002F\u002Fwww.superdev.school\u002F\">\u003Cstrong>www.superdev.school\u003C\u002Fstrong>\u003C\u002Fa>\u003C\u002Fp>","13_11zon_f4ljljda8k.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002F5x8ane989d7afzz\u002F13_11zon_f4ljljda8k.webp","2026-03-04 08:26:45.818Z","",{"keywords":15,"locale":38,"school_blog":48},[16,23,28,33],{"collectionId":17,"collectionName":18,"created":19,"created_by":13,"id":20,"name":21,"updated":22,"updated_by":13},"sclkey987654321","school_keywords","2026-03-04 08:26:35.002Z","eq1u1plwlvvr2rh","Tailwind CSS","2026-04-10 16:07:31.210Z",{"collectionId":17,"collectionName":18,"created":24,"created_by":13,"id":25,"name":26,"updated":27,"updated_by":13},"2026-03-04 08:26:43.800Z","6s6bajdywslvd70","tailwind css @apply","2026-04-10 16:07:33.822Z",{"collectionId":17,"collectionName":18,"created":29,"created_by":13,"id":30,"name":31,"updated":32,"updated_by":13},"2026-03-04 08:26:44.918Z","r991u42vf504emh","component system tailwind","2026-04-10 16:07:34.239Z",{"collectionId":17,"collectionName":18,"created":34,"created_by":13,"id":35,"name":36,"updated":37,"updated_by":13},"2026-03-04 08:26:42.252Z","ujbbp4zfs5h7m0a","tailwind css components","2026-04-10 16:07:33.360Z",{"code":39,"collectionId":40,"collectionName":41,"created":42,"flag":43,"id":44,"is_default":45,"label":46,"updated":47},"th","pbc_1989393366","locales","2026-01-22 10:59:55.832Z","twemoji:flag-thailand","s8wri3bt4vgg2ji",true,"Thai","2026-04-10 15:42:46.614Z",{"category":49,"collectionId":50,"collectionName":51,"expand":52,"id":65,"views":66},"i22e96fj41lsws7","pbc_2105096300","school_blogs",{"category":53},{"blogIds":54,"collectionId":55,"collectionName":56,"created":57,"created_by":13,"id":49,"image":58,"image_alt":13,"image_path":59,"label":60,"name":21,"priority":61,"publish_at":62,"scheduled_at":13,"status":63,"updated":64,"updated_by":13},[],"sclcatblg987654321","school_category_blogs","2026-03-04 08:26:33.946Z","vzv2yduhfk_hs035tvsww.webp","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Fi22e96fj41lsws7\u002Fvzv2yduhfk_hs035tvsww.webp",{"en":21,"th":21},10,"2025-07-25 05:27:14.926Z","published","2026-04-25 02:32:14.403Z","07n2giqabaejy8h",218,"5x8ane989d7afzz",[20,25,30,35],"2025-07-22 10:18:57.142Z","เรียนรู้วิธีสร้าง Component System ด้วย @apply directive ใน Tailwind CSS แบบมืออาชีพ ลด HTML ที่ยาวเยิ่น สร้าง Design System ที่บำรุงรักษาง่าย พร้อมเทคนิค Best Practices และการทำงานร่วมกับ React\u002FVue.js","tailwind-css-component-system-apply-directive-ep7","2026-04-25 02:47:18.631Z",1,{"th":71}]