網站有一些改動的時候,爲了讓用戶熟知新的操做位置,每每會增長一個引導,常見的方式就是使用一個黑色的半透明蒙版,而後須要關注的區域是鏤空的。css
而後上週五我去微雲轉悠的時候,也看到了引導層,因而職業病又犯了,去學習下別人是怎麼實現的。下面是觀測的結果:html
爲了實現鏤空濛層效果,做者發揮了小時候拼積木的才能,使用兩層HTML結構,內層使用5塊獨立區域拼接造成,至於中間鏤空的區域的陰影則是使用的圖片實現的。css3
雖然最終的效果知足了產品的需求,對於用戶而言,目的已經達到。可是,從代碼質量層面、潛在的體驗提高可能性、使用場景廣度上來說,仍是弱了不少的。瀏覽器
舉例來講,若是咱們某個提示區域面積很大,那中間的那個鏤空區域尺寸是否是要變,那後面的背景圖片怎麼辦?搞新圖,有人看到了使用了background-size:cover
, 那IE7,IE8怎麼辦?哦,可能微雲不須要管IE7, IE8.ide
若是不須要管IE7, IE8,那這裏的實現就顯得更加小白了。咱們實際上只須要一層標籤,一層空標籤就能夠實現咱們的效果,且不須要圖片。wordpress
主要在於思惟方式的變化。拼積木這種想法你們都比較容易想到,符合平常認知,可是,但代碼層面,咱們能夠進行思惟轉換,發散思考,偌大的半透明遮罩層,咱們不要老想着背景色塊背景色塊,能夠突破常規思惟,把它認爲是邊框,一個很大很大的邊框(咱們平時使用border都是1
像素巨多),這樣,咱們天然就有了鏤空效果。學習
以下圖示意:動畫
可是,目前咱們中間的鏤空區域方的,有沒有什麼辦法變成圓的呢?
天然有,方法1是元素設置超大圓角,可是,此時爲了邊框依然填滿整個屏幕,border
邊框尺寸要大大增大,可是,爲了避免影響頁面的滾動條,咱們必須再嵌套一層標籤,就顯得囉嗦了;
方法2則是方法1某些方面的逆向思惟處理,就是把當前元素做爲外層限制標籤,裏面從新生成一個大尺寸僞元素,實現自適應尺寸的圓角效果,這個好,HTML乾淨不囉嗦,CSS一步到位(代碼以下示意);網站
.cover::before { content: ''; width: 100%; height:100%; border-radius: 50%; border: 400px solid #000; position: absolute; left: -400px; top: -400px; /* 本身瞎填的參數,示意 */ box-shadow: inset 0 0 5px 2px rgba(0,0,0,.75); }
你們能夠看到,上面的僞元素的各個參數都是固定參數值,與外部元素的尺寸什麼的沒有任何關係,只要外部元素尺寸不超過400,裏面永遠會有一個正橢圓的內陰影的鏤空圖形(由於超出部分會被.cover
隱藏),要理解圓角和正橢圓的關係,能夠參考我以前的文章:「秋月什麼時候了,CSS3 border-radius知多少?」。ui
眼見爲實,耳聽爲虛,您能夠狠狠地點擊這裏:一層標籤實現網站引導鏤空濛版功能demo (點擊黑色蒙層會有引導切換效果)
demo這個鏤空濛層所使用的HTML代碼以下:
<div class="cover"></div>
沒錯,就這麼簡單,沒什麼嵌套,沒有什麼五個元素變形金剛合體,沒有使用圖片。
微雲這張圖片3K多,以微雲的用戶訪問量,估計流量費要很多錢的。
並且,你們若是點擊蒙版,會發現,鏤空的區域大小每次都是不同的,有大有小,有高有瘦,而微雲的那個實現方法要知足此需求就棘手;並且,你們發現沒,這些尺寸位置的變化都是動畫來動畫去的,不是嗙嗙嗙這種生硬的效果,更soft, 對用戶視覺引導效果更好,你看,我從這裏到這裏了,爲何能夠實現動畫效果呢,由於咱們的鏤空和內陰影都是CSS實現的,而微雲的圖片方法,顯然是沒法有動畫的。
JS代碼輔助
固然,個人實現也離不開JS的輔助,JS的工做很簡單,讓蒙層的width
/height
以及border
大小和須要引導的元素相關聯。
我特地整了個能夠公用的方法coverGuide
(命名不喜歡本身隨便改):
var coverGuide = function(cover, target) { var body = document.body, doc = document.documentElement; if (cover && target) { // target size(width/height) var targetWidth = target.clientWidth, targetHeight = target.clientHeight; // page size var pageHeight = doc.scrollHeight, pageWidth = doc.scrollWidth; // offset of target var offsetTop = target.getBoundingClientRect().top + (body.scrollTop || doc.scrollTop), offsetLeft = target.getBoundingClientRect().left + (body.scrollLeft || doc.scrollLeft); // set size and border-width cover.style.width = targetWidth + 'px'; cover.style.height = targetHeight + 'px'; cover.style.borderWidth = offsetTop + 'px ' + (pageWidth - targetWidth - offsetLeft) + 'px ' + (pageHeight - targetHeight - offsetTop) + 'px ' + offsetLeft + 'px'; cover.style.display = 'block'; // resize if (!cover.isResizeBind) { if (window.addEventListener) { window.addEventListener('resize', function() { coverGuide(cover, target); }); cover.isResizeBind = true; } else if (window.attachEvent) { window.attachEvent('onresize', function() { coverGuide(cover, target); }); cover.isResizeBind = true; // IE7, IE8 box-shadow hack cover.innerHTML = '<img src="guide-shadow.png">'; } } } };
這裏的coverGuide
方法使用原生JS實現,IE6+瀏覽器都是兼容的,不依賴JS庫,你們能夠隨意使用。固然,寫得匆忙,沒有嚴格驗證,可能有bug,你們能夠稍微留點心。
使用很是簡單,語法以下:
coverGuide(cover, target);
其中cover
就是.cover
這個單獨的蒙版元素,target
則是咱們須要指引的元素,按鈕啊,導航什麼的。而後,咱們的鏤空區域自動定位到target
的位置,大小也是target
元素的大小。超省心。
具體使用,可參考上面的demo,源代碼就在頁面上。
IE7,IE8怎麼辦
若是你須要兼容IE7,IE8,咱們不妨就方框效果;若是設計和產品接受不了,則可使用圖片打個補丁,例如上面JS代碼部分的:
cover.innerHTML = '<img src="guide-shadow.png">';
我demo使用的這個圖片長下面這樣:
大小還有陰影都是我本身隨手一搞的,旨在示意,真實項目你們能夠向設計師索要圖片。
而後,CSS超easy, 圖片撐滿咱們的cover
就能夠。
/* IE7, IE8 img */ .cover > img { width: 100%; height: 100%; }
這種蒙版覆蓋思想呢,不只僅適用於這種大面積的引導。咱們上傳圖片,尤爲上傳頭像以後,要對頭像進行剪裁,常見的交互之一就是四周黑色,中間鏤空,也可使用巨大border
來實現咱們的效果,一層標籤足矣,根本不須要上下左右額外4層標籤拼接合體實現。
內部自適應的圓角效果單看文字,不少小夥伴估計不知道我在說些什麼,建議去demo頁面看下僞元素的代碼,真實區域大小和最終效果,估計就會明白了。
感謝閱讀,歡迎交流,歡迎提供更好的實現方法,必定有的,只是我功力不夠。
以上~