網誌

React 的 Optimistic UI:故意說謊的介面

「讚好」按鈕立即作出反應,心心圖示填滿,數字隨即增加——而伺服器根本還沒有回應。這不只是微互動那篇文章講過的速度錯覺,而是更進一步的事情:介面展示了一個尚未存在的狀態,並且假定它馬上就會成真。本文探討如何安全地實作這種模式——包括假設落空時要如何老實地收回這個謊言,以及為甚麼手寫 setState 加 catch,是 useOptimistic 提供的方案的劣質版本。

CSS @layer:cascade layers 如何終結 specificity 戰爭

工具類 .mt-4 輸給了 .card .card__header .card__title 這條規則,儘管照道理它是後加上去的,應該要贏。這不是巧合——這正是 specificity 按照它原本的設計在運作。@layer 帶來了一條全新的判定優先次序的軸線,它在 specificity 之前起作用,而不是跟它一起運作——而且當中有一個陷阱違反直覺到連網上部分文件都會寫錯。

Next.js 的 Server Actions:JavaScript 尚未加載,表單已經在運作

「use server」看起來就像是呼叫 API route 的 fetch 的語法糖——正因如此,大部分實作都把它當成普通的函式呼叫來對待。這是一個會帶來具體後果的誤解:每一個標記為「use server」的函式,都會變成網絡上一個公開的端點,而建基於這個機制的表單,甚至在 JavaScript 尚未加載完成之前就已經可以運作。本文探討這個指令背後實際發生的事情,以及那些單看文件未必一眼就能看出的陷阱。

CSS :has()——知道內部發生甚麼事的父元素

表單欄位要在內部 input 無效時變成紅色。聽起來很簡單——只是 CSS 在過去 25 年裡,從來沒辦法讓元素查詢自己內部發生的事,只能反過來做。本文探討 :has() 如何逆轉這個方向、它跟一般組合器有何不同,以及這種新能力在哪些地方真的會犧牲效能。

Container Queries:認識自己容器,而非視窗的組件

同一張商品卡片,放在網格裡好端端的,放進狹窄的側邊欄卻整個散開——即使 media query 早已細心調校過。問題不在你的程式碼,而在 media query 問錯了問題:它問的是螢幕有多寬,而不是這個組件實際分配到多少空間。本文探討 container queries 如何把這個問題放回它本該提出的位置,以及當元素變成「查詢容器」時,底層究竟發生了甚麼事。

為屏幕閱讀器建立可訪問的組件

正確的 HTML 只是起點。本文深入講解可訪問性樹的實際運作方式、ARIA 為何往往弊多於利,並與你一起實作一個真正可用的手風琴組件、一個即時通知區域,以及 Next.js 的焦點處理。