處理粘性的4種新方法:在移動設備上懸停效果

CSS的古老之處:懸停僞類構成了許多CSS效果的支柱,當鼠標滾過頁面上的元素時觸發。在當今不斷變化的環境中,觸摸屏輸入與鼠標共享中心舞臺,這給網站管理員帶來了一些難題。基於觸摸的設備努力不被冷落,這種普遍的CSS功能確實可以響應懸停,但是對於它們來說唯一可行的方式是“點擊”而不是實際的“懸停”。雖然這總體上是一件好事,但它會導致這些設備上所謂的“粘滯懸停”問題:hover樣式與用戶剛剛點擊的元素保持一致,直到他/她再次點擊文檔中的其他位置,或者在某些情況下,在效果被取消之前重新加載頁面。這種“永遠在線”的懸停效果在某些情況下是良性的,但對其他人的用戶體驗是有害的甚至是有害的。例如,頁面上的一組“volumn”按鈕具有“懸停”效果,可以改變鼠標用戶的背景顏色,當鼠標滑過按鈕時,效果會通知用戶按鈕可以與之交互,但是觸摸設備背景顏色“粘在”按鈕上的按鈕,它誤導用戶認爲單擊一下後音量不斷增大或減小。

在本教程中,我們將介紹4種不同的方法來禁用或修改:hover移動設備上的默認效果,以便跨平臺提供更好的用戶體驗。我們將從最保守的方法開始,然後再投入更加雄心勃勃的事情 ,同時考慮支持觸摸屏和鼠標/觸摸板輸入和實時的混合設備。讓我們滾動。

方法1-有條件地將“ non-touch”CSS類添加到文檔根元素

首先,一種保守的方法:hover,通過non-touch在設備被視爲不支持時向根<html>元素添加任意CSS類(即:“ ”),將CSS 樣式限制爲所謂的基於鼠標的設備(即:桌面)。觸摸”。一個COM週一方法是使用JavaScript來作出這樣的判斷:

1

2

3

4

var touchsupport = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)

if (!touchsupport){ // browser doesn't support touch

    document.documentElement.className += " non-touch"

}

non-touch現在只有在使用JavaScript測試觸摸支持時返回false的設備的“ ”類,我們:hover纔會修改相關樣式以僅定位這些設備:

1

2

3

html.nontouch nav a:hover{ /* hover effect only visible to devices that report back as not supporting touch */

    background: yellow;

}

這種方法簡單而簡潔,但並非沒有缺陷。準確地檢測觸摸支持是非常困難的使用當前瀏覽器的API,並且將存在這樣的情況:不支持觸摸的瀏覽器(或反之亦然)將報告相反的情況。然而,總體而言,這種方法確實達到了“足夠好”的門檻,其中:hover 效果不會影響用戶體驗 - 無論是橫向還是負面 - 無論如何都要跨平臺。

方法2-有條件地將“ can-touch”CSS類添加到文檔根元素

與第一種方法相反,這種方法可以讓您:hover單獨保留原始樣式,而是:hover 針對觸摸設備製作定製 樣式。我們將利用JavaScript的“ touchstart”事件,當用戶與啓用觸摸的設備上的屏幕進行聯繫時調用該事件,首先實時確定設備確實支持觸摸輸入,然後再將“ can-touch”類添加到文檔根元素。

1

2

3

4

6

<script>

document.addEventListener('touchstart', function addtouchclass(e){ // first time user touches the screen

    document.documentElement.classList.add('can-touch') // add "can-touch" class to document root using classList API

    document.removeEventListener('touchstart', addtouchclass, false) // de-register touchstart event

}, false)

</script>

用戶第一次觸摸屏幕時,CSS類“ can-touch”被添加到根元素,表示設備是基於觸摸的。我們使用classList API- 它在移動瀏覽器上享有極好的支持 - 更優雅地將類添加到元素中。爲了防止動作超出一次,我們立即從事件中取消註冊已分配的功能。

通過此設置,我們可以:hover正常定義我們的初始樣式,然後在觸摸設備之後撤消或修改它,例如:

1

2

3

4

6

7

8

9

10

11

12

ul li a{

    padding: 10px;

    display: block;

}

 

ul li a:hover{

    background: yellow;

}

 

html.can-touch ul li a:hover{

    background: none; /* disable hover effect on touch devices */

}

這種方法可以說比分離觸摸和非觸摸設備的第一種更準確,儘管它確實需要用戶在它開始之前先觸摸屏幕。爲了處理 :hover按需發生的效果,它可以工作,儘管取決於正常和“可以觸摸”之間的樣式差異:懸停類,頁面佈局的短暫轉換可能會發生,因爲後者應用於頁面按需。此外,請注意,所有移動瀏覽器都不支持觸摸事件,如“ touchstart” ,IE和Firefox移動顯然是其中兩個。

方法3-使用CSS媒體查詢級別4交互媒體功能

CSS Media Queries Level 4增加了對識別用戶輸入設備功能的支持。出於我們的目的,我們對“ pointer”和“ hover” 感興趣,它告訴我們用戶主要輸入設備的精確程度以及它支持懸停的程度。查看以下CSS媒體查詢以及它們有助於隔離的輸入設備類型:

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@media (pointer:coarse) {

    /* Primary Input is a coarse pointer device such as touchscreen or XBox Kinect etc */

}

 

@media (pointer:fine) {

    /* Primary Input is a fine pointer device such as a mouse or stylus */

}

 

@media (hover:none) {

    /* Primary Input doesn't respond to hover at all, even partially (ie: there is no pointing device) */

}

 

@media (hover:on-demand) {

    /* Primary Input responds to hover only via emulation, such as touch screen devices */

}

 

@media (hover:hover) {

    /* Primary Input responds to hover fully, such as a mouse or a Nintendo Wii controller */

}

例如,您可以:hover 在媒體查詢(@media hover:hover{})中定義常規樣式,以將它們限制爲:hover完全支持的設備(配備鼠標或某些指針設備的設備):

1

2

3

4

@media (hover:hover) {

    nav a:hover{

        background: yellow;

    }

}

或離開你原來的更加漸進的方式 :hover風格不變,目標不支持設備的 :hover pletely:

1

2

3

4

@media (hover:none), (hover:on-demand) {

    nav a:hover{ /* suppress hover effect on devices that don't support hover fully

        background: none;

    }

}

所有上述邏輯也可以使用JavaScript打包 ,例如:window.matchMedia()

1

var nofullhover = window.matchMedia("(hover:none), (hover:on-demand)").matches //returns true or false

雖然你可能認爲你已經到達了檢測:hover支持的聖盃 - 使用CSS Media Queries Level 4-但現實並未完全符合其潛力。首先是媒體查詢4級交互媒體功能的不穩定瀏覽器支持。目前沒有Firefox瀏覽器(最高爲FF 50)支持它,這幾乎使得這種方法在該領域的改進之前不切實際。其次,媒體查詢4級交互媒體功能的當前規範在我看來對前兩種處理方法提供的優勢很小:hover跨平臺的行爲,除了它的優雅和沒有JavaScript依賴。所有3種方法,無論它們在檢測觸摸還是無觸摸支持方面都是準確的,都忽略了一種越來越受歡迎的設置,其中該設備同時支持觸摸屏和鼠標/觸控板。在這種情況下,上述檢測方案中沒有一個能夠實時確定用戶 當前正在使用哪個輸入,而是僅在將設備報告爲“觸摸”時僅查看他們認爲是設備的主要輸入的內容。 “或”沒有觸摸/鼠標“。這意味着在大多數情況下,具有觸摸和鼠標輸入的筆記本電腦將始終作爲觸摸設備進行歸類,有時根據具體設置,“鼠標”設備, :hover無論用戶當前使用什麼輸入,相關的樣式只能滿足其中一個輸入。這顯然是一大短COM ING,一個通向下面我最後的檢測方法。

方法4- can-touch根據當前用戶輸入類型動態添加或刪除“ ”類

對於這最後的方法,我把它視爲挑戰 é了一種方法來確定用戶是否使用了實時地觸摸或鼠標/觸控板基於輸入。如上所述,到目前爲止我們看到的所有先前檢測方法在判斷用戶當前使用的輸入類型時都是靜態的; 當面對支持觸摸和非觸摸輸入的混合設備以及用戶可以隨時在這些輸入之間切換的事實時,就像他們所說的那樣,“休斯頓我們遇到了問題”。目前所有可用的瀏覽器API只能告訴我們用戶設備支持的輸入類型而不是他/她目前正在使用的輸入類型,現在是時候進行一些越野編碼以試圖規避這種限制。

實時檢查用戶輸入類型背後的基本思想很簡單,魔鬼就是細節。我們已經擁有上面方法2中的一半神奇公式,我們轉向JavaScript的“ ontouchstart”事件處理程序,以便在用戶與屏幕進行聯繫時通知(因此當時正在使用觸摸)。但是當用戶切換到鼠標/觸控板時呢?第一個想法自然就是參加JavaScript的鼠標相關事件之一 - “ mouseover”,“ mousemove”,“ mouseenter”等 - 以幫助我們撥打電話,但是一旦你意識到觸摸屏設備也響應鼠標事件,那麼興奮是短暫的(很像CSS:hover每當用戶點擊屏幕時,就會侵蝕觸摸設備上所有這些事件之間的區別。

因此,顯然試圖告訴鼠標事件是由實際鼠標/觸控板觸摸何時觸摸觸摸屏上的觸摸要比看到它更難,儘管一切都沒有丟失。我發現當在頁面上註冊了“ touchstart”和鼠標事件(如“ mouseover”)時,當用戶觸摸屏幕時觸發的兩個事件的順序始終是前者,後面是後一個事件:

1

2

document.addEventListener('touchstart', functionref, false) // on user tap, "touchstart" fires first

document.addEventListener('mouseover', functionref, false) // followed by mouse event, ie: "mouseover"

我們可以利用這個可預測的事件序列來區分文檔上的實際觸摸與實際鼠標懸停(即:在混合設備上),通過在發射時暫時阻止第一個事件阻止第二個事件來指示這是觸摸事件,過濾掉真正的鼠標懸停事件。讓我們來看看這一切是如何COM上課共同創造的代碼,動態添加或刪除“ can-touch”類文檔根目錄,以反映此時的用戶的當前輸入類型:

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

三十

<script>

 

;(function(){

    var isTouch = false //var to indicate current input type (is touch versus no touch)

    var isTouchTimer

    var curRootClass = '' //var indicating current document root class ("can-touch" or "")

     

    function addtouchclass(e){

        clearTimeout(isTouchTimer)

        isTouch = true

        if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present

            curRootClass = 'can-touch'

            document.documentElement.classList.add(curRootClass)

        }

        isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event

    }

     

    function removetouchclass(e){

        if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present

            isTouch = false

            curRootClass = ''

            document.documentElement.classList.remove('can-touch')

        }

    }

     

    document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch

    document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad

})();

 

</script>


嘗試一下現場演示以上在桌面上,觸摸設備和混合設備,看的CSS如何:hover影響是每當觸摸用於與鏈接交互,但活躍起來,如果鼠標或觸控板來代替上課處於休眠狀態。讓我們分解它的工作原理:

  • 我們在文檔上註冊兩個事件“ touchstart”和“ mouseover”,以便在用戶與頁面交互時捕獲兩種類型的事件。

  • 在非觸摸設備(如桌面)上,只會mouseover觸發“ ”事件。removetouchclass() 雖然什麼都不做,但調用該函數,因爲isTouch和 curRootClass變量將始終分別爲false 和""(空字符串)。換句話說,沒有“ can-touch”類被添加到文檔中。

  • 在觸摸設備(包括用戶當前正在使用“觸摸”時的混合設備)上,觸摸時觸發“ touchstart”和“ mouseover”事件,前者隨後觸發。

  • 每當用戶觸摸屏幕時,調用函數 addtouchclass()isTouch 變量設置true爲在將“ can-touch”CSS類添加到面向根之前將當前輸入類型指示爲觸摸。爲了防止removetouchclass() 在同一個觸摸操作期間調用函數並撤消剛剛完成的操作,我們添加以下行以 addtouchclass() isTouch變量的狀態保持爲真500毫秒:

    isTouchTimer = setTimeout(function(){isTouch = false}, 500)

    使用上面的關鍵代碼行,當removetouchclass() 也嘗試緊跟在“ touchstart”之後運行(因爲觸摸設備也響應鼠標事件),它被阻止,因爲此時的值isTouch仍然爲真。不久之後,isTouch變量將自身重置爲false在每次觸摸動作之後再次確保在使用觸摸輸入後isTouch不會永久停留在該 true狀態,並且如果用戶之後切換到它(例如在混合設備上),則可以繼續對可能的鼠標/觸控板輸入作出反應,然後打電話removetouchclass() 。

所有這些最終導致can-touch在文檔中實時添加或刪除“ ”類以反映用戶當前正在使用的輸入設備。從我的測試,似乎整個每臺設備我把它那可預見的工作支持JavaScript觸摸事件,但留下一個 COM下面包換,如果你發現,否則。

 結論

在本教程中,我們研究了4種不同的方法來解決:hover移動設備上的棘手問題,從不同的角度進行,以檢測用戶的輸入設備何時觸摸與非觸摸。直到觸摸設備支持實際懸停(可能使用相機檢測手指何時在元素上徘徊),它們允許我們在 不同平臺上創建更好的體驗,具有不同程度的準確性和易於實現。在許多情況下,它比什麼都不做要好。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章