- 做者:陳大魚頭
- github: KRISACHAN
在平常的開發中,咱們對 scroll
這個單詞確定不陌生。javascript
例如由於看不慣瀏覽器默認樣式而用 JS 一頓猛如虎操做的 自定義滾動條 。css
或者是嗖~一下就到頂的 回到頂部 。html
又或者是想去哪點哪的 標題導航 。java
可是在過去的開發中,要實現這些功能並非那麼輕鬆的一件事情。git
例如咱們要實現一個有滾動效果的 回到頂部 功能,咱們可能須要寫下這些代碼github
let timer = null;
let backTop = document.querySelector("#backTop");
backTop.addEventListener("click", () => {
cancelAnimationFrame(timer);
let startTime = +new Date();
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
let totalTime = 300;
timer = requestAnimationFrame(() => {
let lastTime = totalTime - Math.max(0, startTime - +new Date() + totalTime);
document.documentElement.scrollTop = document.body.scrollTop =
(lastTime * -scrollTop) / totalTime + scrollTop;
timer = requestAnimationFrame(func);
if (lastTime === totalTime) {
cancelAnimationFrame(timer);
}
});
});
複製代碼
(免責聲明:僞代碼未經測試,若有 BUG,跪求原諒。)web
嚶,意思就是要寫個動畫,不斷修改當前頁面的垂直滾動距離,直到爲 0。算法
(吃瓜羣衆:「很難嘛?是你太菜了吧,大叔!」)api
但其實隨着時間的推移, web api 以及 css 規範的不斷改進,那些咱們曾經認爲實現起來很麻煩的功能也變得簡單了起來。下面咱們能夠一塊兒來探討一下這些改進的內容。瀏覽器
咱們來康康 scroll 家族 裏有趣的 API。
scroll()
與 scrollTo
方法是用於在給定的元素中滾動到某個特定座標的 Element 接口。
語法以下:
x
:元素要移動的位置橫座標。y
:元素要移動的位置縱座標。options
支持屬性有left
,top
以及behavior
top
:元素要移動的位置橫座標。lef:
:元素要移動的位置縱座標。behavior
:元素的運動模式,若是是auto
,則沒有動畫效果,若是是smooth
,則是平滑滾動。咱們來康康栗子:
上面例子來自 MDN 的 GitHub 倉庫dom-examples
核心 JS 代碼以下:
let scrollOptions;
const form = document.querySelector("form");
const leftInput = document.getElementById("left");
const topInput = document.getElementById("top");
const scrollInput = document.getElementById("scroll");
form.addEventListener("submit", e => {
e.preventDefault();
scrollOptions = {
left: leftInput.value,
top: topInput.value,
behavior: scrollInput.checked ? "smooth" : "auto"
};
window.scrollTo(scrollOptions);
});
複製代碼
scrollBy()
方法是使得元素滾動一段特定距離的 Element 接口。
語法以下:
x
:元素要移動的位置橫座標。y
:元素要移動的位置縱座標。options
支持屬性有left
,top
以及behavior
top
:元素要移動的位置橫座標。lef:
:元素要移動的位置縱座標。behavior
:元素的運動模式,若是是auto
,則沒有動畫效果,若是是smooth
,則是平滑滾動。再舉個栗子:
核心代碼以下:
let scrollOptions;
const form = document.querySelector("form");
const leftInput = document.getElementById("left");
const topInput = document.getElementById("top");
const scrollInput = document.getElementById("scroll");
form.addEventListener("submit", e => {
e.preventDefault();
scrollOptions = {
left: leftInput.value,
top: topInput.value,
behavior: scrollInput.checked ? "smooth" : "auto"
};
window.scrollBy(scrollOptions);
});
複製代碼
Mmmmm,沒錯,就是隻是把上面的 DEMO 中的scrollTo
改成scrollBy
而已。很是的機智~
Element.scrollIntoView()
方法可讓當前的元素滾動到瀏覽器窗口的可視區域內。
語法以下:
alignToTop
是一個布爾值,若是不填則默認爲true
。至關於{block: 'start', inline: ‘nearest‘}
。
若是值爲true
,則元素的頂端將和其所在滾動區的可視區域的頂端對齊。若是爲false
,則是底端對齊。至關於{block: 'end', inline: 'nearest'}
scrollIntoViewOptions
包含下列屬性的對象:
behavior
:元素的運動模式,若是是auto
,則沒有動畫效果,若是是smooth
,則是平滑滾動。block
:定義垂直方向的對齊方式,值能夠是 start
,center
, end
或 nearest
之一。默認爲 nearest
。inline
:定義水平方向的對齊方式,值能夠是 start
,center
, end
或 nearest
之一。默認爲 nearest
。來來來,我給你們解釋一下block
跟inline
的可選值究竟是怎麼回事:
start
:跟當前元素它爹的頭髮(頂部)對齊。center
:跟當前元素它爹的肚子(中間)對齊。end
:跟當前元素它爹的 jio(底部)對齊。nearest
:就近原則,挨哪裏近去哪,若是在中間就不動。若是是block
,就當元素是站着的(從上往下),若是是inline
,就當元素是躺着的(從左到右)。固然,前提是默認的writing-mode: horizontal-tb
。
有點繞?快來康康栗子呀:codepen.io/krischan77/…
好了,上述就是殺馬特,哦不是,scroll
家族的特性了。(廢棄或準備廢棄的就沒往上寫了。)
分享完 JS 中的 scroll
,咱們再來了解下 CSS 中的 scroll
。
咱們上面在講這個 JS 中的 scroll
時,屢次提到一個單詞叫「behavior
」。
Mmmm,因此大家猜猜這個scroll-behavior
跟 JS 裏的behavior
有木有關係?
嗯,沒錯,大家猜對啦,是有關係的。
(吃瓜羣衆:「都沒人理你~」)
scroll-behavior
跟上述各個scroll
API 裏的behavior
同樣,是用來定義頁面進行滾動操做時的動畫效果。
若是定義爲smooth
,則頁面觸發滾動操做時,就會有滾動的效果,若是爲auto
,則跟原來同樣,是瞬間移動到指定位置。這指的是相似於點擊#hash
跳轉同樣的觸發,而不是滑動滾動條。
其效果能夠參照本文第一小節的 DEMO。
CSS Scroll Snap 是 CSS 中一個比較新的獨立模塊,它的第一個正式版本CSS Scroll Snap 模塊 Level 1也是在 2019 年 3 月 19 日才發佈。
CSS Scroll Snap 模塊 可讓頁面容器中止滾動時,捕捉並讓其自動滑動到指定元素的指定位置。
一給我哩 giaogiao!這但是很是了不得的特性啊~
它分了兩部分,一部分做用於滾動容器上,一部分做用於相對的滾動子元素上,具體關係以下表:
做用於滾動容器 | 做用於滾動子元素 |
---|---|
scroll-snap-type | scroll-snap-align |
scroll-padding | scroll-snap-stop |
scroll-margin |
scroll-snap-type
屬性指定能不能去捕捉當前滾動的容器並讓它對齊,以及所執行的方向跟嚴格程度。
它可選的方向值有:
它可選的嚴格值有:
咱們來康康這玩意究竟是啥效果:
以上 DEMO 來自於 MDN 的scroll-snap-type
scroll-snap-align
屬性指定捕捉容器要捕捉的捕捉子元素位置。可選的值以下:
效果以下:
以上 DEMO 來自於 Andy Adams 的scroll-snap-align
由於 Scroll Snap 元素會有幾個捕捉的位置,而scroll-snap-stop
能夠控制到達這些位置以後是否被捕獲,仍是到了指定的位置才被捕獲。可選屬性以下:
栗子以下:
以上 DEMO 來自於 MDN 的scroll-snap-stop
scroll-margin
是一個簡寫屬性,跟margin
同樣,有不一樣的邏輯屬性能夠選。它能夠設置元素跟滾動條之間的外邊框大小。咱們看兩個動圖對比下區別。
當咱們點擊#hash
跳轉時。
普通操做:
h3 {
}
複製代碼
添加了scroll-margin-top
:
h3 {
scroll-margin-top: 5rem;
}
複製代碼
上面 DEMO 來自於 Chris Coyier 的Fixed Headers and Jump Links? The Solution is scroll-margin-top
從上面的兩個 DEMO,咱們能夠清晰地對比,假設#hash
導航的元素有修改scroll-margin
,那麼最終跳轉的位置是會以scroll-margin
的值爲邊界的。
不只如此,咱們再看下面的 DEMO:
以上 DEMO 源自於 Andy Adams 的scroll-margin
當咱們設置了scroll-margin
的元素進入 scroll 的可視區域時,瀏覽器會根據當前元素就近的scroll-margin
值,移動到相應的位置。
scroll-margin
的複寫屬性有如下幾個:
scroll-margin-top
scroll-margin-right
scroll-margin-bottom
scroll-margin-left
scroll-margin-block
scroll-margin-inline
scroll-margin-block-start
scroll-margin-inline-start
scroll-margin-block-end
scroll-margin-inline-end
scroll-padding
跟scroll-margin
類型,只不過跟padding
與margin
的同樣,有內外邊距的區別。
來個 DEMO:
以上 DEMO 源自於 Andy Adams 的scroll-padding
scroll-padding
的複寫屬性也一樣有如下幾個:
scroll-padding-top
scroll-padding-right
scroll-padding-bottom
scroll-padding-left
scroll-padding-block
scroll-padding-inline
scroll-padding-block-start
scroll-padding-inline-start
scroll-padding-block-end
scroll-padding-inline-end
overscroll-behavior
是 2019 年 6 月份 W3C 第一次發佈的CSS 過渡滾動行爲模塊 Level 1裏惟一一個屬性。
overscroll-behavior
讓你能夠控制瀏覽器滾動到邊界時的表現。
它也是個簡寫屬性,具體的屬性有:
overscroll-behavior-x
同樣。overscroll-behavior-y
同樣可選的值爲:
栗子以下:
使用了overscroll-behavior: contain;
默認狀況
不知道各位有沒有注意上述各個屬性的值,除了有常規的x
,y
,top
,right
,bottom
跟left
以外,還有四個比較少見的值block
,inline
,start
跟end
。
因此這究竟是什麼呢?
實際上是由於 W3C 爲了照顧到非西文排序國家的書寫習慣,特地修改了 CSS 的邏輯屬性。
對於像咱們國家或者是美國這樣,文檔排列是從上到下,從左到右的,top
、 right
、 bottom
跟 left
就很好理解。
可是像日本或者阿拉伯等書寫排列跟咱們不同的國家,在邏輯上就會有不合理的地方,例如:
padding-left
實際上方向是咱們的padding-right
padding-left
實際上方向是咱們的padding-top
按照上面的狀況,這就比較詭異。因此 W3C 出來新的邏輯屬性,新舊的對好比下:
舊的邏輯屬性 | 新的邏輯屬性 |
---|---|
top | inset-block-start |
bottom | inset-block-end |
left | inset-inline-start |
right | inset-inline-end |
margin-top | margin-block-start |
margin-right | margin-inline-end |
margin-bottom | margin-block-end |
margin-left | margin-inline-start |
border-top | border-block-start |
border-right | border-inline-end |
border-bottom | border-block-end |
border-left | border-inline-start |
padding-top | padding-block-start |
padding-right | padding-inline-end |
padding-bottom | padding-block-end |
padding-left | padding-inline-start |
width | inline-size |
height | block-size |
總結一下就是橫座標爲inline
,縱座標爲block
,起始位置爲start
,結束位置爲end
。
這是一個利用scroll-behavior: smooth
的特性寫出來的效果,以前跟朋友們一塊兒出去玩,咱們進行了許多的活動。其中有一項遊戲就是「你比劃我猜」,做爲策劃者的魚頭,天然不能放過此次機會,遂用技術小秀了一把。
咱們先來看看效果。
源碼地址在這:
因爲代碼太長,就不徹底貼出來了,可是核心邏輯就是利用scroll-behavior: smooth;
來控制#hash
跳轉時的效果,爲了避免污染 url,同時利用了 history api 來維護正常的 url。大概就是醬紫:
let pageIndex = 1;
const urlChangeHandler = event => {
const { newURL } = event;
const current = newURL.replace(/.+\#page\-(\d)/, "$1");
pageIndex = +current;
console.log(pageIndex);
history.pushState(
{},
window.location.href,
window.location.origin + window.location.pathname
);
};
window.onhashchange = urlChangeHandler;
複製代碼
你們也不妨嘗試下用所掌握的姿式增添點生活情趣呀~
吃瓜羣衆:我看完了整篇,沒看到哪裏有跟忍術相關的內容啊?騙我流量,賠錢。
魚頭:沒有又咋啦?說好的寵我,你如今兇我是什麼意思?
若是你喜歡探討技術,或者對本文有任何的意見或建議,很是歡迎加魚頭微信好友一塊兒探討,固然,魚頭也很是但願能跟你一塊兒聊生活,聊愛好,談天說地。 魚頭的微信號是:krisChans95 也能夠掃碼關注公衆號,訂閱更多精彩內容。