某著名小白說過 :世上原本處處都是坑,只要走的人多了,也就把坑都給埋了。該小白還說過:坑自己並不可怕,可怕的是踩了一次以後,還第2、第三次踩到了相同的坑。html
所謂"坑",主要是因爲咱們對某些知識點理解不夠透徹,致使在應用的時出現了一些奇怪的問題。由於咱們每一個人,對於某個知識點的理解程度不同,因此,有些坑我以爲真的很坑,可是你可能以爲一點都不坑,由於你早就對它瞭如指掌了。前端
這裏列舉的一些坑,都是我過去一年在項目中所遇到過的,並當時在筆記中記錄下來的,如今稍加整理就造成了這篇博客,以供往後查閱。git
不知不覺,開頭又bb了這麼多,仍是趕忙進入正題哈。github
以前作爐石盒子的天梯環境頁面,地址是 爐石天梯環境 ,就在項目作得差很少的時候,準備上線了, QA 忽然發現了以下的一個 bug:
web
有一個選擇排序方式的下拉菜單,它的定位是 position: absolute
,正常來講,它應該會覆蓋在其餘元素之上的,但是爲何 0.14%
反而會覆蓋在它上面呢? 在代碼中找了很久,那個 0.14%
並無設置 z-index
屬性,也沒有 position: absolute
這樣的東西,真是好鬱悶哦。後來到 mdn 查文檔才發現,原來是 opacity
屬性引發 的: opacity 屬性值小於 1 的元素會建立新的層疊上下文 。由於當時我有個偷懶的作法,字體繼承的顏色是 #666
, 我想讓 0.14%
(天梯比率)顏色變淺一些,直接加了個 opacity: 0.6
,致使了建立了新的層疊上下文,層級比下拉菜單高了,因此就覆蓋在了上面。具體什麼是層疊上下文,以及哪些屬性會建立新的層疊上下文,這裏也不介紹了有須要的能夠參考一下 層疊上下文canvas
雖然上面描述得已經很詳細了,可是可能因爲個人表達能力不太好,有些朋友還不是很明白個人意思,能夠看一下這裏的 demo 代碼:小程序
<div class="menu"> <div class="title">下拉菜單</div> <div class="menu-list"> <div class="item">菜單1</div> <div class="item">菜單2</div> <div class="item">菜單3</div> </div> </div> <div class="content"> 我是半透明的文字,能夠覆蓋在下拉菜單之上哦~ </div> <style> .menu { position: relative; } .menu-list { display: none; position: absolute; background: #ccc; } .menu:hover .menu-list { display: block; } .content { opacity: 0.6; } </style>
將鼠標移動到下拉菜單上,就會發現文字會發生重疊了:
微信小程序
那這個坑有什麼解決辦法呢?最簡單的就是下拉菜單添加個屬性 z-index: 1
。另外,這裏再囉嗦一下,就是z-index
的值不要亂設置。之前剛剛接觸前端時,會常常看一些視頻教程,看到裏面講師動不動就設置個 z-index: 999
之類的特別大的數值。這是一個很差的習慣。張鑫旭老師在《CSS世界》一書中,提到了 不三原則
,就是說通常狀況下,z-index
的值不要超過3,基本能知足大多數的需求了。數組
以前作漫畫閱讀器,由於漫畫可能有長圖片,也可能有短圖片。長圖片能夠滾動查看,短圖片就居中顯示。因此,很天然會想到用 flex 佈局來實現。簡單的代碼以下:微信
<div class="app"> <img src="https://m.tuniucdn.com/fb2/t1/G1/M00/F1/51/Cii9EFkAaZ-IRgGNAATB18ldk0UAAJzuQN-p1cABMHv15.jpeg" alt=""> </div> <style> html, body { height: 100%; } .app { display: flex; height: 100%; justify-content: center; align-items: center; } img { width: 100%; } </style>
這裏,咱們的 .app
容器裏面這裏有一張很長的圖片。當咱們運行上面的代碼,若是你仔細觀察原圖和頁面顯示的圖片,就會發現圖片的頂部和底部的一些內容看不到了,滾動條到了必定位置就沒法滾動了。正常來講,咱們應該能夠經過滾動條的上下滑動看到圖片的所有內容纔對的。當時我想了好久也沒有想出來緣由,最後到 stackoverflow 找到了答案 Can't scroll to top of flex item that is overflowing container
答案中有提到,能夠設置子項的 margin: auto
來實現內容溢出時也自動居中(包括水平和垂直的):
修改後的 CSS 代碼以下:
.app { display: flex; height: 100%; } img { width: 100%; margin: auto; }
因此,之後若是在使用 flex 佈局實現居中,若是子項的內容會溢出 flex 容器 ,能夠將子項設置爲 margin: auto
試試。
CSS3 的 transform 屬性也算是比較經常使用的,特別是作一些動畫效果的時候,用它來移動元素的位置,性能會比設置 top 或 left 要高一些。可是,若是一個元素設置了 transform 屬性,而它的子元素又設置 fixed 定位,那麼這個 fixed 定位的子元素表現會有些奇怪,以下代碼:
<div class="app"> <button onclick="layer.style.display='block'">彈出蒙層</button> <div class="layer" id="layer"></div> </div> <style> .app { position: relative; width: 100px; height: 100px; background: #ccc; /* 使用transform讓元素向下偏移20px */ transform: translate(0, 20px); } .layer { display: none; position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0, 0, 0, 0.7); } </style>
打開頁面,效果是這樣的:
咱們但願點擊「彈出蒙層」按鈕後,就顯示個覆蓋整個窗口的蒙層。可是結果卻出乎意料。以下:
蒙層只是遮住了小正方形,這不是咱們想要的結果,由於咱們知道,fixed 定位是相對於屏幕視口(viewport)定位的, 可是,本例卻相對於它的父親元素。這是爲何呢?若是認真查閱 mdn文檔 ,就會找到答案:
可見,問題的緣由在於,咱們只是記住了fixed是相對於 viewport 定位,可是也有特殊狀況: 當元素祖先的 transform 屬性非 none 時,容器由視口改成該祖先 。因此,這並非bug,是由於我基礎不紮實致使的。事實上, 除了 transform 會改變 fixed 的定位元素以外,還有其餘屬性也會改變,ChokCoco大佬有一篇文章作了詳細的講解,想要了解更多的請點擊 不受控制的 position:fixed
那遇到這種狀況怎麼辦呢?比較好的辦法就是把 fixed 元素移到外面去,不要放到有 transform 屬性的元素裏面。可是,有時候咱們沒有辦法移到外面怎麼辦呢?好比,這是它是一個子組件,它的某個父親組件就是用了 transform,那怎麼辦呢?我也不知道怎麼辦,歡迎你們探討一下哈哈哈~
fixed 定位還具備其餘的坑,這裏也不展開了,有興趣的可看 看github 上有大佬整理好的這篇文章 移動端web頁面使用position:fixed問題總結
咱們都知道, video 標籤設置了 playsinline 就能夠內聯播放視頻,而不是全屏播放。(注意:前提是客戶端的 Webview 配置了容許內聯播放,因此有時候雖然設置了 playsinline,但在某些 app 裏面打開依然是全屏播放,這不是前端的鍋哦)。最近有一個需求,相似下面這樣的:
頁面上有一個視頻,視頻播下面有一個按鈕,點擊按鈕就彈出一個圖片,該圖片要覆蓋整個屏幕,好比是這樣的:
示例代碼以下:
<video id="video" controls="" playsinline="" src="https://vod.cc.163.com/file/5bcbe1ae9efdc0608bb6d06b.mp4"></video> <img id="image" src="https://ds.163.com/2018/mrzh/appointment/static/img/bg-body.cdef1ec.jpg" alt=""> <button id="button">彈出圖片</button> <style> video, img { width: 100%; } img { display: none; position: absolute; top: 0; } </style> <script> var video = document.getElementById('video'); var image = document.getElementById('image'); var button = document.getElementById('button'); button.onclick = function() { image.style.display='block'; } image.onclick = function() { this.style.display='none'; } </script>
可是,在安卓上卻發現一個問題,開始播放視頻後(注意,只有播放視頻後才能夠復現),點擊「彈出圖片」按鈕,顯示以下所示:
圖片沒法覆蓋在視頻播放器上面。而後,我設置了 z-index 或者 transform ,都沒有任何效果。最後, 剩下的可能緣由就是: 安卓微信視頻播放器實際上用的是原生組件。爲了驗證這一猜測,咱們能夠啓用開發者選項的繪圖模式 (開發者選項 --> 繪圖 --> 顯示佈局邊界,不一樣機型不同,找不到的請百度找一下哈),結果以下:
看到沒有,視頻是一個完整的有邊框的東西,證實他是一個獨立於 Webview 的原生組件。
那怎麼辦呢?只能上網找答案呀!咱們都知道,微信 webview 使用的是 X5 內核,因此我也但願能從它的開發者文檔上找到一些有用的信息,好不容易找到了一篇叫作 H5同層播放器接入規範 。它說能夠能夠在 video 標籤添加一個屬性 x5-video-player-type ,而且給出的例子是這樣的:
<video src="http://xxx.mp4" x5-video-player-type="h5"/>
我當時很高興,覺得問題就這樣解決了,然並卵,添加了 x5-video-layer-type 屬性以後,playsinlie 屬性就失效了,沒法內聯播放了,只能全屏播放,因此,不能添加這個屬性。
而後我就想,既然沒法覆蓋這個視頻,那在彈出圖片的時候能不能把視頻給隱藏掉?而後關閉圖片的時候再把視頻顯示回來呢?因而就把 JS 代碼改爲下面這樣:
button.onclick = function() { image.style.display='block'; video.style.display = 'none'; } image.onclick = function() { this.style.display='none'; video.style.display = 'block'; }
而後,這樣就能夠了。由於我在網上找不到更好的辦法,若是你們遇到這個問題能夠參考這種作法。固然,若是大家找到了有更好的辦法,歡迎評論分享出來哈~
關於安卓微信視頻播放器的坑就先講到這裏啦。
等等,一講到原生組件,這裏還得再補充一下微信小程序相關的東西,固然,我本身尚未太小程序的開發的經驗, 這是以前的一次內部交流會,一位同事的分享:小程序在渲染的時候,大多數組件都是渲染成 HTML 組件,可是有少部分好比 canvas、 video、 input、 map 等會渲染成原生組件的。因此,若是你在寫小程序時,想用一段文字覆蓋在一個 canvas 上,發現怎麼設置都沒法實現,那是由於 canvas 渲染後是原生組件,而文字是 html 組件,因此沒法覆蓋上去的 。那有什麼辦法呢?能夠考慮把文字放到 cover-view 上, 它也是一種原生組件,能夠覆蓋在 canvas 上的。具體的能夠參考小程序官方文檔 原生組件說明
關於2018踩的坑就寫到這裏了,固然還有一些其餘的,暫時沒有時間整理,下次若是整理後,再寫一篇補充一下。
若是你們有什麼問題,或者過去踩到過了哪些坑,歡迎在評論區討論哈。