Category: reference
CSS @property — Typed Custom Properties
CSS @property ทำให้ custom properties มี type, initial value, และ inheritance control — รองรับ animation ของ color, number, และ gradient
สารบัญ
@property คืออะไร
CSS Custom Properties ปกติ (--color: red) เป็น untyped string — browser ไม่รู้ว่าเป็น color หรือ number ทำให้ animate ไม่ได้ @property แก้ปัญหานี้โดยระบุ type ให้ชัดเจน
/* ❌ ปกติ: animate ไม่ได้ */
:root { --hue: 220; }
.element {
background: hsl(var(--hue), 80%, 60%);
transition: --hue 0.3s; /* ไม่ทำงาน */
}
/* ✓ @property: animate ได้ */
@property --hue {
syntax: '<number>'; /* type */
inherits: false; /* ไม่ inherit จาก parent */
initial-value: 220; /* ค่าเริ่มต้น (required ถ้า inherits: false) */
}
.element {
--hue: 220;
background: hsl(var(--hue), 80%, 60%);
transition: --hue 0.3s ease; /* ✓ ทำงานแล้ว */
}
.element:hover { --hue: 280; }
Syntax Types ที่ใช้ได้
@property --color { syntax: '<color>'; inherits: true; initial-value: #000; }
@property --length { syntax: '<length>'; inherits: false; initial-value: 0px; }
@property --number { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --percentage { syntax: '<percentage>'; inherits: false; initial-value: 0%; }
@property --length-pct { syntax: '<length-percentage>'; inherits: false; initial-value: 0px; }
@property --angle { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
@property --integer { syntax: '<integer>'; inherits: false; initial-value: 0; }
/* หลาย types (pipe = OR) */
@property --size { syntax: '<length> | <percentage>'; inherits: false; initial-value: 0px; }
/* ค่าเฉพาะ (เหมือน enum) */
@property --theme { syntax: 'light | dark'; inherits: true; initial-value: light; }
/* รับทุก value (ไม่มี type checking) */
@property --any { syntax: '*'; inherits: false; initial-value: 0; }
Animate Gradient
/* ❌ ก่อน @property: transition gradient ไม่ได้ */
.gradient {
background: linear-gradient(90deg, red, blue);
transition: background 0.5s; /* ไม่ smooth */
}
/* ✓ หลัง @property: animate ได้ */
@property --from-color {
syntax: '<color>';
inherits: false;
initial-value: #ef4444;
}
@property --to-color {
syntax: '<color>';
inherits: false;
initial-value: #3b82f6;
}
.gradient {
background: linear-gradient(90deg, var(--from-color), var(--to-color));
transition: --from-color 0.5s, --to-color 0.5s;
}
.gradient:hover {
--from-color: #f59e0b;
--to-color: #10b981;
}
Progress Bar Animation
@property --progress {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
.progress-bar {
--progress: 0%;
background: conic-gradient(#2563eb var(--progress), #e2e8f0 var(--progress));
border-radius: 50%;
width: 80px;
height: 80px;
transition: --progress 0.6s ease-out;
}
/* set จาก JS */
.progress-bar { --progress: 75%; }
Counter Animation
@property --count {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@keyframes count-up {
from { --count: 0; }
to { --count: 1000; }
}
.counter {
animation: count-up 2s ease-out forwards;
counter-reset: num var(--count);
}
.counter::after {
content: counter(num); /* แสดงค่า --count */
}
Color Theme ด้วย @property
@property --brand-hue {
syntax: '<number>';
inherits: true; /* ✓ inherit ลงมาจาก :root */
initial-value: 220;
}
:root {
--brand-hue: 220;
--brand: hsl(var(--brand-hue) 80% 50%);
--brand-light: hsl(var(--brand-hue) 80% 95%);
--brand-dark: hsl(var(--brand-hue) 80% 25%);
}
/* เปลี่ยน theme ทั้งหมดด้วยการเปลี่ยน hue เดียว */
.theme-green { --brand-hue: 142; }
.theme-purple { --brand-hue: 280; }
.theme-red { --brand-hue: 0; }
/* animate theme switching */
:root { transition: --brand-hue 0.4s; }
ใช้งานจาก JavaScript
// อ่านค่า
const el = document.querySelector('.element');
getComputedStyle(el).getPropertyValue('--progress'); // '75%'
// ตั้งค่า
el.style.setProperty('--progress', '75%');
// @property ด้วย CSS.registerProperty() (JavaScript version)
CSS.registerProperty({
name: '--progress',
syntax: '<percentage>',
inherits: false,
initialValue: '0%',
});
Browser Support
Chrome 85+, Edge 85+, Firefox 128+, Safari 16.4+ — ใช้งาน production ได้แล้ว
/* Progressive enhancement */
@supports (animation-timeline: scroll()) {
/* ใช้ @property features ขั้นสูง */
}
/* หรือ detect ด้วย JS */
const supported = window.CSS?.registerProperty !== undefined;
เปรียบเทียบกับ CSS Variables ปกติ
| CSS Variable ปกติ | @property | |
|---|---|---|
| Type | String (untyped) | Typed (<color>, <number>, etc.) |
| Animation | ❌ ไม่ได้ | ✓ animate ได้ |
| Initial value | ไม่มี | ต้องระบุ |
| Inherit | ตามปกติ | control ได้ (true/false) |
| Browser support | ทุก browser | Chrome 85+, Firefox 128+ |