纯css实现手机通信录

咱们常常在手机上看到通信录列表,这类布局通常有两个显著的效果css

20181016202731.png

  1. 首字母吸顶
  2. 快速定位

下面咱们来实现一下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

20181016204441.png

.contacts dt加上position:stickyspa

.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的元素上

如今对咱们的页面添加一些herfid

<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下面的列表却没有出来

20181016205557.png

这是什么问题呢?

通过屡次的研究,发现是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...

如今看看,是否是完美跳转了?

其余细节

一般咱们在选择右侧索引时,页面中间会出现一个大写的字母

20181017093614.png

这个若是用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滚动监听强上好多倍,并且引用方便,只要数据生成了就能够直接使用^^

相关文章
相关标签/搜索