利用HTML5,無JS實現各類交互效果

本文利用的是HTML5 details, summaryjavascript

首先前端

1、瞭解HTML5 details, summary默認交互行爲java

<details> 標籤在Chrome,Firefox等瀏覽器下默認是有展開收起行爲的,例以下面HTML:web

<details>

    <summary>這是摘要1</summary>

    <p>這裏具體描述,標籤相對隨意,例如這裏使用的&lt;p&gt;標籤。</p>

</details>

複製代碼

結果UI表現爲:瀏覽器

details標籤默認效果截圖

具體描述爲:bash

  1. 只顯示了<summary>標籤內容,而<p>默認隱藏了;
  2. <summary>標籤前面出現了一個小三角;

小三角圖形的隱喻是:我是可點擊的,點擊我可能會出現寶箱。框架

OK,咱們不妨就點擊一下,結果以下圖:ide

image.png

具體描述爲:svg

  1. 本來隱藏的<p>標籤顯示出來了;
  2. <summary>標籤前面的小三角方向朝下了;

此時咱們再一次點擊,<p>標籤內容又會隱藏收起,箭頭方向還原,以下圖:學習

image.png

活脫脫一個自然的展開收起效果。

展開與收起是經過open屬性控制的

經過在<details>標籤上添加布爾類型的open屬性,可讓咱們的詳情信息默認就是展開狀態,以下HTML示意:

<details open>
    <summary>這是摘要2</summary>
    <content>這裏&lt;details&gt;標籤設置了HTML布爾屬性open,所以,默認是展開狀態。</content>
</details>

複製代碼

結果以下截圖:

open屬性下的信息默認展開

若是咱們使用JS腳本手動移除這個open屬性,即便沒有點擊行爲的發生,咱們內容也會收起。

若是缺省

<summary>標籤若是缺省,則<details>元素會在內部自動建立一個<summary>內容,默認的文案是「詳細信息」。以下HTML代碼:

<details open>
    <p>若是&lt;summary&gt;缺省,則會自動補上,文案是「詳細信息」。</p>
</details>

複製代碼

結果以下截圖所示:

summary 詳細信息佔位示意圖

2、details瀏覽器內置UI能夠自定義

<details>標籤默認的小三角樣式有些簡陋,在實際應用的時候,每每不是咱們但願的樣子,不要擔憂,咱們是能夠對其進行自定義的。在Chrome等瀏覽器下使用::-webkit-details-marker,在Firefox瀏覽器下使用::-moz-list-bullet能夠對小三角進行UI控制,例如改變顏色,改變大小,使用自定義的圖形代替,或者直接隱藏等,咱們來看幾個簡單的案例。

案例1:小三角右側顯示同時顏色變淡

HTML代碼以下:

<details class="details-1" open>
    <summary>這是示例1</summary>
    <content>本案例展現對小三角UI重定義:包括顯示在右側,顏色減淡等。</content>
</details>

複製代碼

CSS以下:

.details-1 summary {
    width: -moz-fit-content;
    width: fit-content;
    direction: rtl;
}
.details-1 ::-webkit-details-marker {
    direction: ltr;
    color: gray;
    margin-left: .5ch;
}
.details-1 ::-moz-list-bullet {
    direction: ltr;
    color: gray;
    margin-left: .5ch;
}

複製代碼

結果以下圖所示:

三角位置和顏色示意

當咱們點擊摘要標題升起的時候,表現爲下圖(截自Firefox):

三角收起效果

而實際上實際開發的時候,對小三角UI更便捷的定製方法是:隱藏瀏覽器原生的小三角,而後藉助::before或::after僞元素從新生成咱們想要的UI效果,下面這個案例就將展現相關的處理。

案例2:隱藏瀏覽器原生的小三角並使用自定義三角替換

HTML結構仍是相似的:

<details class="details-2" open>
    <summary>這是示例2</summary>
    <content>本案例隱藏原生小三角,使用自定義小三角。</content>
</details>

複製代碼

CSS主要分爲2部分,一部分是隱藏瀏覽器原生的小三角,另一部分是使用僞元素生成自定義的三角效果。

首先看一下隱藏<details>標籤默認的小三角的CSS:

/* 隱藏默認三角 */
.details-2 ::-webkit-details-marker {
    display: none;
}
.details-2 ::-moz-list-bullet {
    font-size: 0;
}

複製代碼

能夠看到Chrome瀏覽器和Firefox瀏覽器的小三角隱藏採用的是不一樣的策略。在Chrome瀏覽器下,咱們能夠直接設置display:none進行隱藏,可是這一招在Firefox瀏覽器下確實沒有效果的,即便設置display:none!important也是如此,根據個人測試,只有font-size:0可以比較完美的隱藏。相似position:absolute;visibility:hidden這種常見的隱藏也是不行的,由於position:absolute沒法生效。

而後是自定義小三角顯示的CSS,這裏採用的是::after僞元素模擬的:

/* 自定義的三角 */
.details-2 summary::after {
    content: '';
    position: absolute;
    width: 1em; height: 1em;
    margin: .2em 0 0 .5ch;
    background: url(./arrow-on.svg) no-repeat;
    background-size: 100% 100%;
    transition: transform .2s;
}
.details-2:not([open]) summary::after {
    margin-top: .25em;
    transform: rotate(90deg);    
}

複製代碼

最終效果以下圖所示:

自定義三角效果截圖

收起時候:

收起時候效果


最後有一點須要注意一下,就是若是<details>標籤內並無<summary>元素,則咱們的對三角的自定義代碼都是無效的,可使用一個空的<summary>元素佔位,相似這樣:

<details>
    <summary></summary>
    <content>內容。</content>
</details>
複製代碼

3、Chrome瀏覽器下點擊時候outline輪廓等體驗處理

UI能夠定製了,可是還有個不容忽視的體驗問題,那就是在Chrome瀏覽器下點擊時候會出現outline輪廓,以下圖所示:

Chrome下的outline輪廓

在實際項目開發的時候,產品和設計必定會讓你把這個效果去掉的。以及,當咱們<summary>元素點擊較快的時候,文本會被選中,也不是咱們想看到的。

阻止文本選中,咱們能夠:

summary {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

複製代碼

對於outline輪廓,比較直接的作法是:

summary {
  outline: 0;
}
複製代碼

可是這樣處理對無障礙訪問而是很是不友好的,那有沒有什麼辦法兼顧視覺體驗和無障礙訪問體驗呢?

個人作法是這樣子的:

  1. 利用標籤的outline交互體驗 瀏覽器對標籤元素的outline輪廓進行了專門的體驗優化處理,鼠標點擊的時候不顯示輪廓,鍵盤訪問時候顯示輪廓。因而咱們可採用李代桃僵策略,讓元素的outline交給元素,方法就是在中再內嵌一個,同時經過tabindex屬性remove掉本來的可訪問性。HTML代碼示意以下:
<details open>
    <summary tabindex="-1"><a href="javascript:">這是示例</a></summary>
    <content>點擊無外框,鍵盤focus有。</content>
</details>

複製代碼

CSS以下:

summary {
    user-select: none;
    outline: 0;
}
summary a {
    color: inherit;
}

複製代碼

此時,在Chrome瀏覽器下,咱們點擊摘要信息,沒有任何outline輪廓出現;可是當咱們使用Tab鍵索引時候,能夠看到下圖所示的輪廓效果:

輪廓示意

輪廓區域比原生的<summary>要小,但這無傷大雅,並且實際項目開發的時候,咱們會去掉小箭頭,此時只要設置<a>標籤display:block,則輪廓就能夠和<summary>保持一致了。

接下來,咱們按下Space空格鍵,就會發現<details>元素內的內容信息不斷的展開與收起:

收起狀態

而後上面實現並不完美,相比原生的

元素,Enter回車鍵展開收起效果丟失了。這是由於HTML元素中若是多個focusable同時帶click瀏覽器行爲元素嵌套的時候,點擊裏面的元素,外部元素的瀏覽器行爲是不會觸發的。相似的有標籤。

對於標籤,其瀏覽器行爲只能經過回車鍵觸發,空格鍵是無效的;可是對於

,回車鍵和空格鍵都能觸發展開收起行爲,這就是爲何上面代碼空格鍵有效,回車鍵無效的緣由。

若是想要同時支持回車鍵展開與收起,能夠對HTML以下處理:

<details open>
    <summary tabindex="-1"><a href="javascript:" onClick="this.parentNode.click();">這是示例</a></summary>
    <content>點擊無外框,鍵盤focus有。</content>
</details>

複製代碼

須要注意的是上面處理在

本身額外綁定click事件時候可能會有double觸發的問題,此時,阻止元素的冒泡便可。

  1. JS捕獲鍵盤行爲手動設置outline 這個方法不須要對HTML進行任何的改動,是經過CSS和JS配合對全局的元素進行outline優化。

CSS以下:

summary {
    user-select: none;
    outline: 0;
}
summary[focus] {
    outline: 1px dotted;
    outline: 5px auto -webkit-focus-ring-color;
}

複製代碼

JS以下:

window.addEventListener('keydown', function () {    
    window.isKeyEvent = true;
    setTimeout(function () {
        window.isKeyEvent = false;
    }, 100);    
});

document.addEventListener('focusin', function (event) {
    var target = event.target;
    if (target && target.tagName.toLowerCase() == 'summary' && window.isKeyEvent == true) {
        target.setAttribute('focus', '');
    }
});
document.addEventListener('focusout', function (event) {
    var eleFocusAll = document.querySelectorAll('summary[focus]');
    [].slice.call(eleFocusAll).forEach(function (summary) {
        summary.removeAttribute('focus');
    });
});

複製代碼

只要把上面的CSS和JS複製到頁面中,視覺體驗和交互體驗完美支持的

元素outline效果就有了。

表現爲,點擊

沒有任何outline,鍵盤focus時候出現,且和瀏覽器原生outline效果如出一轍,Space鍵和Enter鍵展開與收起訪問徹底保留。

例以下圖就是鍵盤Tab鍵focus後回車後的效果:

鍵盤訪問回車收起後效果截圖

往往看到如此極致的用戶體驗處理,心情都大好。

原理: 關鍵是全局監聽keydown事件,若是有發生,則認爲此100毫秒內的頁面focus行爲均是鍵盤產生,從而有效區分是點擊觸發的focus行爲仍是鍵盤觸發的focus行爲,若是是鍵盤觸發,給<summary>元素手動增長outline效果。

4、基於details元素行爲的各類交互效果案例

瞭解了<details>元素的點擊交互行爲;解決了UI定製難題;解決了outline的體驗問題,下面咱們就能夠付諸實踐,不借助任何JS來實現各類咱們日常見到的交互效果。

案例1:「更多」展開與收起效果

實現最終效果以下gif:

更多展開收起gif效果

由於「更多」元素是在底部,所以效果實現的要點的全部的內容信息都放在<summary>元素內部,而後經過<details>元素的open屬性控制UI的變化。

HTML和CSS代碼以下,其中,最核心部分已經紅色高亮:

<details>
    <summary>
        <p>據臺媒報道,大...青睞。</p>
        <div class="more">
            <p>其餘幾首歌曲...</p>
        </div>
        <a>更多</a>
    </summary> 
</details>
::-webkit-details-marker {
    display: none;
}
::-moz-list-bullet {
    font-size: 0;
    float: left;
}
.more {
    display: none;
}
[open] .more {
    display: block;
}
[open] summary a {
    font-size: 0;
}
[open] summary a::before {
    content: '收起';
    font-size: 14px;
}

複製代碼

把「更多」對應的信息放在.more元素內,而後經過[open]屬性選擇器控制器顯示,效果即達成。

案例2:無JS實現點擊顯示懸浮菜單,自定義下拉框等效果

效果以下gif:

下拉菜單gif效果

沒有任何JS參與。HTML結構以下:

<details>
    <summary>個人消息</summary> 
    <div class="box">
        <a href>個人回答<sup>12</sup></a>
        <a href>個人私信</a>
        <a href>未評價訂單<sup>2</sup></a>
        <a href>個人關注</a>
    </div>
</details>

複製代碼

而後CSS讓.box元素絕對定位便可,顯示和隱藏<details>元素內置行爲就搞定了。

案例3:accordion多項摺疊效果

此效果常見於條目比較多的垂直導航欄,新聞條目等。

例以下面實現的效果:

多條目菜單展開與收起效果

這個更加簡單了,就是一堆<details>元素並排放置就能夠了,以下HTML:

<details open>
    <summary><dt>訂單中心</dt></summary> 
    <dd><a href>個人訂單</a></dd>
    <dd><a href>個人活動</a></dd>
    <dd><a href>評價曬單</a></dd>
    <dd><a href>購物助手</a></dd>
</details>
<details open>
    <summary><dt>關注中心</dt></summary> 
    <dd><a href>關注的商品</a></dd>
    ...
</details>
<details open>
    ...
</details>


複製代碼

計算CSS沒有任何設置,效果也自然達成。

案例3中的展開項顯示的時候是很是生硬的忽然顯示,實際上咱們能夠藉助一些選擇器技巧以及CSS3 transition屬性讓菜單展開收起的時候是有動畫效果的,效果以下gif截圖:

含slideup/slidedown動畫的展開與收起

此效果實現原理核心是[open]屬性選擇器,和加號+相鄰兄弟選擇器。

首先看下HTML,展開列表結構發生了變化,不是做爲<details>的子元素,而是做爲其相鄰兄弟元素存在,HTML示意:

<details open><summary>訂單中心</summary></details>
<dl>
    <dd><a href>個人訂單</a></dd>
    <dd><a href>個人活動</a></dd>
    <dd><a href>評價曬單</a></dd>
    <dd><a href>購物助手</a></dd>
</dl>
...

複製代碼

上面<dl>定義列表就是展開收起的內容,其做爲兄弟元素和<details>元素分庭抗禮,因而,咱們就能夠利用點擊<summary>元素<details>元素的open屬性會變化的特性實現咱們想要的動畫效果,CSS以下:

details + dl {
    max-height: 0;
    transition: max-height .25s;
    overflow: hidden;
}
[open] + dl {
    max-height: 100px;
}

複製代碼

藉助相鄰兄弟選擇器以及max-height任意元素slideUp/slideDown技術就能夠效果達成。

案例5:多級嵌套的樹形菜單交互效果

這裏的樹形菜單效果實現也很簡單,多個<details>元素相互嵌套就能夠,效果Gif以下:

樹形菜單展開gif效果截圖

HTML結構大體以下:

<details>
    <summary>個人視頻</summary>
    <details>
        <summary>爆肝工程師的異世界狂想曲</summary>
        <div>tv1-720p.mp4</div>
        <div>tv2-720p.mp4</div>
        ...
        <div>tv10-720p.mp4</div>
    </details>
    <details>
        <summary>七大罪</summary>
        <div>七大罪B站00合集.mp4</div>
    </details>
    <div>珍藏動漫網盤地址.txt</div>
    <div>咱們的小美好.mp4</div>
</details>

複製代碼

CSS的主要工做就是繪製菜單前面的加號和減號圖形,例如咱們能夠藉助background線性漸變,相關CSS以下:

details {
    padding-left: 20px;
}
summary::before {
    content: '';
    display: inline-block;
    width: 12px; height: 12px;
    border: 1px solid #999;
    background: linear-gradient(to right, #999, #999) no-repeat center, linear-gradient(to top, #999, #999) no-repeat center;
    background-size: 2px 10px, 10px 2px;
    vertical-align: -2px;
    margin-right: 6px;
    margin-left: -20px;
}
[open] > summary::before {
    background: linear-gradient(to right, #999, #999) no-repeat center;
    background-size: 10px 2px;
}

複製代碼

效果即達成!

5、若是隻想要details/summary的語義不要行爲

若是隻想要<details>元素,<summary>元素的語義,可是並不須要點擊展開收起的行爲,該怎麼處理呢?

例如,某評論,或者某帖子有標題和正文,很是符合詳情-概要-內容的語義,可是但願是純展現的,點擊時候不收起,能夠這麼處理:

1.<summary>標籤設置tabindex="-1"讓鍵盤沒法訪問; 2.設置CSS:

summary {
  outline: 0;
  pointer-events: none;
}

複製代碼

這樣就不能點,也不會有outline輪廓。

6、兼容性以及Polyfill

兼容性以下圖:

detailas兼容性

除了IE和Edge瀏覽器,大好河山一片綠,至少移動端能夠用得比較開心。

若是想要在桌面web網頁使用<details>元素的棒棒噠特性,咱們能夠對其進行Polyfill

對鍵盤訪問,事件toggle都作了兼容。

若是開發策略是對不支持的IE進行特異處理,則下面的JS判斷是否支持<details>元素的腳本可能對你有用:

var isSupportDetails = 'open' in document.createElement('details');

最後,無JS實現的好處有:

省了代碼,加載快了; 實現更簡單了,開發快了; JS還沒加載交互也能進行,體驗好了; 鍵盤無障礙和aria閱讀設備無障礙自然支持,體驗檔次高了。

這裏推薦一下個人前端學習交流羣:784783012 ,裏面都是學習前端的,若是你想製做酷炫的網頁,想學習知識。本身整理了一份2018最全面前端學習資料,從最基礎的HTML+CSS+JS到移動端HTML5到各類框架的學習資料都有整理,送給每一位前端小夥伴,有想學習web前端的,或是轉行,或是大學生,還有工做中想提高本身能力的,正在學習的小夥伴歡迎加入學習。

相關文章
相關標籤/搜索