簡單的說明一下,使用這個標題並不就是說要使用全英文來寫這篇文章,主要是實在想不到更好的叫法了,也不知道怎麼樣可以更好的翻譯成中文。javascript
能夠簡單地理解爲:使用 CSS 來實現一個閱讀文章時的簡單的進度條效果。css
本文所須要用到的背景知識點包括:
background-size, linear-gradient, calc() 函數, vh 單位
。html
Indicator 是什麼?能夠把它看做是一個指標,這種指標其實很常見,在咱們閱讀文章的時候,咱們會將文章向上滾動,一些網站的作法就是給用戶一個指標,標示用戶已經讀了多少內容了,這個指標就相似於一個進度條的樣子,鼠標每向上或者向下滾動一點,這「進度條」會增長或者減小一點。用戶閱讀完畢的時候,它的長度也會達到整個網頁的寬度。java
通常狀況下,若是要實現一個這樣的效果,咱們首先想到的確定是使用 JavaScript。經過使用 JavaScript 來根據用戶滾動的距離,而後,將這個距離和 Indicator 的總長度以及剩餘內容的高度綜合進行比較,進行一些換算,而後改變 Indicator 的長度,這樣,就實現了一個 Indicator 了。git
本文不會講解如何使用 JavaScript 來實現此效果,若是有須要的,能夠參考 Bloomberg Article Scroll Indicator。web
那麼,本文主要講解的就是如何使用 CSS 來實現此效果。api
首先,咱們將 HTML 都寫好了(因爲涉及到滾動,因此,能夠隨意的多加點內容,此處只是示範性地寫了一點內容,具體的讀者能夠自行添加更多內容):瀏覽器
<header> <h1>Scroll Indicator</h1> </header> <main> <h2>I was interested to see if I could make a scroll indicator like this with just CSS.</h2> <p>You can! But maybe you shouldn't. This is an interesting consequence of a bunch of hacks held together with duct tape. It uses z-index hacks, gradient hacks and tricks with calc and viewport units.</p> <p>Having said that, hacks are not always bad. I love hacks and many of us have made quite a good living selling floats and clearfixes.</p> <p>The techniques used here are well supported, if not conventional. If you can read the CSS, understand how it works, and how to change it, and you think this works better for you than JavaScript, feel free to implement it. Just be aware of the z-index behaviour and possible conflict with other CSS using negative z-index.</p> <hr> <p>Cras mattis consectetur purus sit amet fermentum. Donec id elit non mi porta gravida at eget metus. Donec id elit non mi porta gravida at eget metus. Aenean lacinia bibendum nulla sed consectetur.</p> <h3>Tristique Aenean Etiam Cras</h3> <p>Donec id elit non mi porta gravida at eget metus. Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue. Donec sed odio dui. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.</p> <p>Cras mattis consectetur purus sit amet fermentum. Donec id elit non mi porta gravida at eget metus. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Etiam porta sem malesuada magna mollis euismod. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec ullamcorper nulla non metus auctor fringilla.</p> <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Donec ullamcorper nulla non metus auctor fringilla. Sed posuere consectetur est at lobortis. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Aenean lacinia bibendum nulla sed consectetur. Nulla vitae elit libero, a pharetra augue.</p> <p>Donec sed odio dui. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Cras mattis consectetur purus sit amet fermentum. Maecenas sed diam eget risus varius blandit sit amet non magna.</p> </main>
而後,咱們簡單的調整一下樣式:函數
html, body { margin: 0; padding: 0; } body { font-family: "Times New Roman", Courier, monospace; font-size: 1.25rem; }
因爲咱們滾動的時候,須要讓 header
保持不動,因此,須要給它設置 position: fixed;
:優化
header { position: fixed; top: 0; width: 100%; height: 125px; padding: 0 10%; background: #ffffff; }
而後,爲了不 main
元素包含的內容被 header
覆蓋,咱們須要讓 main
往下挪一些,同時給它設置一個 padding
:
main { margin-top: 125px; padding: 10px 10%; }
OK,大概的調整就這些,咱們如今來構思如何實現這個 Amazing 的效果。
按照使用 JavaScript 來實現這個效果的思想,那麼,咱們就須要先去計算一個百分比——也就是滾動的文章長度與總的剩餘文章長度的比。
以下圖所示:
假設咱們文章的總長度爲 a
,以紅色的線爲界限,超出紅線上的部分即爲滾動的距離。那麼,咱們此刻滾動的距離爲 x
,z
表明的是滾動的進度百分比,紅線的總長度 y
即爲咱們的 Indicator 的總長度,也就是所謂的 100%。那麼,咱們須要的確定是如下的關係:
x / a === z / y;
那麼,計算出來的滾動的進度百分比 z
應該就是:
z = (x * y) / a;
好了,這是 JavaScript 的大概思路,咱們已經瞭解了,咱們先把這個結果放這兒,來看看如何使用 CSS 來實現。
在這裏,咱們須要用到兩個 CSS 屬性和一個 CSS 方法和一個 CSS 單位——linear-gradient, background-position 和 calc() 和 vh
。
簡單的介紹一下這兩個屬性:
1.
background-position
接受 1 到 4 個參數,默認值爲0% 0%
。能夠設置的值有top right bottom left center
,前四個值後面還能夠跟具體的數值或者百分比。若是不加方向說明,直接設置數值或者百分比,位置則會以left top
進行定位。注意:此處的top right bottom left
定位是以padding-box(即 padding 的外沿框)
進行定位的。
(若要了解詳細內容,可查看 background-position | MDN。)2.關於
linear-gradient
,即用來建立線性漸變。這個函數可接受多個參數值,其中,第一個表示漸變的方向,若是不寫的話,默認爲to bottom
,其他分別是to top | left | right
,後面的參數表示漸變的顏色,能夠有多個顏色,每個顏色後面還能夠指定顏色的漸變位置。
(若要了解詳細內容,可查看 linear-gradient | MDN。)注意:因爲
linear-gradient
生成的是一個 CSS image 對象,因此,這個函數只能應用在須要的數據類型是 image 的屬性(如background-image
,background
)上。也就是說,若是在color
或者background-color
屬性上應用這個函數的話,將會不起做用。3.關於
calc()
函數,能夠用來動態計算 CSS 的屬性值。好比calc(100px - 10px)
最終結果就爲90px
;
若要了解詳細內容,可查看 calc | MDN。注意:爲了讓這個函數向上兼容,之後可能會在 calc 的內部容許使用關鍵字(或者說變量),而這些關鍵字(或者變量)就包含連字符(即減號),因此,爲了不解析衝突,要在運算符的先後加上空格。其中,+ 和 - 先後必須加上空格,* 和 / 先後不要求,但爲了一致性,最好也都加上空格。
4.關於
vh
單位,這個單位表明的意思即ViewHeight
,即瀏覽器可視區域的高度。與百分比相似,100vh = height: 100%
。
(若要了解詳細內容,可查看 length | MDN。)
那麼,咱們使用 CSS 實現的話,思路和 JavaScript 稍微有一點區別。但原理是同樣的,咱們仍然須要計算一個比例。
仍是來看一張圖:
咱們將咱們的咱們讓 Indicator 的寬度和 body
等寬(好吧,其實就是 100%,此處這樣話會好理解一點),而後,注意到黃色的三角形了嗎,當咱們向上滾動的時候,黃色的三角形也會跟着向上滾動,同時,它會和長度爲 y
的 Indicator 發生交叉,Indicator 會從三角形截出一段距離 z
。這時候,黃色三角形向上移動的距離是 x
。那麼,要達到 Indicator 的效果,我麼確定要知足下面的條件:
x / a === z / y;
因此,這樣計算出來,咱們的 z
就是:
z = (x * y) / a;
注意到沒,其實和咱們上面的使用 JavaScript 時的計算結果是同樣的。因此,原理相同,咱們只須要變通一下就行了。
那麼,怎麼用 CSS 寫出來呢?
注意到黃色三角形了嗎,它上面還有一個白色三角形,它們兩個是對稱的,由兩種不一樣的顏色組成,正好能夠將其做爲咱們的 Indicator 的高亮色和默認色。
咱們把這兩種顏色做爲 body
的背景顏色,文章就在這個背景的上面,那麼,咱們滾動文章的時候,背景也會跟着動,就會有以上圖中的效果了。
body { background: linear-gradient(to right top, #0089f2 50%, #DDD 50%); background-position: 0 125px; background-size: 100% calc(100% - 100vh + 5px); background-repeat: no-repeat; }
注意到第一個屬性的設置了嗎,咱們將兩個顏色的位置都設置成了 50%
,那麼,這就至關於簡便的過渡區域趨於無限小,看上去就至關於兩種顏色累積在一塊兒。
第二個屬性,咱們將背景的位置進行了更改,將其往下移動了 125px
,這個距離正好是咱們的 header
的高度。這樣,在咱們沒有滾動的時候,Indicator 的進度將會是 0;。
第三個屬性,看着這麼長一個計算的等式,其實計算的是咱們的剩餘文章的長度。100%
即文章的總長度,100vh
即咱們所看到的文章的長度,至於那個 5px
是什麼,那是咱們預留出來顯示 Indicator 的高度。
OK,咱們如今來看效果將會是下面這張圖片顯示的樣子。
咱們看到,當咱們向上滾動的時候,header
和 main
的交界處的藍色區域在變化,對,這就是咱們將要實現的 Indicator 的原型。
那麼,既然是一個 Indicator,那他就應該有一個 Indicator 的樣子。咱們須要把下面的那些所有遮住,只留出 Indicator 的那一條 progress bar。
因此,咱們繼續完善代碼:
body:before { content:''; position: fixed; top: 127px; bottom: 0; width: 100%; z-index: -1; background: white; }
咱們經過使用一個僞元素來把 body
中多餘的背景給隱藏掉。
設置 top: 127px;
目的即讓 Indicator 的高度爲 2px
,即到頂部的距離減去 header
的距離。
至此,咱們使用 CSS 製做的 Indicator 就上大功告成了。
下面是咱們實現的全部代碼和效果:
本文參考自 https://codepen.io/MadeByMike...,我在此基礎上對其進行了一些優化。若是有問題,歡迎在評論區留言,Feel Free To Ask。