URL錨點HTML定位技術機制、應用與問題

by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=3591

1、錨點是什麼

錨點就等同於火影中的「飛雷神之術」,咱們先看百科中錨點的解釋:html

使用命名錨記能夠在文檔中設置標記,這些標記一般放在文檔的特定主題處或頂部。而後能夠建立到這些命名錨記的連接,這些連接可快速將訪問者帶到指定位置。
建立到命名錨記的連接的過程分爲兩步。首先,建立命名錨記,而後建立到該命名錨記的連接。web

再看看「飛雷神之術」的解釋:瀏覽器

日本動漫《火影忍者》中時空術的一種,S級。利用標記完成空間穿梭。ide

飛雷神之術 張鑫旭-鑫空間-鑫生活

都是作標記,而後快速定位。說不定AB(岸本齊史)也是個網頁製做愛好者哦!wordpress

其實,關於錨點,我3年前就寫過一篇針對性文章:「關於錨點跳轉及jQuery下相關操做與插件」,不過內容略浮躁,都是偏表象、偏基本應用層面的東西;這裏仍是關於錨點,探討的內容可能更深層次一點。佈局

其實web頁面上還有一種定位,稱爲「focus定位」,也稱「聚焦定位」,當頁面上控件,例如文本框、單複選框、按鈕等在『可響應聚焦狀態』下,經過相似label for或JS ele.focus()觸發焦點選中狀態的時候,也會發生定位。這個之後有機會探討,這裏,專一錨點定位。學習

//zxx: ① 非disabled狀態,同時沒有應用visibility:hidden以及display:none等CSS聲明。其中,單純應用pointer-events:none的控件元素是能夠被focus的,pointer-events:none的做用更多相似徹底穿透,而非不可用。測試

② 我只在Chrome瀏覽器下作過完整測試,至於IE6這些奇葩,按照以往經驗,也應如此。但IE6的尿性你們都嘗過的,我不100%保證,你們自備照妖鏡。動畫

2、web網頁中錨點定位的觸發

當下,錨點定位的應用通常有:
href="#"返回頂部;或者文章較長時候的標題索引,相似下面:
錨點與頁面間內容快速定位 網站

這類應用每每都是經過點擊觸發的,因而,不免的,咱們可能就很簡單地認爲錨點定位的觸發是經過點擊事件。

而實際上,這種順勢而然的理解相似於古人理解爲太陽繞着地球轉同樣,是有失偏頗的。

我我的認爲,錨點的定位是經過瀏覽器URL地址的hash觸發的。

hash?

CSSer們可能對hash這個名詞不感冒,hash中文通常翻譯爲「哈希」,爲方便記憶,你也能夠讀做「拉稀」。Hash是程序中很是重要以及常見的概念,能夠實現內容的快速查找,這一點跟錨點很相似。

JS中,並無專門的hash的說法(雖然object幹了相似的活)。可是,有一個地方,確是實打實、正兒八經出現了hash!這就是location.hash.

例如,某頁面的URL是:

http://this.summer.io/is/#hot    // location.hash → #hot

則,location.hash值就是#hot.

這裏#hot再URL地址中是有個專有名詞的,叫什麼來着? 協議?主機?域名?路徑?擦,顯然都不對!罷了,你們就叫「哈希」吧;恩,彷佛太生僻了,那叫「拉稀」吧;額,好像又難聽了點,就叫「錨鏈」吧。

畫性大發,畫個抽象派的圖吧。

錨鏈和錨點的基友關係 張鑫旭-鑫空間-鑫生活

上圖很抽象地暴露了錨鏈和錨點的基友關係。也就是說,頁面之因此能定位到錨點所在位置,都是由於URL地址中的錨鏈的做用,而不是點擊行爲。最好的證據就是,當從新載入帶有錨鏈的頁面時,錨點依然會被定位。

瞭解錨點定位的觸發源有助於咱們實際應用時候問題的規避等處理。

3、web錨點定位的機制

帷幕漸漸拉來,高潮慢慢到來。

做爲頁面製做開發人員,錨點定位必定都有用過④。然,就跟打飛機同樣,你們都會打,也打得來;可是,可能就沒想過這飛機運動的機制什麼,我是否是從中發現什麼,而後開個掛,秒了衆多好友。我想,錨點定位可能也是如此。今天,我就說說我對錨點定位機制的理解。

//zxx: ④ 若是你睜大懵懂的雙眼,楚楚可憐的看着我說,「主啊,我沒用過錨點定位誒」;那麼,我請你,去超市買包「炫邁口香糖」,一遍嚼炫邁口香糖,一邊點擊本頁面右下角的返回頂部,直到沒有味道,或者頁面URL地址後面出現#爲止。

1. 錨點定位他丫就是滾牀單
錨點定位的機制就是滾牀單

不要邪惡,這裏的滾牀單就是滾牀單,比方說下面的這位狗兄:
狗狗滾牀單 滾啊滾

牀單即頁面中可滾動的元素,汪星人則是該元素內部的的錨點元素,錨點定位就是汪星人滾牀單。噢啦!

OK,注意這裏的兩個重要條件:
❶. 元素可滾動;
❷. 錨點元素在內部;

換句話就是無滾動則無定位!此話務必牢記。

舉個普通的板栗:
舉個栗子

夏天很熱,由於妹子們衣服穿的少,以下HTML:

<img id="hot" src="http://image.zhangxinxu.com/image/study/s/s512/mm1.jpg">

因而,當含有#hot地址的時候,妹子圖片就會頂着瀏覽器窗口上邊緣顯示了(若是滾動距離足夠,比方說1920寬的顯示器只能滾動一點)。

您能夠狠狠地點擊這裏:夏天很熱,由於妹子穿的少demo

瀏覽器上邊緣顯示 張鑫旭-鑫空間-鑫生活

之因此美女圖片會瀏覽器窗口頂端顯示,是由於其父元素存在滾動條,能夠滾動。

錨點定位的本質就是修改容器的滾動高度;若是父容器無滾動,則錨點定位就是失效的命,再舉個有滾動條但不滾動的例子。

您能夠狠狠地點擊這裏:父容器無滾動錨點定位失效demo

美女圖片的idhot, 以下截圖(img#hot…):
id爲hot截圖示意 張鑫旭-鑫空間-鑫生活

URL錨鏈也是#hot, 可是,美女卻沒有被錨上去,而是,傻傻地看着你,看着你……
錨鏈是#hot

爲什麼呢?下面源代碼示意可能會告訴你答案:

body,
html {
    height: 100%;
    margin: 0;
    overflow: hidden;
}
.container {
    height: 100%;
    overflow: auto;    /* 滾動條來自這裏 */
}

目標圖片在滾動容器以外 張鑫旭-鑫空間-鑫生活

本demo的滾動其實是由container這個div產生的,而idhot的這張圖片在container以外,所以,錨點定位圖片是沒法上移的,由於圖片父級木有可滾動的容器。

2. 雙滾動條定位機制
咱們還可能遇到這樣的狀況,即錨點元素有兩個父容器有滾動條,比方說我博客後臺頁面,滾動條的表哥表姐都出現了:
滾動條的兄弟姐妹們

不知有沒有想過這個問題,這種狀況下,元素錨點定位,是先改變爺爺的滾動高度呢仍是爸爸的滾動高度呢?小demo可參見這裏

目前,我還沒想出100%證明的實驗方法(由於父親和爺爺的定位是一瞬間完成的,沒法經過計算獲知),不過,從理解上,我的認爲計算是從裏面發起的,緣由有兩個:
首先,若是先計算最外容器,可能就會存在一種裏外裏3次計算的狀況。

//zxx: 下面的研究與探討多半沒有實際價值,實用主義派能夠繞開幹你的活去。

demo頁面的狀況,不管內外先計算,都是兩次就完成,由於,最後定位的結果是,圖片上邊緣/內滾動容器上邊緣/瀏覽器可視區域上邊緣三者對齊。換成容易理解的解釋:柯南,毛利蘭,小五郎在死人的時候會聚在一塊兒(錨點定位對齊),假設嫌疑犯A讓柯南和毛利蘭在一塊兒(內滾動定位),嫌疑犯B可讓毛利蘭和小五郎在一塊兒(外滾動定位)。則不管是嫌疑犯B先行動,仍是嫌疑犯B先行動,最後都是三者在一塊兒,都是2步完成。

可是,存在這樣一種狀況,錨點元素在滾動容器的負左上距離處或底部(即沒法讓元素滾動到頂部),以下截圖:
錨點元素在內部滾動容器的底部

此時,定位的最後結果不是圖片上邊緣/內滾動容器上邊緣/瀏覽器可視區域上邊緣三者對齊了。而是,圖片上邊緣,內部容器的半部分以及瀏覽器可視區域上邊緣三者對齊。見下:
容器折半對齊

此時,若是外部先計算,則須要3步了——外部滾動條不知道內部滾動應當定位的狀況,其只能讓內部容器上邊緣和瀏覽器對齊(或乾等);內部定位;外部發現位置不是本身所想,再次調整!

顯然,這種狀況,要先內部能夠肯定滾動位置的先偏移,而後在父級容器;

再者,咱們滾輪鼠標觸發滾動的時候,老是裏面的先滾,滾不動了才滾外部滾動條;雖然有些牽強,但,隱隱中能夠感覺到那種由內而外的調調。

再囉嗦點廢話,有人可能會疑問,這誰先計算壓根就沒有研究的意義吧,你研究這個的目的是什麼呢?

這個問題乍聽上去沒什麼問題?實際上,多少隱射出中國這個大環境浮躁與功利性的心態。

做爲職業人,學習帶有功利性其實也沒什麼很差;商業須要什麼,什麼學習有商業價值,我去學習之,沒什麼很差,你們都須要養家餬口的。可是,要是全部人都這個心態,怕不是什麼好現象。

我之因此研究「內外滾動誰先計算」,真沒什麼目的,我就只是好奇,我就是但願獲得一個正確的結論。私心確定有,我但願本身在尋找結論的過程當中,得到一些意外的知識與結論,經過深刻的思考,走在別人不曾走過的道路上;固然,也但願獲得我想要的結論,而不關心是否有價值。即單純的研究心態。

研究這個東西,原本就不該該爲了某個目的而去作,不然就是功利性研究,這就是爲什麼中國科研爛到一坨屎的緣由之一。牛頓哥哥被蘋果砸,他就是好奇,爲什麼蘋果砸我,因而他去研究,你說他研究蘋果爲什麼往下掉有什麼目的嗎?難道要向蘋果報仇?在中國,鮮有人會研究蘋果爲什麼往下掉,可能會有不少人會研究怎麼讓蘋果長得像西施同樣好看——有錢賺啊!

我以爲咱們作技術研究,大可鄙棄「研究這個有什麼價值」這個功利性的思考,喜歡什麼,好奇什麼,就去研究什麼,價值?目的?等研究結束了,可能會有更深遠的價值。

但話說回來,上頭拿錢給你,確定不是想讓你搞些無用的研究的。所謂人在江湖漂,哪有不挨刀。每人心中都有本身的一杆秤,該如何作仍是本身決定。

3. overflow:hidden下的錨點定位
首先,你們要明確一點,overflow:hiddenoverflow:auto/scroll的差異就在於有沒有那個滾動條。元素overflow:hidden了,裏面內容高度溢出的時候,滾動依然存在,僅僅滾動條不存在

下面這種GIF動畫演示了錨點元素如何經過滾動高度的改變定位到滾動容器上邊緣的;該動畫適用於有滾動條以及沒有滾動條的狀況。
錨點定位的gif動畫示意 張鑫旭-鑫空間-鑫生活

我這裏屢次強調overflow:hidden沒有滾動條這種狀況,不是由於今天週五心情好,而是由於一些高級應用以及奇怪問題出現(參見後面)都是在overflow:hidden條件下。

正如上面反覆提到,錨點定位本質就是滾傳牀單。所以,若是元素在滾動容器的左上角區域及其以外,顯然滾不動,天然也沒有錨點定位的效果!可是,若是元素在滾動容器的右下方及其以外,滾動條就是用來滾動右下溢出內容的,所以,這類元素能夠被錨點定位。

以上結論略含糊,後面的例子會讓你清楚我在說什麼的。

4、錨點定位機制下的應用

錨點定位機制的最經典應用就是「無JavaScript實現選項卡輪轉切換效果」。

1
2
3
4

若是您以爲此頁面上看此效果有干擾(錨點跳來跳去,好討厭哦),能夠狠狠地點擊這裏:無JavaScript實現的切換效果demo

若是您理解上面那句「錨點定位本質就是滾動」的含義,則上面的效果就很好理解了。

點擊下面這個按鈕,把上面容器從overflow:hidden改爲overflow:auto,親自滾滾牀單,您就會知道怎麼回事了(參考上面GIF的定位示意圖)!

overflow:hidden其實是個障眼法,裏面的選項卡列表們由於錨點定位而一個一個滾動到容器上邊緣了,就造成了「選項卡切換」效果。

上面的例子由於是垂直滾動,所以,容器定高了;咱們還能夠改爲水平滾動,讓列表們水平排列,也能夠實現相似的效果。

一樣的,圖片列表那種滑來滑去瀏覽的效果,咱們也能夠藉助錨點;固然,使用錨點是爲了讓JS掛掉時候依然可用。實際,咱們要組織錨點默認的行爲的,由於——這種跳來跳去的效果不是平滑滴。//zxx: 據我親自測試,Chrome實驗性質的平滑滾動並不適用於錨點跳轉

5、:target僞類與錨點的配合

在CSS2的時代,錨點的應用並非很普遍,或者說不被看好與關注,很大一部分緣由在於沒有CSS這個好幫手輔助。CSS3中有個名外:target的僞類選擇器,我跟大家講,這但是個好東西。沒有:target錨點就像30年前的甲魚,送人都沒人要;有個:target,錨點的應用開始走上香餑餑之路,潛力與價值立馬彰顯。若是不是還有半壁的IE6-IE8瀏覽器,我必定大力推崇:target僞類與錨點技術。

好了,吹噓的話語講完了,究竟是真是假,舉個例子讓你們明鑑下。我常常會去中國天氣官網看4-7每天氣預報(影響個人釣魚計劃),其中有個「查看將來4-7每天氣」的按鈕(見下圖),其href地址是#, 交互式JS實現的,並且JS在底部加載,且該網站加載速度較慢。因而,差很少頁面呈現的前半分鐘,我點擊這個按鈕都是徒勞的,反而是出觸發了#的返回頂部功能,更多天氣不出來——很是糟糕的體驗。

其實,要提升體驗很簡單,JS咱們保留,HTML和CSS稍做修改,檔次立馬不同!

小二,給我上盤demo過來~

好嘞,客官,您能夠狠狠地點擊這裏::target與錨點元素顯示隱藏效果demo

點擊demo中「查看4-7每天氣」能夠瀏覽展開與收起效果,以下gif動畫截圖演示:
查看與收起4-7每天氣預報演示 張鑫旭-鑫空間-鑫生活

此效果徹底HTML+CSS實現,JS醬油。此方法與「複選框顯示隱藏控制法」並稱新時代CSS顯隱技術兩大神器。

:target僞類能夠表示URL錨鏈對應的元素被錨中時候的狀態。例如,點擊「展開…」按鈕後,錨鏈是"#7d",則此時,就能夠激活錨點元素:target選擇器,例如:

<div id="7d" class="weatherYubao"></div>
.weatherYubao:target {} /* 我終於執行啦! */

:target僞類的顯隱控制比單複選框要靈活不少,由於其能夠不只能夠經過兄弟選擇器控制樣式,還可使用父子選擇器(如本demo),且推薦使用父子選擇器能夠作更多精確的控制(展開與收起的狀態等)。

.weatherYubao:target #weatherYubao2 {
    display: block;
}
.weatherYubao:target ...

可是,不足也顯而易見,觸發定位,即頁面的scroll滾動會改變⑤,略影響體驗。但,這只是JS還沒有載入完畢的交互體驗加強之法,實際仍是要藉助JS組織默認行爲的。所以此技術大可以使用,由於是純JS方法上的改進。

//zxx: ⑤ 若是您有錨鏈改變,但頁面不滾動的方法,歡迎分享

:target僞類選擇器IE9+, 以及其餘現代瀏覽器支持。但,這並不影響該技術的使用,由於是純JS方法上的改進。

6、錨點定位機制產生的問題

好的影視做品是要有波瀾起伏的,到目前爲止,展現的都是錨點定位的正面形象,如今,有必要曝光下錨點定位機制對交互實現形成的影響。

根據上面的介紹,理論上,咱們能夠藉助:target僞類以及CSS3 transition或者animation實現動畫效果。

比方說上面的查看4-7天氣demo,咱們再稍做調整~

小二~
懂的,客官,來了~

客官,您能夠狠狠地點擊這裏::target僞類與錨點元素的動畫顯隱demo

爲展現平滑效果,截了個視頻:

變化很簡單,display:none/block顯隱,改爲height值控制的隱藏。

#weatherYubao2 {
    height: 0px;
    overflow: hidden;
    transition: height .35s;
}
.weatherYubao:target #weatherYubao2 {
    height: 300px;
}

喲,不錯哦。那有什麼問題呢?

我想實現上面1,2,3,4選項卡從下往上slide動畫效果,能夠不?

按照咱們常規實現slide向上相關的思路,應該是從translateY(100%)translateY(0%)的變化,咱們來試試~

IE10+以及其餘現代瀏覽器下,您能夠狠狠地點擊這裏:常規slideup思路下demo

可是,demo頁面的效果很奇怪,點擊那個選項卡,元素上去了,而後就不見了,咋回事?

博主,是你這個demo作的有問題吧!?

非也非也!仍是上面那個demo,咱們其餘什麼都不修改,就把從下往上進入的slide動畫效果改爲從上往下,也就是動畫方向從改爲

IE10+以及其餘現代瀏覽器下,您能夠狠狠地點擊這裏:常規slidedown思路下demo

您會發現:「喲,這裏效果挺正常的嘛~~」。

正常的slidedown動畫效果截圖 張鑫旭-鑫空間-鑫生活

真的就translateY(100%)改爲translateY(-100%)這一點點的差別(不信諸位能夠右鍵源代碼查看),那爲什麼向上效果嗝屁;而向下效果倒是好的呢?

其實我上面已經給了答案了,上面曾說過下面這段話:

若是元素在滾動容器的左上角區域及其以外,顯然滾不動,天然也沒有錨點定位的效果!可是,若是元素在滾動容器的右下方及其以外,滾動條就是用來滾動右下溢出內容的,所以,這類元素能夠被錨點定位。

slidedown效果是元素從容器的上面往下出現,在觸發錨點定位的時候,這個元素是沒有定位的。可是,slideup是從下面開始,在執行CSS的translateY(100%)的一瞬間,實際上一個等高的滾動條已經出現,錨點定位因而被觸發,元素被上移一個身位;而後slideup動畫觸發,因而,元素跑到了容器以外,不可見了,這就是slideup demo中元素莫名向上的緣由。

文字解釋蒼白,看下面的分解示意圖:

如何解決此問題?
很簡單,兩個字:「延時」!

slideup效果是從translateY(100%)translateY(0%),其效果不能準確呈現的終極緣由就是translateY(100%)形成的滾動和錨點定位偏移滾動同一時間出現形成了衝突!

避免這個問題很簡單,咱們只要讓動畫效果,尤爲code>translateY(100%)的應用延時,CSS是能夠搞定的。

有必要來一發,您能夠狠狠地點擊這裏:延時解決slideup和錨點定位衝突demo

您會驚訝地發現,已經幾乎徹底真實的slideup效果,以前的選項內容向上隱藏,新點擊的內容從下出現顯示。
動畫過程當中的效果截圖 張鑫旭-鑫空間-鑫生活

因而,純CSS實現帶slide動畫效果的選項卡完美呈現。相關CSS代碼以下(省略私有前綴, .05s表延遲時間):

@keyframes slideupin {
    0% {transform: translateY(100%); }
    100% { transform: translateY(0%);}
}
.list{
    ... position:absolute;
    transform: translateY(-100%);
    transition: transform .35s .05s linear;
}
.list:target {
    z-index: 1;    /* 最上面顯示 */
    transform: translateY(0%);
    animation: slideupin .35s .05s linear forwards;
}

7、將來高端流行技術之一:錨點技術

其實,當下,錨點技術就能夠在實際項目中大規模使用了,不過其身份是「CSS效果加強」,即更強的CSS action效果。咱們依然保留JS在交互中的主導地位,可是同時完美融合CSS+HTML的錨點技術——JS只要return falseevent.preventDefault()組織了默認行爲就不要擔憂CSS會搶佔本身的王位。

然,融合與兼顧必然會存在一些細節上的問題。這些問題即便我如今拿出來說,其實也是秋風掃落葉,無人問津,時機很重要。

我一貫推薦看問題要面向將來。雖說,最爲錨點技術最核心的:target僞類目前IE6-IE8瀏覽器不支持,阻礙了其繁榮昌盛。可是,在不久的未來,或許就1~2年時間,新畢業的小朋友可能就以爲咱們這些還拿IE8說事的叔叔阿姨們太凹凸曼了!

凹凸喵

舉個簡單例子。比方說微博這個產品,09年10年出來的,不管是新浪的,仍是騰訊的。網頁的效果、圖形化東西等主要是經過圖片加強的,而不是CSS加強;到了當下,視網膜等設備對網頁有個更高的要求,圖片加強的網頁有種鮮花插牛糞的感受。因而,後面的結果是——專門作一個獨立的針對移動設備的版本!

其中要看清兩點:
其一,這些公司大,資源豐富,另開個新項目,尤爲是網頁這個短時間項目,肥豬身上割塊肉,仍是能跑能跳的。可是大多數公司中小企業,加上國家坑爹的政策,這些企業活得很辛苦,資金很緊張。你說web項目還不容器上了一段時間,爲了iPad瀏覽器效果,又專門搞個移動版本,其中的開發、推廣等人力成本可想而知,錢就這樣被燒掉了。可是,若是從面向將來的角度作產品,比方說技術這一塊,之後所節約的成本可能會至關驚人。
其二,這些公司大,可是作事相對不靈活。畢竟用戶基數大,一個網站從圖片加強改成CSS加強,這個擔子誰都擔不起。只能作新的版本。可是,中小企業不同。這些公司產品爲了面向將來而做必定的犧牲與捨棄是徹底能夠,並且應該如此。例如嘗試響應式佈局、或者大量應用面向將來的一些技術,好比本文展現的錨點技術,在此基礎上作JS加強。因而,3年後,到了一個新的設備時代,這個網站尼瑪儼然成爲流行之先驅了。

學習馬雲,高瞻遠矚,把握將來。

8、結尾滾牀單時間

進入新環境,須要時間適應,例如新的時間規劃安排等,技術的學習與博客更新會慢慢進入正常。擦,忽然想起來,忘記探討一個重要的問題了,爲什麼href="#"點擊後,觸發的效果是回到頁面頂部呢?對於這個問題,您怎麼看呢?不妨咱們一塊兒探討下(評論、郵件都可)~~

最後再補充兩個小tip:
1. F5刷新不會觸發錨點定位,在Chrome瀏覽器下,這個過程由三部曲完成:首先,滾動高度爲0;其次,錨點定位高度;最後,還原成刷新以前滾動條的滾動高度。您也能夠本身F5試試,會看到滾動條明顯的重定位。
2. 連續按F5,或者說長按F5,則彷佛等同於Ctrl+F5, Chrome瀏覽器以及IE瀏覽器都是如此。

很久沒寫東西了,因此可能話癆了點,能靜心讀到這裏的朋友們我雙手合一,表示誠摯的感謝!另外,文中有些觀點結論都是本身感性認識,可能存在不許確之處,歡迎大力指正。

但願本文的內容可以對您的學習有所幫助。

哦,快12點了,滾牀單時間到了……

原創文章,轉載請註明來自張鑫旭-鑫空間-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=3591

(本篇完)

相關文章
相關標籤/搜索