咱們常常在手機上看到通信錄列表,這類佈局通常有兩個顯著的效果css
下面咱們來實現一下html
這裏頁面結構很簡單,就是兩個列表前端
<div class="con"> <!--聯繫人列表--> <div class="contacts" id="contacts"> <dl>A</dt> <dt>a1</dt> <dt>a2</dt> <dl>B</dt> <dt>b1</dt> <dt>b2</dt> ... </div> <!--導航列表--> <div class="index" id="index"> <a>A</a> <a>B</a> </div> </div>
而後加點樣式後端
html,body{ margin: 0; height: 100%; padding: 0; } dl,dd{ margin: 0; } .con{ position: relative; height: 100%; overflow-x: hidden; } .index{ position: absolute; right: 0; top: 0; bottom: 0; display: flex; flex-direction: column; justify-content: center; } .index a{ display: block; width: 30px; height: 30px; text-align: center; line-height: 30px; border-radius: 50%; background: cornflowerblue; text-decoration: none; color: #fff; outline: 0; margin: 5px; } .contacts{ height: 100%; background: #fff; overflow: auto; line-height: 2em; } .contacts dt{ background: bisque; font-size: 1.5rem; color:cornflowerblue; height: 2em; line-height: 2em; padding: 0 10px; } .contacts dd{ padding: 0 10px; display: block; cursor: pointer; }
這樣就能夠看到佈局了瀏覽器
https://codepen.io/xboxyan/pe...佈局
吸頂效果其實很簡單,只要用到css中的新屬性position:sticky
就能夠了性能
粘性定位元素(stickily positioned element)是計算後位置屬性爲 sticky 的元素。
兼容性還不錯,至少在移動端能夠放心使用flex
給.contacts dt
加上position:sticky
spa
.contacts dt{ /*添加以下屬性*/ position: sticky; top: 0; }
這樣就實現了每一個類目吸頂效果code
https://codepen.io/xboxyan/pe...
若是不用js,那麼可採用href
錨點的方式來實現定位
具體作法就是
<a href='#A'></a> ... ... <div id='A'></div>
若是整個頁面是能夠滾動的,那麼只要點擊a
,那麼頁面就會迅速跳轉到id=A
的元素上
如今對咱們的頁面添加一些herf
和id
<div class="con"> <!--聯繫人列表--> <div class="contacts" id="contacts"> <dl id='A'>A</dt> <dt>a1</dt> <dt>a2</dt> <dl id='B'>B</dt> <dt>b1</dt> <dt>b2</dt> ... </div> <!--導航列表--> <div class="index" id="index"> <a href='#A'>A</a> <a href='#B'>B</a> </div> </div>
https://codepen.io/xboxyan/pe...
點擊右側的導航按鈕,頁面就能夠快速定位了
等等,好像還有些問題,當往回跳轉時,發現並無徹底展開,好比像調回A
,結果雖然A
標籤出來了,可是,A
下面的列表卻沒有出來
這是什麼問題呢?
通過屢次的研究,發現是position:sticky
搞的鬼!
當往上定位的時候,咱們經過href
定位過去,定位的依據是到該元素第一次可見的位置,此時雖然該元素空壓機了,可是下面的元素沒有展現出來,因此就形成了這樣的問題
發現問題就要解決問題
其實咱們想要定位的還能夠是A
下面的第一個列表元素,可是又不能是該元素,由於若是是第一代元素,當跳轉的時候就會被上面的A
標籤遮住。
因此咱們在二者之間再插入一個標籤,用於定位
以下,添加了<dl class="stikcy-fix"></dt>
<div class="contacts" id="contacts"> <dl>A</dt> <dl class="stikcy-fix" id='A'></dt> <dt>a1</dt> <dt>a2</dt> <dl>B</dt> <dl class="stikcy-fix" id='B'></dl> <dt>b1</dt> <dt>b2</dt> ... </div>
若是直接放在這裏確定會佔空間,因此咱們把他向上位移,而後設置不可見,使該元素恰好覆蓋在原標籤位置
以下
.contacts .stikcy-fix{ position: static; visibility: hidden; margin-top: -2em; }
https://codepen.io/xboxyan/pe...
如今看看,是否是完美跳轉了?
一般咱們在選擇右側索引時,頁面中間會出現一個大寫的字母
這個若是用css實現也比較簡單,用到僞元素的content:attr()
就能夠了,在以前的文章(用純css實現打星星效果)中也講到過
具體實現以下
.index a:active:after{ content: attr(data-type); position: fixed; left: 50%; top: 50%; width: 100px; height: 100px; border-radius: 5px; text-align: center; line-height: 100px; font-size: 50px; transform: translate(-50%,-50%); background: rgba(0,0,0,.5); }
這裏用到了content: attr(data-type)
,因此a
上面要有一個data-type
屬性
<!--導航列表--> <div class="index" id="index"> <a href='#A' data-type='A'>A</a> <a href='#B' data-type='B'>B</a> </div>
其次,實際項目中,咱們須要用js
來生成這些列表
假定咱們要求的數據以下
var data = [ { 'type':'A', 'user':[ { name:'a1' }, { name:'a2' }, { name:'a3' }, { name:'a1' }, { name:'a2' }, { name:'a3' }, { name:'a3' }, { name:'a1' }, { name:'a2' }, { name:'a3' }, ] }, { 'type':'B', 'user':[ { name:'b1' }, { name:'b2' }, { name:'b3' }, { name:'b1' }, { name:'b2' }, { name:'b3' }, { name:'b3' }, { name:'b1' }, { name:'b2' }, { name:'b3' }, ] }, { 'type':'C', 'user':[ { name:'c1' }, { name:'c2' }, { name:'c3' }, { name:'c1' }, { name:'c2' }, { name:'c3' }, { name:'c3' }, { name:'c1' }, { name:'c2' }, { name:'c3' }, ] }, { 'type':'D', 'user':[ { name:'d1' }, { name:'d2' }, { name:'d3' }, { name:'d1' }, { name:'d2' }, { name:'d3' }, { name:'d3' }, { name:'d1' }, { name:'d2' }, { name:'d3' }, ] }, { 'type':'E', 'user':[ { name:'e1' }, { name:'e2' }, { name:'e3' }, { name:'e1' }, { name:'e2' }, { name:'e3' }, { name:'e3' }, { name:'e1' }, { name:'e2' }, { name:'e3' }, ] } ]
這種格式的數據能夠要求後端返回,或者直接前端改造都行
而後對數據進行循環遍歷便可
var indexs = document.getElementById('index'); var contacts = document.getElementById('contacts'); var index_html = ''; var contacts_html = ''; data.forEach(el=>{ contacts_html += '<dl><dt>'+el.type+'</dt><dt class="stikcy-fix" id='+el.type+'></dt>'; index_html += '<a href="#'+el.type+'" data-type='+el.type+'>'+el.type+'</a>'; el.user.forEach(d=>{ contacts_html+='<dd>'+d.name+'</dd>'; }) contacts_html+='</dl>' }) indexs.innerHTML = index_html; contacts.innerHTML = contacts_html;
https://codepen.io/xboxyan/pe...
這部分js
只是生成佈局,沒有任何功能上的邏輯
雖然經過錨點實現列表的快速定位,可是此時瀏覽器的地址欄會加上#A
這樣的標識,一很差看,二在使用瀏覽器默認的返回時會把這些標識所有走一遍,不太方便。
還有一個問題,在滾動列表的時候,無法作到右側索引當前類別高亮顯示,同時右側索引也不支持滑動快速定位。
這些細節問題也只能經過js
來修復了。
不過要是一個簡單的小項目,沒那麼多要求的話,純css
仍是能很好的適用的,性能上絕對要比經過js
滾動監聽強上好多倍,並且引用方便,只要數據生成了就能夠直接使用^^