ENTER or SPACE, KEYDOWN or KEYUP

前一篇文章作動行為 Activation Behavior發佈之後,卡西又做了一些測試,發現到 ENTERSPACE 的觸發時機其實不一樣:

然後我仔細測試過發現真的是這樣,而且 SPACEkeypress的狀態,就像是滑鼠按鍵按下去但是還沒放開時的樣子,然後這又讓我有點好奇起來了,仔細搜尋一番,發現 web 標準都沒有提到這個細節的定義,唯一有一點關係的是卡西也有找到的WAI-ARIA Authoring Practices Issue 610,於是我就覺得這應該和 Web 標準定義沒關係,應該是更古老的預設行為,於是改變方向改找 Windows 預設行為相關的文件,搜尋一陣子其實也找不太到東西,大概是因為 GUI 和 Windows 剛出的時候其實 www 還不知道在哪裡吧,不過後來還是找到兩篇 stackoverflow 的問答看起來是相關的:

總和這兩篇的內容,大概整理一下:

這個行為應該是 Windows 一開始的時候就如此設計的了(看起來是很難找到相關設計的文件),然後實際上和 ENTER 相關(相對)的操作其實是 ESC 鍵,ENTER 鍵代表的是直接點 default button(例如 form 的 submit、dialog 的 ok 之類的),或是可以說是執行元件預設的行為,至於 ESC 鍵則是取消,不過取消在網頁的控制元件中幾乎是不存在的,過去有的大概只有<select>展開下拉選單後又決定不選時可以取消,到 HTML5 則又多了<dialog>有取消的行為(關閉 dialog),大概也是因為這個原因讓人忽略了 ENTERESC 的關係,變成注意到 ENTERSPACE 都可以操作元件;至於 SPACE 鍵其實就像是滑鼠點擊,keyDown如同mouseDownkeyUp如同mouseUp,要到keyUp才算一個點擊的動作,也就是到這時候才會去觸發click事件。

搞清楚這現象的原理之後,其實也就更容易理解WAI-ARIA Authoring Practices的範例那些 ENTERESCSPACE 幾個按鍵行為為什麼是那樣了,當然,以後需要客製 widget 時也不用再對這幾個按鍵的行為該怎樣定義苦惱了。


作動行為 Activation Behavior

前幾天全知全能的米奧大人在 Twitter 上徵求中階的 JavaScript 課程:

然後 Jedi 提供了一個題目:

後來米奧大人真的交作業了,也有提出一些問題,然後卡西有回應:

其中,「keyup 該觸發 button 上的 onclick」這句引起了我的興趣。

為了要顧及到網頁親和力,所有的控制元件的操作都應該要可以用鍵盤執行,所以像是 button 的動作也應該要可以用鍵盤控制,但是其實我以前一直搞不清楚,這之間正確的關係應該是怎樣,就三種可能性:

  • key 事件觸發 click 事件,click 事件有 default handler
  • click 事件觸發 key 事件,key 事件有 default handler
  • click 事件和 key 事件都有同一個 default handler

當我看到卡西那段文字的時候,我覺得他應該說的是有憑據的,不過我也覺得有些不正確,像是就我的認知,button 的 key 事件預設是不會觸發 click 事件的,於是我就花了點時間研究一下網路標準,這次終於找到規範和正確的關係了。

我先從 button 標籤開始查起,然後注意到一段,在說明 button 的activation behavior行為應該如何的文字,行為分成 submit button、reset button 和 button 三種,其中前兩個就像是在說 submit button 和 reset button 的行為一樣,所以我就了解到,activation behavior 就是我要找的關鍵字了,目前將它翻譯為「作動行為」。

然後在HTML 6.3 Activation找到:

Certain elements in HTML have anactivation behavior, which means that the user can activate them. This is always caused by aclickevent.

The user agent should allow the user to manually trigger elements that have anactivation behavior, for instance using keyboard or voice input, or through mouse clicks. When the user triggers an element with a definedactivation behaviorin a manner other than clicking it, the default action of the interaction event must be tofire aclickeventat the element.

第一段就是說作動行為(activation behavior)都是click事件觸發,第二段則是說瀏覽器要讓其它方法(像是鍵盤、語音操作等)可以觸發作動行為的話,實做的方法應該是在該事件的處理器(event handler)內觸發click事件來觸發該 HTML 元素的作動行為。這段文字就可以證明卡西說的基本上沒錯,另外就是我有疑惑的,應該是keydown還是keyup事件呢?根據我自己的實驗結果應該是要用keydown,不過總還是想找一下標準定義的出處,雖然沒有找到很明確的文字說明,不過UI Events 3.5. Activation triggers and behavior裡面的 EXAMPLE 4 內確實是寫 keydown event,當然keydown的時間點也比較符合期待,目前在不同標準文件內看到的範例也都是用 keydown。

查到這邊大概就可以確定,正確的關係應該是「key 事件觸發 click 事件,click 事件有 default handler」,不過卡西說的小錯誤是應該要用 keydown 事件,然後我在 twitter 有回說普通 button 不應該 keydown 觸發 click 則是我當時的錯誤認知(請見ENTER or SPACE, KEYDOWN or KEYUP)。

再來,其實我還很好奇,哪裡有定義不同的元素分別用哪些按鍵 active 呢?因為表單送出是用 ENTER 鍵,但是像是 checkbox 的狀態切換卻是用 SPACE 鍵;上面提供的幾份文件也都沒講到這部分的定義,有種刻意避開的感覺,後來又找了許久才終於找到,其實是放在 WAI-ARIA Authoring Practices 這份 Working Group Note 內,拿checkbox為例,在它的 Keyboard Interaction 段落內就明白寫了:

When the checkbox has focus, pressing the Space key changes the state of the checkbox.

當然也有button的規範,就是同時有定義spaceenter;由於這份文件是 Working Group Note,規範的硬性比較低,這應該也是故意為之的。

最後來整理一下,首先是 HTML 文件有定義,預設的作動行為都是透過click事件觸發,但是同時也要保留其它操作介面觸發作動行為的可能性,像是常見的鍵盤行為,而其它操作方式都要透過觸發click事件的方式來觸發作動行為;再來就是不同 HTML 元素的作動行為要做哪些事情也是在 HTML 文件內;至於不同 HTML 元素要支援哪些按鍵呢,這部分就要交叉參考ARIA in HTMLWAI-ARIA Authoring Practices兩份文件了,前者用來查詢 HTML 元素對應的 ARIA role,後者可以根據 role 來判斷要支援哪些鍵盤按鍵。

以後要做自訂的控制元件的時候,就可以正大光明的把主要的動作寫在 onclick 事件下了(然後根據情況去加上 key event)。


W3C and WHATWG and HTML

w3c-whatwg-logos

「天下大勢,分久必合,合久必分」,沒想到 W3C 和 WHATWG 之間的複雜關係就這麼突然的踏上新的里程碑了,今天 W3C blog 發表了一篇文章-W3C and the WHATWG signed an agreement to collaborate on a single version of HTML and DOM,說兩個組織已經簽好合作的協議了,未來算是要共同維護同一份 HTML 和 DOM 的 spec,HTML WG 的章程也因此要重新制訂,現在有草稿可看,詳細一點的摘要可以看 W3C CEO Jeff Jaffe 的文章 -W3C and WHATWG to work together to advance the open Web platform

  • W3C and WHATWG work together on HTML and DOM, in the WHATWG repositories, to produce a Living Standard and Recommendation/Review Draft-snapshots
  • WHATWG maintains the HTML and DOM Living Standards
  • W3C facilitates community work directly in the WHATWG repositories (bridging communities, developing use cases, filing issues, writing tests, mediating issue resolution)
  • W3C stops independent publishing of a designated list of specifications related to HTML and DOM and instead will work to take WHATWG Review Drafts to W3C Recommendations

基本上就是 W3C 相關的 WG 以後都改成貢獻到 WHATWG 那邊(在 GitHub 上),然後 W3C 那邊會拿 WHATWG 標準文件的 snapshot 來作為 CR、PR、REC,或許也可以稱為 Living Standard 的勝利。

如果要看比較細節關於兩個組織間簽的合作內容也有公開在網路上-Memorandum of Understanding Between W3C and WHATWG,裡面還有列出所有相關的 W3C 的標準文件,以前我就一直很好奇到底全部是有哪些,剛好趁這機會一次收集齊全,其實還不少我沒看過的,甚至也有 404 的(?),其中推薦標準(REC)的部分:

  1. https://www.w3.org/TR/html5/including other URLs under this directory
  2. https://www.w3.org/TR/html50/including other URLs under this directory
  3. https://www.w3.org/TR/html51/including other URLs under this directory
  4. https://www.w3.org/TR/html52/including other URLs under this directory
  5. https://www.w3.org/TR/html/including other URLs under this directory
  6. https://www.w3.org/TR/webstorage/
  7. https://www.w3.org/TR/webmessaging/
  8. https://www.w3.org/TR/eventsource/
  9. https://www.w3.org/TR/2dcontext/
  10. https://www.w3.org/TR/dom/

非推薦標準:

  1. https://w3c.github.io/html/including other URLs under this directory
  2. https://www.w3.org/html/wg/drafts/html/master/including other URLs under this directory
  3. https://www.w3.org/TR/websockets/
  4. https://www.w3.org/TR/2dcontext2/
  5. https://www.w3.org/TR/microdata/
  6. https://www.w3.org/TR/staticrange/
  7. https://www.w3.org/TR/workers/
  8. https://dvcs.w3.org/hg/webperf/raw-file/default/specs/RequestAnimationFrame/Overview.html
  9. https://w3c.github.io/dom/
  10. https://www.w3.org/TR/dom41/
  11. https://www.w3.org/TR/DOM-Parsing/
  12. https://www.w3.org/TR/html53/

這些東西在 WHATWG 那邊基本上都寫在HTMLDOM裡面,就是單一份標準文件內塞了比較多東西這樣。

最後就是我還發現一點有趣的,WHATWG投票那邊,四位出來投票的分別是 Apple、Microsoft、Mozilla 和 Google 四間公司的人。然後我只對 Mozilla 的dbaron有印象而已。


Lab Gradient

Gradient

一早起來就看到這篇文章視覺上的完美漸層 Chromatic,介紹了一個 Sketch plugin 可以用不同色彩系統的漸層來產生更好的視覺效果,之前其實也有注意到這個問題好幾次,就是覺得 CSS gradient 的效果不好,也有注意到一些其他的漸層方法,不過一直沒記錄下來,所以趁這時候把一些資源記錄一下,該篇文章的作者 Samuel 是推薦 Lab 色彩系統的漸層。

目前因為 CSS 就是只有 RGB 漸層,所以要用其他系統的漸層就只能用模擬的,SASS 的話有chromatic-sass,PostCSS 則是postcss-easing-gradients,這套背後用的則是首篇文章也有介紹的chroma.js來轉換的,不過它其實主要是在做 easing gradient 的,然後還有一些線上的模擬工具可以讓人直接看看效果,第一個其實是 easing gradient 的工具,其實就是在 easing gradient 標準提案時有人做來讓人體驗的,另一個介面比較不 fancy,但是我覺得比較實用的Lch and Lab colour and gradient picker


CSS 屬性排序

CSS Box

上週在弄Stylelint的設定,然後理所當然的處理到屬性排序的問題,以前我是用 CSScomb 的zen這組設定, 這組排序規則是從Zen Coding那邊來的,它的規則其實應該就是Concentric CSS的規則,concentric 是同心的的意思,同心圓的那個同心,這組規則的基本原則就是從外到內,從外部的定位、排版方式、到邊距、外框、內距、寬高等 box model 的屬性,然後才到內文的屬性,這組也是我第一次知道的有系統的 CSS 屬性排序規則,而且我覺得這個規則很直覺,而且也是很有邏輯的設計,所以就一直用到現在了。

最近這次要弄 Stylelint 設定時順便又研究了一下現在主流的排序規則,發現現在 lint tool 如果有內建排序規則的話,一定會有的其實是照字母順序排序,我自己是覺得在 CSS 領域照字母排序根本是 anti-pattern 啦,不過一直都有聽說有些大型企業的專案會用這種排序規則。事實上在 CSS-Tricks 的Poll Results: How do you order your CSS properties?的這篇文章,裡面就有 14% 的人是使用字母排序,當年還是 2012,2017 年 SitePoint 的調查結果其實沒有很大改變,變成 13%,所以雖然我覺得 anti-pattern 但其實還是有一定比例的人真的這樣用,其實要說的話也還是有好處啦,因為其它的屬性排序規則都是有個基本原則,實際上要仔細排列所有屬性的時候都還是有可能會有些地方有灰色地帶。

最高比例的排序方法則是照屬性類型分類,照屬性分類其實算是比較籠統的說法,Concentric CSS 的排序規則也算是照屬性分類的,同樣符合這樣條件的另外還有 Nicolas 的Idomatic CSS和 Jonathan Snook 的SMACSS的排序規則,其實這兩種方法的大方向也和 Concentric 的很接近,雖然是分成幾個大類別,但是大類別的排序基本上一樣是從外到內的方向,然後根據 npm 的安裝數字,目前使用度最高的應該是 SMACSS 的排序建議了吧,細部的完整排序可以在 Stylelint plugin package 的repo那邊看到。而除了 Stylelint 之外,PostCSS 也有 plugin 叫css-declaration-sorter來幫你排,也內建了Concentric CSSSMACSS,而且該 plugin 還號稱:

  • Up-to-date CSS properties fetched from theMDN Web Platform.
  • Thought-out sorting orders out of the box, approved by their authors.

感覺很不錯的樣子,它們的完整排序清單也可以在 repo 內找到:SMACSSConcentric CSS,不過排序這東西應該還是要在 lint 的時候做啊,PostCSS 的產出物通常是 production 環境用的 code 了,只是 stylelint 那邊用的排序清單和這邊的又不同,不過其實StylelintVSCode都可以拿 PostCSS 的來用的樣子,還沒測試過就是~

最後提兩個 Concentric CSS 灰色地帶的問題:

  1. Grid、 column、 flex、 float 這幾個屬性你會怎麼排呢~?
  2. 如果box-sizing: border-box;設下去後,width/height 要放在 padding 前面還後面呢?

SVG

SVG

最近網站的 icon 都盡量改用 SVG 向量檔了,網路上也有不少資源,像是Material Icons,累積了一些心得可以記錄一下,其實早在 GitHub 開使用 icon font 之前,大部分的瀏覽器就都有支援 SVG 了,只不過當時的支援還不夠完備,會各自有一些問題,這應該也是 Github 當年不先用 SVG,而是用 icon font 先檔了幾年的主因,總之現在比較不用擔心這些問題了,所以 GitHub 又開槍轉用 SVG icon 了。

GitHub 的用法是 inline SVG 為主,我自己則是用<picture>比較多:

<picture>
  <source srcset="/path/to/icon.svg" type="image/svg+xml">
  <img src="/path/to/icon.png" alt="" width="32" height="32" />
</picture>

CSS Trick 有一篇文章A Complete Guide to SVG Fallbacks則介紹了各種在網頁內放入 SVG 圖檔的古老方法,用<picture>是比較新的,沒列在其中,而我是為了向下相容選擇用<picture>,因為支援<picture>標籤的瀏覽器都很新了,對於 SVG 的支援度很夠,剩下少數(大概都是 IE)就讓他直接吃 png 之類的(PS: pngquant 處理過的 PNG 很多可以直接在 IE6 上顯示透明色),這樣用起來就像是一般<img>一樣,SVG 檔可以先用svgo工具處理過,除此之外,我通常會先用 Adobe Illustrator 把不必要的圖層階層刪除,圖層在 SVG 原始碼裡面通常是會<g>標籤,另外也記得要把圖層名稱(id)改成 ASCII only 的名稱,甚至直接編輯原始碼刪除 id,因為 svgo 不會處理這部分。

用外部 SVG 檔案好處是可以善用 browser cache 減少傳輸量,尤其是大量重複使用的圖片,不過也會犧牲一些 SVG 的特性,例如會因此不能直接用 CSS 來調整樣式,做 transition,做動畫等等,所以有時候也是會用 inline SVG,就可以搭配 CSS、JS 弄出很多不錯的效果(Safari 偶爾還有遇到無解 bug),不過要讓 inline SVG fallback 回一般圖片就比較麻煩些了,在做這件事之前可以先看一下是不是有需要支援,以前是 iOS 不支援,現在還有機會碰到的大概還是 IE(6-8)吧,總之,如果有需要的話,就是參考 CSS Trick 的SVG Fallbacks這篇文章,使用

<svg width="96" height="96">
  <image xlink:href="svg.svg" src="svg.png" width="96" height="96" />
</svg>

這是個很有趣的技巧,首先<image>標籤是合法的 SVG 元素,所以放在 SVG 不成問題,但是不支援 SVG 的瀏覽器,照理說也不應該認得<image>標籤啊,其實,<image>在很久以前就一直是<img>的別名了,甚至在 WHATWG 的 parse HTML 文件的流程裡都還有提到處理的方式,而經過測試也都證實了以前的瀏覽器確實是這樣的行為,文裡也有各瀏覽器的行為和支援狀況,不支援 inline SVG 的就會顯示替代的 png 或 jpg 。

文章裡面還有提到背景圖使用 SVG 的處理方式,不過因為我沒這樣使用,所以沒什麼實做到,另外最近也有人用外部 SVG 加上 CSS filter 來改變SVG icon 顏色,不過這太技巧太新了,考慮到支援度我也是沒有用過。

親和力問題的部分,一樣 CSS Tricks 有篇文章Accessible SVG在講相關的作法,像是用<title>加替代文字,加上role="img"等;如果要自己編寫 SVG,W3C 還有份Authering Guide可以參考,除了親和力相關的資訊外還有不少技巧可以參考。

最後整理一下,拿到 svg 檔案後我的處理過程:

  1. 用 Adobe Illustrator 先開來整理一下,修改圖層名稱、刪去合併不必要的圖層
  2. 輸出成 SVG 和 1x 解析度的 PNG
  3. SVG 檔用svgo最佳化、PNG 會用pngquantzopflipng處理過

使用方式則還是當成一般外部圖片為主,需要動畫效果才會用 inline SVG。


表單 Practice

Form Validation

這邊是我最近對於表單的一些作法,因為內化還不夠,每次都會漏掉一些,所以花了些時間整理整理,適合的情境不是 single page application 就是了,比較偏傳統形式網頁的表單,然後可能也包括不少大家早就知道(?)的細節就是了。

首先,我現在偏好不用 JavaScript 做表單檢查,而是先做好最基本的 server side 檢查,然後加上HTML5 的表單檢查,會這樣決定的主因是:

  1. JavaScript 的表單檢查 library 用起來都不太順手,而且不想花時間處理串接,且能少點 library 總是好的;
  2. 幾個常用的 type,像是 email, url 比較不需要擔心檢查的 pattern 有不周全的地方,我想很多人都有上網搜尋過這些欄位的 regular expression pettern 的經驗;
  3. 支援度已經不是大問題了,事實上我的工作上還需要支援 IE 10, 9 之類的,其實這些非 modern browser 的量都已經非常少了,所以就靠個 server side 檢查對付他們就好,使用體驗稍微差一點也還可以接受,這也是種 graceful degradation(優雅降級);
  4. HTML5 的表單檢查可以說是 web developer 當年對抗網路標準發展遲緩一大勝利指標,當然應該要好好用一下。

而用 HTML5 表單檢查還有個意外的好處是基本的錯誤訊息自動有翻譯(看使用者瀏覽器的語言),另外如果有自製的輸入元件,也有API可以串接,當然訊息就要自己提供就是了。

用 HTML5 表單檢查當然也不是完全沒有問題,例如目前 email 欄位還沒有瀏覽器支援IDN domain 的信箱;另外就是上傳檔案的 file input 的值不能從 server 端直接給,這限制是因為會有安全性問題,而這限制所衍生的問題是:表單送到 server side 檢查後發現有錯誤時(例如 captcha 錯),使用者就一定要重新選取上傳的檔案,對於使用者體驗算是個扣分(而且上傳檔案大的話很花時間,然後另外還有個上傳檔案大小限制、就又是另外一個議題了),要解決這問題一般來說就是靠 JavaScript 做些加強,例如針對 captcha 可以先用 ajax call 檢查 captcha ,正確的話就換個 session token 之類的回來,不過即使這樣,還是逃不了完整的 server side 表單檢查,所以也還要處理 ajax submit 後的表單錯誤訊息顯示。

不管是 server side 檢查後產生的錯誤訊息,還是 ajax call 之前檢查產生的錯誤訊息,理所當然都會放在欄位附近,不過還要讓訊息和欄位之間建立關聯,才好進一步做一些處理,例如使用者有更新欄位值之後會把錯誤訊息隱藏之類的,或許很多人會用父層 DOM 節點加上特殊的 class 包起來找,不過我比較偏好用aria-describedby,大概會看起像是:

<input id="mail" name="mail" type="email" aria-describedby="mail-field-info" />
<span id="mail-field-info">Required field!</span>

這樣只要找的到#mail欄位,就可以透過他的aria-describedby屬性找到該欄位的相關訊息的 DOM 節點,另外值得注意的是,aria-describedby 值的格式是IDRefList,不是單一個 ID,而是一個用空白切分的 ID 指標們,所以如果有這種情形,還可以在錯誤訊息的那個 DOM 節點加上role="alert"給它用來辨識,其實就算只有一個 ID 也還是可以加上 role 屬性啦。如果真的需要用透過父層 DOM 節點來找的話,之前研究的結論是可以在預期的父層標籤用role="section"來方便定位,用 jQuery 大概會像是:

$fieldSection = $field.closest('[role="section"]');

這個標籤下應該會包括欄位的標籤(label)、欄位的 input element 以及相關的資訊(說明、錯誤訊息)等。

另外還有一點,就是要用 ajax 上傳檔案的話,需要有支援FormData的瀏覽器,並且如果用 jQuery 送 FormData 的話記得要加點設定:

contentType: false,
processData: false

還有就是 ajax 送表單的目標 URL,我目前比較喜歡的作法是讀<form>action屬性,也就是和瀏覽器自己送的 URL 一樣,然後透過 HTTP content negotiation 機制來決定回傳的格式,比較正確的作法是看Accept,以 jQuery 來說,如果要 server 回 JSON 格式的話,可以加上:

dataType: 'json'

這樣送出的 request 就會帶上正確的Acceptheader,向 server 端要求application/json,不過Accept的值解析起來比較麻煩些,其實是可以送出說 client 端可以接受多種格式,然後還加上個優先度的,也因此也有很多人是看X-Requested-With,一般 library 如果是透過 XHR 發的 request 都會有這個 header;還有就是送出的資料格式(Content-Type),即使是 ajax call,我目前也都不用 JSON 了,還是用application/x-www-form-urlencoded為主,另外要上傳檔案的話當然一定要用multipart/form-data,主要是因為:

  1. 送 JSON 的話就不會是simple request了,有些時候會比較麻煩,例如 Cross Origin 時會需要發 preflight,然後就可能遇到 AWS 以前不支援 preflight request 的 bug;
  2. 用這幾個老的 Content-Type 支援度還是比較高,對於 server 端實做和 client 端實做其實都相對友善一點,例如 jQuery 預設就依然是 form-urlencoded,没特别需求還是用標準一點的格式,特殊需求是例如 GraphQL,不過一般表單發送應該不會走 GraphQL 吧。

其實 JSON 雖然已經有 RFC 規範了,不過在 Web 標準的世界還沒相當深入內化,不知道以後有沒有機會更加的內化整合進去。

前面有提到 ajax call 送出的目標 URL 我會偏好從,<form>裡面讀,不過或許有的情境會讓 ajax call 必須要自己用不一樣的 API URL,這時候我建議還是把 API URL 寫在<form>的屬性裡面,這樣可以讓 JavaScript 的邏輯比較乾淨,也不用作什麼 mapping 或是常數來儲存 API 的 URL,維護修改時也不用兩邊檢查,屬性名稱可以用例如:data-action之類的屬性,data-*屬性正好適合來做這些事情,不但有 DOM API 支援,jQuery 也可以用.data()method 來讀取,命名上,如果覺得有個標準參考比較好,可以看看jQuery-ujs的設計,雖然比較長一點,它用的是:data-ujs:submit-button-formaction,我是覺得有些不正確啦,畢竟要送出表單不一定是點擊 submit button。

其實假設送出表單的動作都是滑鼠點擊 submit button 這是個親和力問題,如果只把 ajax call 送的函式 bind 在 submit button 的 click 事件上,這其實是不太好的,因為其實瀏覽器預設的行為是可以在很多地方用鍵盤送出表單,例如在 text input 上按下 Enter 鍵,或是在 submit button 上按下空白鍵之類的,所以針對表單還是要去 bind form submit 事件才是正解,至於 jQuery-ujs,其實也是這樣做的,它是用 delegate event 的形式去監聽傳遞到 document 上的 submit 事件,然後才去做後續的處理,只是命名上讓人覺得不太正確。

最後一項,前面說不用 JavaScript 做表單檢查(不看自訂輸入元件的話),其實有一個例外,就是上傳檔案的大小檢查,因為沒做對使用體驗的影響比較大,然後就是要還要記得針對 ajax call 送表單加上HTTP 413Status Code 的錯誤訊息處理。


Graceful Degradation Background

Rockman

昨天解了一個其實困擾蠻久的問題,就是在蘋果開始支援 Retina Display(HiDPI)之後,網站上使用的圖片也跟著要提升解析度,一般網頁會使用的圖片基本上就是<img />標籤的圖片和用 CSS 設定的背景圖,對於<img />標籤來說,提供高解析度的圖片並不會有向下相容的問題,當然瀏覽器和作業系統不支援的,抓了比較大的圖下來是比較浪費,也為此有<picture>標籤、srcset屬性和Client Hints等標準來處理這個問題,不過我的需求只要圖片都能正常且正確的顯示。

<img />標籤只要有設定寬高,圖片顯示出來就會是預期的大小,但是background-image就不是了,在background-size出來前,背景圖多大,它在網頁上就會照那樣的尺寸下去畫,所以在不支援background-size的瀏覽器(IE6-8)上用 HiDPI 的背景圖就會很悲劇,雖然可以用 media query 來處理,不過解析度相關的 media query,如果要考慮到以前的瀏覽器,變化有點多,從早期的 device pixel ratio 到 dppx 到現在 resoulution 用的 dpi,還要加上 vendor prefix,自己寫起來有點痛苦,而且原始碼變醜很多,當然,如果有用 PostCSS 就可以用 autoprefixer 解決,不過其實我不太喜歡寫 Media Query,所以都是能少則少(針對 CSS 的 polyfill 也是不太喜歡用),並且有些舊的專案沒有 PostCSS,所以就一直有這個問題,以前的處理方法就是幾種:

  • 真的寫 Media Query
  • <img />標籤模擬背景圖,也很麻煩(也可以用 polyfill,不過個人不想用)
  • 大家一起用標準解析度的圖

這些方法對我來說都算是 workaround 的方式,一直想找個漂亮乾淨一點的解法,直到昨天終於想到了,首先整理一下我的需求:

  • 可以有兩張圖不同解析度的圖
  • 不要用 Media Query
  • 有機會支援 HiDPI 的環境就用 HiDPI 的圖
  • 舊瀏覽器顯示正確

其實這些需求可以簡化成:**不支援background-size的就乖乖看低解析度的圖片吧**,其中隱含著一個現實狀況是,不支援background-size的瀏覽器都只能在不支援 HiDPI 的環境下跑,實做上基本的構想是先寫好一個基本背景的定義,然後再加上一個只有新瀏覽器看的懂得定義,這構想有了很久,卻到昨天才想到怎麼寫,結果如下:

background: #123456 url('the-bg.png') center center;
background: #123456 url('the-bg@2x.png') center center/32px 32px;

用了background可以把全部背景相關屬性寫在一起,而且如果解析失敗就整條失效的特性,以前因為我都會background-size單獨寫(有另外的原因),這種寫法就落入我的盲區,所以過了這麼久才想到,不過這方法不是萬能,還有些限制和使用時機:

  • 有需要支援 IE6-8 才需要,IE9 以上就有支援background-size
  • 不考慮 HiDPI 時其實不需要background-size,例如固定大小區塊的背景、用背景的 icon、有重複排列的背景等
  • background-size: cover;依然需要靠 polyfill 之類的來處理

想出來之後,有開了 IE8 來測試,結果一如預期,這樣應該是 IE6-7 也會正確吧。


Acclerated Mobile Pages

O2 DAC + AMP,

Acclerated Mobile Pages簡稱 AMP,是 Google 所推出,為了提升行動網路體驗的一個專案,我一開始對於這種(看似)偏離網路標準的方案其實不太有興趣,不過在瞭解其技術原理後,覺得相當有趣,而且其實沒有想像中的偏離標準,整個架構也比 Facebook 的 Instant Article 還要來的開放,雖然我覺得這個解決方案(只說是 Framework 或是 Library 都不夠完整),其實只算是個暫時的解法,但是 AMP 本身的實做方式,其實是架構在一堆網路標準的發展之上的,相當出人意料,可以說是Extensible Web 宣言以來,第一個重要的里程碑。

閱讀「Acclerated Mobile Pages」全文

Modern HTML Email Development

今天在 Modern Web 分享的主題

其實最主要是想介紹MJML這個工具,不過最後介紹的篇幅有些不夠,有些可惜,話說今天設備也有些狀況,一是投影機解析度和預期的不一樣,二是無線麥克風聲音會延遲,對於講者來說還蠻干擾的,最後時間還剩的比預期多,覺得愧疚啊。

最後附上這次介紹的一些資源的連結,方便取用:


此類別所有文章