纯css实现手机通讯录
我们经常在手机上看到通讯录列表,这类布局一般有两个显著的效果
- 首字母吸顶
- 快速定位
下面我们来实现一下
页面结构
这里页面结构很简单,就是两个列表
<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 的元素。
兼容性还不错,至少在移动端可以放心使用
给.contacts dt
加上position:sticky
.contacts dt{
/*添加如下属性*/
position: sticky;
top: 0;
}
这样就实现了每个类目吸顶效果
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
滚动监听强上好多倍,而且引用方便,只要数据生成了就可以直接使用^^
纯css实现手机通讯录的更多相关文章
- 演示:纯CSS实现自适应布局表格
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 纯css实现京东导航菜单
纯CSS代码实现导航菜单,推荐在chrome预览! 预览请点击这里:mygithub <!doctype html> <html lang="en"> &l ...
- 使用纯 CSS 实现响应式的图片显示效果
有许多方法可以实现页面里图像的响应式显示(Responsive).然而,我碰到的所有方案都使用了JavaScript.这使我疑惑不用 JavaScript 实现图像响应是否可行. 我提出了下面纯CSS ...
- 纯CSS(无 JavaScript)实现的响应式图像显示
有许多方法可以实现web页面里图像的应答.然而,我碰到的所有方案都使用了JavaScript.这使我疑惑不用JavaScript实现图像响应是否可行. 我提出了下面纯CSS的方案. 它是如何工作的呢? ...
- 谈谈一些有趣的CSS题目(八)-- 纯CSS的导航栏Tab切换方案
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- 一个标签的72变,打造一个纯CSS图标库
每次要用到图标的时候都会到 icono 去copypaste,但每次用到的时候尺寸都各不一样,总是要调整参数,巨烦.当然你可以会想到用zoom.scale来做缩放,但是这样的缩放会使得线宽也变粗了,不 ...
- 利用animation和text-shadow纯CSS实现loading点点点的效果
经常在网上看到loading状态时的点点点的动态效果,自己也用JS写了一个,思路是使用一个计数参数,然后在需要添加点的元素后面利用setInterval一个一个加点,当计数到3时,把点变为一个--写完 ...
- 使用纯CSS实现带箭头的提示框
爱编程爱分享,原创文章,转载请注明出处,谢谢!http://www.cnblogs.com/fozero/p/6187323.html 1.全部代码 <!DOCTYPE html> < ...
- 用纯css改变下拉列表select框的默认样式(不兼容IE10以下)
在这篇文章里,我将介绍如何不依赖JavaScript用纯css来改变下拉列表框的样式. 事情是这样的,您的设计师团队向您发送一个新的PSD(Photoshop文档),它是一个新的网站的最终设计 ...
随机推荐
- Ubuntu 16.04简单配置备忘录
1.几个安装包的地址 1.Linux QQ:https://im.qq.com/linuxqq/index.html 2.网易云音乐:http://s1.music.126.net/download/ ...
- [知乎]ARM 到底是什么
[小宅按]近期公司推出来基于ARM芯片的服务器,本文就一些基本概念,比如ARM, ARM64, ARMv8, ARM7,ARMv7, 64位等让人费解的概念进行了粗浅地分析,涉及的关键字已用粗体标出. ...
- c++ 判断两圆位置关系
对于两圆的位置一般有五种关系: (1) 外离:两圆的半径之和小于两圆圆心距离 (2) 外切:两圆的半径之和等于两圆圆心距离 (3) 相交:两圆的半径之和大于两圆圆心距离,两圆圆心距离大于两圆半径之差 ...
- [luogu5339] [TJOI2019]唱、跳、rap和篮球(容斥原理+组合数学)(不用NTT)
[luogu5339] [TJOI2019]唱.跳.rap和篮球(容斥原理+组合数学)(不用NTT) 题面 略 分析 首先考虑容斥,求出有i堆人讨论的方案. 可以用捆绑法,把每堆4个人捆绑成一组,其他 ...
- [Codeforces 1214D]Treasure Island(dfs)
[Codeforces 1214D]Treasure Island(dfs) 题面 给出一个n*m的字符矩阵,'.'表示能通过,'#'表示不能通过.每步可以往下或往右走.问至少把多少个'.'变成'#' ...
- Django创建mysql数据表流程
在Django项目建好后,在setting.py中设置好mysql连接参数: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysq ...
- 如何使用js在移动端和PC端居中
在手机移动端和PC端控制居中是一个很蛋痛的问题,因为屏幕宽度在变化,所以就不要写死样式,那么我想用JS来控制,灵活的控制宽度,需要注意这三个时候: (1)首先需要在页面刚加载的时候就调用此函数, (2 ...
- nginx动静分离与网关
当我们请求一个网页的时候,可能会加载很多css,js,img等静态文件:一般这些文件是很久都不会变化的,所以我们为了提高页面响应速度,完全可以将这些文件缓存到浏览器中(可以理解为cookie信息),这 ...
- luogu P1399 [NOI2013]快餐店
传送门 注意到答案为这个基环树直径\(/2\) 因为是基环树,所以考虑把环拎出来.如果直径不过环上的边,那么可以在环上每个点下挂的子树内\(dfs\)求得.然后如果过环上的边,那么环上的部分也是一条链 ...
- NSURLSession断点下载
#import <Foundation/Foundation.h> @class XHDownLoadManager; #pragma mark - delegate Method @pr ...