以前作了一個網頁,網頁中的全部輸入框都被設計爲「得到鼠標焦點時外邊框不變藍」。忽然某一天,產品以爲這樣用戶體驗很差,不能很明顯地告訴用戶當前鼠標停在哪裏,因而要求改成「當輸入框得到鼠標焦點時,外邊框自動變藍;失去焦點時外邊框恢復原樣」。php
瀏覽器自動會給輸入框input
、textarea
的outline
屬性設置一個默認值,效果就是當輸入框得到鼠標焦點時外邊框會自動帶上顏色,失去焦點時外邊框顏色消失。因爲不一樣瀏覽器outline
屬性的默認值不一樣,致使外邊框的顏色也不一樣。若是不想要瀏覽器的outline
默認設置,只須要將 outline
屬性設置爲none
便可。css
因此一開始聽到這個需求,感受特別簡單,不就是純 CSS 的問題嘛!我只要將全部輸入框的 outline
屬性設置爲瀏覽器默認的值就行了,但我想的太天真了。。。。web
因爲網頁中已有的輸入框的樣式遍及在各個文件中,有一種很是機械的辦法,那就是到每一個文件中去刪除掉輸入框的 outline:none
樣式,這樣輸入框就會使用瀏覽器默認的 outline 樣式了。可是這樣作要改的地方太多了,會瘋掉的!再想一想有沒有更省事的方法,有了!在最基本的base.css
樣式文件中給輸入框添加一個focus
時候的outline
樣式不就解決了麼。那麼問題來了,該將outline
設置何值,才能自動使用瀏覽器默認的outline
樣式呢?瀏覽器
我第一個想到的方法是將 outline
設置爲auto
,但發現只有webkit 內核的瀏覽器才支持這個屬性值,firefox 不支持,由於auto
並非標準的outline
值。因此要想直接複製瀏覽器默認的outline
樣式是作不到的。難道我要針對每一個瀏覽器設置不一樣的outline
值,爲了這麼一點破需求費那麼大工夫?!算了,省事點的方式仍是直接摒棄瀏覽器的默認outline
樣式,統一將outline
設置爲一種樣式好了。函數
但我發現了新問題,經過設置outline
樣式爲輸入框添加外邊框,效果並很差。由於 outline
沒有相似 border-radius
的屬性來改變邊角的弧度。這樣就致使了一個問題:當輸入框設置了border
顏色,同時border-radius
爲3px
以上時,能明顯的看到outline
外邊框並無和border
重合。看來設置 outline
來達到邊框變藍效果並非最好的選擇,爲何不選用設置 border
來達到一樣的效果呢?只要將border
再設置下 border-shadow
,那麼看起來也是和outline
效果同樣的,並且border
還能設置border-radius
,顯示效果更知足需求。firefox
經過設置 border 解決了大多數輸入框,但發現又有了新問題。設計
網頁中有些輸入框其實並非單一使用 input
/textarea
來實現的,這類「輸入框」看起來和通常輸入框並沒有兩樣,但其實 HTML 結構是一個 div
裏面包含着一個 input
/textarea
來實現的。並且輸入框的邊框設置在了父元素 div
上,全部當輸入框得到焦點時,看到的應該是父元素 div
上的邊框變藍,而不是裏面的input
/textarea
的邊框變藍。code
要想得到焦點時父元素 div
的邊框變藍,確定可行的方法是經過 JS 來實現:給input
/textarea
綁定一個 focus
和 一個blur
事件,在focus
事件處理函數中將父元素div
的邊框置藍,在blur
事件處理函數中將父元素div
的邊框恢復原樣。這種方法時絕對可行的,可是我總以爲應該有更簡單的,純粹使用 css 實現的方法。orm
若是想單純經過css 實現,首先想到的是用選擇器div:focus
。可是發現div
上沒法使用:focus
僞類。因而我就猜測:可能並非全部的元素都是 focusable的,那麼得找一份說明哪些元素 focusable的規範。事件
搜索結果:
根據 DOM Level 2 HTML規範,focusable 的DOM元素都會有一個原生的focus()
方法,只有 focusable 的DOM 元素纔有 focus 事件,才能使用:focus
僞類。擁有原生的focus()
方法的DOM元素包括幾種:HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement and HTMLAnchorElement。很明顯,規範中遺漏了HTMLButtonElement and HTMLAreaElement。
雖然規範這麼定義,但瀏覽器在實現時倒是另一套。瀏覽器給任何一個 HTMLElement 都定義focus()
方法,但並非任何一個HTMLElement 都能得到焦點(得到焦點術語叫 active, 具體請參考:http://help.dottoro.com/ljqmdirr.php)。通常來講,任何一個時刻HTML 文檔中只會有一個active元素,但並非任何一個元素都能成爲active元素。能成爲active 的元素包括:
表單元素(form controllers):input/option/textarea/button
連接元素(links):a
標籤、area
標籤(必需要帶 href
屬性,包括 href
屬性爲空)
能夠被編輯的元素(包括經過添加 contenteditable = "true"
屬性變成可編輯的狀況)
設置了 tabindex
屬性(tabindex
值非-1)的元素
window
:當頁面窗口從隱藏變成前置可見時,focus
事件就會觸發
根據搜索結果,要想將父元素div
變成focusable,只須要在元素上設置 tabindex 屬性,而後經過:focus
僞類設置父元素div
得到焦點時的border
樣式。但我發現當鼠標點擊裏面的 input
元素時,父元素div
並無得到焦點,得到焦點的是子元素input
。
因此最後仍是沒能經過純 css 的方法來解決這個問題,無奈之下我仍是經過js去解決了。。。。。。