發表文章

不需要計算DOM的動態文字排版:pretext

文字排版,甚至是文字與元素的動態互動,常常因繁瑣且頻繁地計算DOM,造成效能不佳。 然而,當Cheng Lou在twitter po出這篇文章時,所有前端人員都震驚了:只需要用數學方法觀察文字大小和字體計算換行符,「不需要去碰DOM的解決方案」,完全避開了Reflow惡夢。 My dear front-end developers (and anyone who’s interested in the future of interfaces): I have crawled through depths of hell to bring you, for the foreseeable years, one of the more important foundational pieces of UI engineering (if not in implementation then certainly at… pic.twitter.com/BKnwCDIp75 — Cheng Lou (@_chenglou) March 28, 2026 你可以查看此篇文的各方高手引用實作,就能看出這是多麼劃時代的解決方案。金字塔、文繞圖(圖片會動)、Bad Apple動畫等文字排版完美解決且非常順暢,在文章中玩Air Hockey也沒有問題。 Cheng Lou也把pretext技術開源放到 github ,你也能親自發揮你的創意體驗一下它的強大。 Riding the wave of the pretext.js without pretext 😅 pic.twitter.com/D8CAAZqcpJ — Felix Martinez (@Sirokos) March 30, 2026 上面是有人用pretext.js實作的衝浪效果。不怕做不到,只怕沒創意靈感。
隨著自主 AI Agent 與 A2A(Agent to Agent)技術快速成長,網路流量與互動主體正經歷一場劇變。當前,自動化機器人與代理程式已佔據全球網路流量的 51%,這些沒有視覺也沒實體雙手的軟體,正試圖在專為人類設計的介面上,處理越來越複雜的任務。 Chrome 146 引入了一項足以改變網際網路底層互動邏輯的實驗性功能:網頁模型上下文協定(Web Model Context Protocol,簡稱 WebMCP)。 WebMCP 的核心目標是幫網頁建立一層專供機器讀取的語意化抽象結構,讓網頁從純粹的「視覺化呈現」轉變為「機器可操作」的網路。透過這個協定,網頁能直接向 Agent 宣告自己支援哪些工具與操作邏輯,把原本模糊的介面摸索,轉化為精準的 API 呼叫。 在 W3C 網頁機器學習社群群組的藍圖中,WebMCP 屬於增強網頁 AI 能力的核心標準之一。它被定位為低階的網頁 API,讓開發者把網站功能打包成 Agent 能呼叫的「工具」——本質上就是帶有自然語言描述與 JSON Schema 的 JavaScript 函式。 代理程式優化(AAO)的崛起 AAO 被視為 SEO 與 AEO 的下一步。在 AAO 的戰略框架下,網站的目標不再只是讓爬蟲「讀懂」靜態內容,更要確保機器具備「操作」網站核心商業功能的能力。 對技術長與行銷團隊而言,前端架構的投資方向必須重新評估。提供語意清晰、型別嚴謹的工具描述與參數定義,重要性已經等同於過去設定 Meta 標籤或優化 Core Web Vitals。寫得不清不楚(例如只寫 "Search stuff"),Agent 看不懂就會直接略過。 面對這個轉變,企業安全架構也得同步升級,防禦重點必須轉向「意圖感知控制」,防範自動化交易帶來的風險。誰能率先定義出安全(具備 OAuth 與短效 Token)、高效且語意明確的 WebMCP 工具合約,誰就能在 AI 商業交易中搶佔先機,把技術升級轉變為絕對的商業優勢。 擁抱機器可操作的語意網路 Chrome 146 導入實驗性 WebMCP,精準解決了過去 Agent 解析 DOM 既耗費代幣又容易出錯的痛點。純前端的設計加上同源安全邊界,也克服了後端 MCP 伺服器的隱私與授權限制。 WebMCP 區分宣告式與...
圖片
徹底告別換行破版? 我們在處理 RWD(響應式網頁設計)時,最頭痛的往往不是圖片,而是 文字的換行 。特別是在 banner(也有人稱hero)的大標題,設計師希望它永遠單行滿版,但視窗一縮小,文字就無情地折行,破壞了原本的視覺張力。 以往我們可能需要依賴 clamp()達到max,min font-size的動態效果 ,但在 Chrome 145 版本之後,原生CSS就提供了強大的解決方案: text-grow 與 text-shrink 。 語法介紹 這兩個屬性允許文字根據容器空間自動「膨脹」或「收縮」,核心概念是 不換行 ,改變文字型態來適應容器。 /* 基本語法 */ text-grow: <fit-target> <fit-method>? <length>?; text-shrink: <fit-target> <fit-method>? <length>?; text-grow :當文字短於容器時,如何變大填滿。 text-shrink :當文字長於容器時,如何變小塞入。 參數說明 1. <fit-target>:決定調整的對象 (必填) 決定了多行文字該如何反應: per-line (逐行調整) : 對於 text-grow :每一行都會獨立計算,短的行會自動擴展填滿容器。 對於 text-shrink :長的行會自動縮小,短的行保持原狀。這對於多行標題非常有用。 consistent (一致性調整) : 對於 text-grow :找出 最短 的那一行,計算放大比例後, 所有行 套用相同比例。 對於 text-shrink :找出 最長 的那一行,計算縮小比例後, 所有行 套用相同比例。這能保持文字原本的層級與視覺比例。 2. <fit-method>:決定變形的方式 (選填) scale :縮放字形而不是改變 font-size 。 scale-inline :縮放字形而不是改變 font-size ,但只能水平縮放。 font-size :相應地增大或縮小字體大小...
圖片
很多網站一打開就會跳「權限請求」的視窗,使用者第一個反應通常是:「為什麼要我的位置」、「我連內容都還沒看為何就要我訂閱」、「為什麼要我的xx存取權」,結果就是使用者直接拒絕。 Chrome 144 新增的 <geolocation> 就是在處理這類問題:在使用者理解網站功能後,讓權限請求從網站方變成使用者自己主動要求。 <geolocation> 在做什麼 一定要使用者點擊後才會問權限 不是 JavaScript 自己跳視窗,使用者已有心理準備。 請求發生在有情境的地方 例如「找附近店家」按鈕,點了才要位置,很直覺。 之前拒絕過,也還有回頭路 不用叫使用者自己跑去翻瀏覽器或系統設定。 開發者少寫一堆平台判斷 權限流程、系統層級阻擋,瀏覽器幫忙處理。 它不是突然冒出來的 一開始 Chrome 是用一個比較泛用的 <permission> 元素 做測試,從 Chrome 126 到 143 都在 origin trial。 後來發現,與其什麼權限都塞在同一個元素,不如拆成「用途明確」的元素比較好用,所以才有現在的 <geolocation> 。 相關文章: 對 <permission> 元素的再強化 。 實際怎麼用 用法很單純,就是把它當成一個 HTML 控制項放在畫面上。若瀏覽器不支援,仍可用自己的button: <geolocation> onlocation="handleLocation(event)" autolocate accuracymode="precise" <button onclick="navigator.geolocation.getCurrentPosition(updatePosition)"> 不支援時使用這個button...
圖片
現在只要在CSS加上一行 text-autospace:normal ,中文與英文數字間就會自動產生空格般的視覺間距,不用再為這個網頁開發規範而煩惱。 舊有的快速解決方案 在以前,遇過一個開發規定,就是上面提到的「空格規範」,這其實很簡單就能做到:在VS Code開發環境使用AutoCorrect或 Auto Add Space between Chinese and English 套件就能自動幫你空格。 但如果是要修改公司從以前到現在累積的上千篇文章,全部更正除了人工加上空格之外,想要快速解決這個問題就是載入 pangu.js 這個套件在client端自動處理。 但這個套件其實在某些少數的狀況下不會產生空格,而且為了這個需求而載入一個套件,開發人員還要為此多寫一段測試。 text-autospace降臨解救眾生 在瀏覽器支援text-autospace語法之後,一切的問題都不再是問題。 body{ text-autospace:normal; } text-autospace的瀏覽器支援情況。 但是你在加上這行語法之後,若遇到中英文中間不需有空格視覺的時候(例如某些品牌名稱),則要再寫 text-autospace: no-autospace; 讓文字間看起來沒有空格。 另外,目前也沒有辦法設定這個空白空間的寬度,這是未來瀏覽器可以再精進的方向。 註:本篇文章中文與英文之間都沒有空格,並加上此語法,你可以直接看到此語法的視覺效果。
圖片
為什麼 API 權限全開,還是會封鎖連線? 開發前後端分離架構,或是串接不同環境 API 時,常發生一種情況:後端已設定 Access-Control-Allow-Origin: * (允許所有網域存取),且 Postman 測試正常,但從瀏覽器環境透過 JavaScript 發送請求給內網或私有環境的 API 伺服器時,Chrome 卻強制阻擋連線。 這是 Chrome 實施「 區域網路存取權 」(Local Network Access, LNA)規範所致,目的是為了保護使用者免於跨網站要求偽造 (CSRF) 攻擊。 使用者在初次進入網站時, 若網頁向「本機」網路索取資料時 ,可能會看到這2種提示訊息視窗(也可能不會看到就自動封鎖或允許): 這會帶來什麼影響? 這項安全機制會導致即使後端 API 權限全開,瀏覽器仍攔截請求。具體的錯誤訊息如下: Access to fetch at 'https://api.example.com/apiName' from origin 'https://www.example.com' has been blocked by CORS policy: Permission was denied for this request to access the `unknown` address space. net::ERR_FAILED 有些人一看到「blocked by CORS policy」這幾個字可能會誤以為是CORS的問題,實際上並非如此,而是上面所述的LNA或HTTPS問題。 看到 Permission was denied for this request to access the ... address space 關鍵字,即代表觸發「區域網路存取限制」。瀏覽器判定來源(如 www.example.com )位於公網,而目標解析後位於私有網路或無法判定的位址空間,直接封鎖。 技術債的償還:API 呼叫的正規做法 遇到此問題時,有些網站管理者會教使用者如何解除封鎖,並叫他們點擊「允許」: 點擊網址左邊的icon。 開啟存取權。 重新整理頁面。 跳出提示視窗時點擊允許。 使用者手動解除封...
圖片
許多人在最近都有看過一份來自seer interactive的 AIO觀察報告 ,點擊率下降已是常態,但讓人出乎意料的是,就算沒有出現AIO(AI Overviews),點擊率也下降。 數據來源是他們的客戶,觀察時間從去年6月到今年9月: 42 個客戶組織的 3119 個搜尋詞彙 2510 萬次自然曝光和 110 萬次付費曝光 自然搜尋點擊有無AIO的影響 有AIO下降幅度:61% 無AIO下降幅度:41% 為何就算沒有AIO,點擊率仍然下降了41%?原因很簡單: 零點擊搜尋越來越多 AIO與其它AI平台的出現,造成更多企業往PPC投資 Google自家平台在SERP越來越活躍(商家檔案、Google Maps、Google Shopping、YouTube) 其它使用者習慣的改變 你可以發現,就算沒有AIO,自然點擊率也註定會下降,只是AIO加劇了這個情況。 但多投資付費關鍵字廣告就是解答嗎?倒也不是,實際上付費廣告的點擊率也不一定會好。 付費廣告點擊有無AIO的影響 有AIO下降幅度:68% 無AIO下降幅度:32% 就算付費廣告出現的位置在AIO上面,點擊率仍然大幅下降;且就算沒有AIO,也因為可預見的競爭變多、AI Agent的自動完成工作,下降幅度也不小。 有趣的是,在下方的AIO如果有提到你的品牌,付費點擊率又會上升91%。 AIO存在且品牌被AIO引用,會提升點擊率 但要注意,這個數據可能有誤導性:也許搜尋的字詞本身就包含品牌也說不定,又或者是二次搜尋導致。 Google拿石頭砸自己腳? 所以,Google AIO 的出現反而讓 Google 自己在付費廣告賺的錢變少了? 答案是不一定,畢竟競爭變多了,平均單次點擊價格也會大幅提升。而且,Google自己可能也發現了PPC點擊率下降的問題,因此在9月測試並修改了AIO的某些演算法。 BrightEdge 發現,9月時AIO在電子商務類的覆蓋率異常 這次的改動,多半是AIO對於「意圖」的理解度提升,讓使用者在需要點擊付費廣告時大幅降低出現AIO的機率,判斷是比較、研究、學習等意圖時則保留出現率。 因此,我們可以觀察11、12月的購物季,付費廣告的點擊率有沒有稍微改善。 被AI提及或引用太重要 我...
圖片
長久以來,Google提出的data-nosnippet方法只對Google爬蟲有用;現在Bing也跟上支援這個HTML attritube,且就連Copilot AI也能看懂data-nosnippet了。 圖片作者: Jason Leung data-nosnippet是什麼?功用是什麼? 自從2021年開始, 網頁title 和描述(description)會在搜尋結果中被Google修改後,為了不讓描述出現網站擁有者不想讓別人看見的文字, data-nosnippet 就此孕育而生。 它的功用在於,只要該段落加上data-nosnippet,當中的文字絕對不會變成Google搜尋結果中的網頁描述。以下為簡單的使用例子: <section data-nosnippet> <p>這段文字不會變成網頁描述,也不會被Copilot AI提取</p> </section> 另外,Bing也簡單 舉例 了它的常見運用方式: 將付費內容排除在預覽之外。 不想讓用戶評論或評價的曝光。 隱藏法律樣板、免責聲明和Cookie通知。 排除贊助廣告或過期的促銷內容。 A/B TEST。 Bing和Copilot AI的支援,樂觀看待 另一個搜尋巨頭也能用data-nosnippet的話,可以樂觀地期待所有搜尋引擎都支援的一天到來。 更開心的是連Copilot都支援以提升AI生成的品質,其它AI巨頭是否也會跟上?
圖片
以前如果說 CSS 是「程式碼」的話,通常都會被糾正為「原始碼」,但在 @function 等功能性的語法出現之後,現在這個傳統界線也越來越模糊。 本文將透過之前提過的 if() 和 sibling-index()、sibling-count() 語法,帶大家體驗 @function 的強大功能。 1. 結合 attr() 與型別定義的狀態樣式 過去我們使用 attr() 取值時,通常只能用於 content 屬性,且無法參與運算或邏輯判斷。新的語法允許我們指定型別 type(<custom-ident>) ,這讓 HTML 的屬性值可以被 CSS 的 if() 邏輯正確識別。 在這個範例中,我們定義了一個 --status-color 函數,它接收一個狀態參數,並根據傳入的值決定回傳的顏色。你可以注意到,它和 JavaScript 一樣可以設定變數的預設值: @function --status-color(--status: xxx, --success: #7dfaa5, --error: #ff3874) { result: if( style(--status: success): var(--success); style(--status: error): var(--error); else: #fccd81 ); } .card { /* 使用 attr() 抓取 HTML 的 data-status,並強制轉型為 custom-ident */ background-color: --status-color(attr(data-status type(<custom-ident>))); } 跟 JavaScript 不同的地方在於,JS 是用 return 拋出結果,CSS 則是用 result: 。 這樣的寫法讓我們可以直接在 HTML 中控制語意,而樣式的邏輯完全封裝在 CSS 函數內: <div class="card" data-status="error">error</div> <div class="card" data-status=...
圖片
許多行銷人員都會依賴 GTM 插入 Facebook Pixel 的程式碼,但你是否有想過,當一個網站上出現多個 Pixel ID 的時候,一直 init(重新宣告)Pixel ID、直接觸發事件、整段程式碼貼上,會重複追蹤事件(一直Add to Cart)、覆蓋變數影響其它 Pixel ID……等問題,最終除了讓網頁效能降低外,收集到的數據也不準確。 曾經經手過一個充滿好幾個 meta pixel 和 bing uet 的網站,單純把 GTM 拿掉,效能就可以提升超過40分。 自訂事件一般寫法 許多行銷人員會在 GTM 中使用「自訂 HTML」直接貼上像這樣的程式碼來達成他想要的自訂事件: <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '1234567890'); fbq('trackCustom', '自訂事件名稱', { '額外要傳送的數據Object': 999 }); </script> 但他完全沒有考慮可能會發生的問題: https://connect.facebook.net/en_US/fbevents.js 是否已經載入過了。( 這個其實官方程式碼已經處理: if(f.fbq)return; ) Pixel ID 是否已經宣告...
圖片
CSS 中「兄弟元素」的應用與痛點 在網頁切版與動畫設計中,我們經常遇到需要根據「元素是第幾個」或「總共有幾個元素」來改變樣式的情境。例如: 交錯動畫 (Staggered Animation): 讓列表中的項目一個接一個出現,而不是同時出現。 動態寬度: 根據容器內有多少個項目,自動計算每個項目的寬度。 階梯狀視覺: 依序改變背景色深淺或位置偏移。 在過去,要純用 CSS 達成這些效果非常繁瑣。我們通常只能依賴 :nth-child() 寫死一堆規則(例如寫 50 行 CSS 來對應 50 個項目),或是使用 SCSS 的迴圈在編譯時產生代碼。更靈活的做法則是依賴 JavaScript 去計算並動態賦予 CSS 變數(如 --index , --total )。因此原生的 CSS 解決方案因此備受期待。 此圖片由AI生成 sibling-index() 與 sibling-count() sibling-index()返回該元素在兄弟節點中的 索引值 (通常從 1 開始計算,具體依實作而定)。它相當於 JavaScript 中遍歷 DOM 得到的 index。 sibling-count()返回該元素的父容器下,包含自己在內共有多少個 兄弟節點總數 。它相當於 JavaScript 中的 parentNode.children.length 。 基本語法範例: .item { /* 讓每個項目的動畫延遲時間隨索引增加 */ animation-delay: calc(sibling-index() * 0.1s); /* 根據總數量自動計算寬度 */ width: calc(100% / sibling-count()); } CodePen 實例解析 接下來我們透過 CodePen 實作一些簡單的範例。 See the Pen sibling-index(), sibling-count() by cj ( @cjzopen ) on CodePen . 自動計數與視覺堆疊 在範例中,透過 sibling-index() ,我們可以為每一個卡片或列表項目設定獨立的 Z 軸層級或顏色變化,而...
圖片
大家都知道,AI 為了迎合使用者、不懂裝懂時,會產生 AI 幻覺(hallucination),除了文字之外,有時也會出現超連結的幻覺。若只是 AI 幻想的連結那還好,但若是把社交工程的連結拿來給使用者點擊,嚴重性可大可小。 本圖片由AI生成 實際經驗 前幾天在AI平台詢問如何報廢機車領取補助、如何得知該報廢機車的出廠年份,AI 給出的答案都非常正確,但其中一個連結卻是連到釣魚網站。 雖然我以前就知道 AI 有時候會自創連結,但沒想到這次自創的連結剛好具有攻擊性,不可不注意。 說到這裡,有些人的網站也遇到一些來自AI平台的404流量。 如何處理因AI幻覺而進站的404流量? 絕對不要為了從以前就不存在的頁面設定301轉址。 網站的404頁面要有引導能力。 任意設定301轉址的話會造成各方面的困惑(不論是爬蟲還是使用者),最差的做法就是將404全部跳轉到首頁,這對 SEO 來說是禁忌。 404並沒有什麼不好,它也是好不容易得來的流量;反過來看,你可以把404頁面當成landing page,好好地設計它,讓它成為有效的流量。 舉例來說,404頁面可以導入AI技術,從網址來判斷使用者的意圖,再推薦使用者一些他可能會感興趣的頁面。 為何網站的404幻覺流量會很多? 有一說是網頁架構太差,加上網頁的網址結構太爛。例如明明存在產品導覽頁面,但產品網址卻不在產品導覽頁面下面。 另外也有一說是缺乏標準網址(canonical)、原本存在的404連結就很多。就看你信不信。 總而言之,在AI平台(尤其是 ChatGPT)點擊超連結時,就跟打開 email 一樣,稍微留意一下網域是否錯的太離譜。
圖片
也許你有發現各AI平台有在優化「黏著度」,有的是在回答完後問你要不要繼續幫你做某些事,有的則是會在回答中分段落,在點擊段落標題後把此標題當作你的繼續提問,有的則是列出你可能還會問的問題吸引你點擊,有的還會跳出相關領域的「AI專家」吸引你切換後繼續提問。 在越來越多人使用、花費更多時間在AI平台時,所有人都知道要評估自身品牌 GEO 的成效,但是,資料從哪裡來? 先說結論:目前有 ahrefs 等大廠推出評估工具,但效果如何見仁見智。為什麼?因為目前仍然無法得知: 真正的使用者問了什麼,讓我的品牌被提及了?只能自己設定 prompt。 AI 提及我的品牌時是如何描述的?就算用 API 去執行一次,實際上也會因為不同人而產生差異;且就算是同一個人,重複提問產生的內容也未必相同。 AI 因「黏著度」的考量會引導使用者追問,它說了什麼?使用者又是追問了什麼?這個跟前兩者是類似的原因。 什麼時候開始引用我的連結?是否為「無效引用」?一直問類似問題出現的比例是多少?顯示的圖片又是哪一張? 「無效引用」跟使用者問了什麼息息相關,舉例來說,當使用者提問像是「導入AI的最佳指南是什麼」之類的問題,AI在思考期間想從多種角度切入,其中一個角度是ROI;然而,你因為寫了一篇「什麼是ROI」的文章而被引用,但跟使用者的主要目的完全無關,就是無效引用。 是的,你可以發現目前大廠的工具都只是「模擬」,而不是真正的數據。你要認真想一下,每個月花超過99元得到的不真實數據,能為產品帶來什麼好處?又或者你只是想要一個數據應付你的主管,那這還需要花錢嗎? 強化AIO與GEO的方法 也許你也會想知道怎麼優化,這裡先提供一份簡報給你參考: https://gamma.app/docs/AIOGEOAI-MODE-rt0q4h5vz30dwaz 。 總而言之就是先做好 SEO 的基本功:indexing。 簡報中有寫: Priming Effect:一旦某個品牌或概念出現在AIO,它就會變成人們想法的起點(或視野會被限制)。 風險、成本越高,就越會查證。而查證就是 SEO 的方向。 SEO成功的驅動力之一: 線下SEO 。用戶在AIO或搜尋結果中看到你的品牌之前,你已經贏得了多少 「心智份額」(有別人稱心佔率) 。 除此...