給用戶一個是否減弱動畫效果的選擇

做者:Chris Coyier

翻譯:瘋狂的技術宅javascript

https://css-tricks.com/reduce...css

未經容許嚴禁轉載html

你有沒有看到過這樣一種簡潔的技術,它基於 prefers-reduced-motion 媒體查詢,將 <source media=""> 用於 <picture> 元素來提供動圖(或不提供動圖)? 前端

當咱們在 newsletter 上分享這種方法以後,獲得了 Michael Gale 的有趣回覆:java

喜歡 GIF 動畫,但又不想讓 UI 在變得花裏胡哨的人該怎麼辦?讓他們被迫在內容和界面之間作出選擇嗎?

我認爲這是一個很是有趣的問題。程序員

此外,這段時間每當看到 <img src="gif.gif"> 時,個人大腦被觸發到若是是 MP4 會怎樣?!總的來講,這是由於我確信從總體上來講在 Web 上視頻要比 GIF 具備更多的優點。事實證實,有些瀏覽器會在 <img> 元素中支持視頻,無論你信不信,你能夠爲 <picture> 元素寫下後備方案web

讓咱們把全部這些東西結合起來。面試

添加MP4源

最簡單的方法是在 picture 中添加一個額外的 <source>。這意味着咱們須要三個源媒體文件:segmentfault

  1. prefers-reduced-motionreduce 時啓用的後備非動畫圖片。
  2. 動畫 GIF 做爲默認值。
  3. 若是支持後備,則用 MP4 視頻替換 GIF 。

例如:瀏覽器

<picture>
  <source srcset="static.png" media="(prefers-reduced-motion: reduce)"></source>
  <source srcset="animated.mp4" type="video/mp4">
  <img srcset="animated.gif" alt="animated image" />
</picture>

在 Chrome 的默認條件下,只會下載並顯示 GIF:

clipboard.png

在 Safari 的默認條件下,僅下載並顯示 MP4:

clipboard.png

若是你在 Chrome 或 Safari中激活了 prefers-reduced-motion: reduce (在 Mac 上,能夠經過:系統偏好設置→輔助功能→顯示→減弱動態效果 進行設置),兩個瀏覽器都只下載靜態的 PNG 文件。

clipboard.png

我在測試 Firefox 時,發現它彷佛不起做用,繼續下載 GIF 版本。 Firefox 彷佛支持 prefers-reduced-motion,也許它只是目前不支持 <source> 元素?我不肯定這到底是怎麼回事。

使用工具把提供的單個動畫源生成其餘動畫源是一件很酷的事情!我打賭你能夠用 Cloudinary 之類的東西來解決這個問題。

添加顯示動畫版本的切換按鈕

就像 Michael Gale 所說的那樣,你可能徹底沒法看到動畫版本,由於你可能已經減弱了動畫效果。

添加一個 <button> 用 JavaScript 獲得媒體查詢並強制瀏覽器顯示動畫版本應該是很容易的。

我很肯定沒有什麼好的辦法在 HTML 中以聲明方式執行此操做。咱們也不能把這個按鈕放在 <picture> 標籤內。即便 <picture> 不是替換元素,瀏覽器仍然會感到困惑而且不喜歡它。甚至根本不會渲染它。這沒什麼大不了的,咱們還可使用包裝器。

<div class="picture-wrap">
  
  <picture>
     <!-- sources  -->
  </picture>

  <button class="animate-button">Animate</button>

</div>

咱們能夠將按鈕放在圖像頂部的某個位置。這只是一個隨意的選擇 —— 你能夠把它放在你但願的任何地方,或者甚至可讓整個圖像均可以點擊,只要你認爲能夠向用戶解釋清楚。請記住,只有在同一媒體查詢匹配時才能顯示按鈕:

.picture-wrap .animate-button {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .picture-wrap .animate-button {
     display: block;
  }
}

單擊(或點擊)按鈕時,咱們須要刪除媒體查詢以經過下載動畫源來啓動動畫。

let button = document.querySelector(".animate-button");

button.addEventListener("click", () => {
  const parent = button.closest(".picture-wrap");
  const picture = parent.querySelector("picture");
  picture.querySelector("source[media]").remove();
});

如下是演示:

CodePen上的演示:https://codepen.io/chriscoyie...

也許這是一個很好的組件?

咱們能夠用 web 組件自動包含按鈕、按鈕樣式和功能。嘿,爲何不呢?

CodePen上的演示:https://codepen.io/chriscoyie...


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索