1、依赖overflow的样式表现
有一种效果就离不开overflow:hidden声明,即单行文字溢出点点点效果。效果的核心是textoverflow:ellipsis。效果实现必需的3个声明如下:
.ell {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
目前,对-webkit-私有前缀支持良好的浏览器还可以实现多行文字打点效果,但是却无须依赖overflow:hidden。比方说,最多显示2行内容,再多就打点的核心CSS代码如下:
.ell-rows-2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
2、overflow与锚点定位
锚点,通俗点的解释就是可以让页面定位到某个位置的点。基于URL地址的锚链(如上面的#1,可以使用location.hash获取)实现锚点跳转的方法有两种,一种是标签以及name属性,还有一种就是使用标签的id属性。
百度百科里是这样表现得
<a href="#1">发展历程></a><!--这是初始点击位置-->
<a name="1"></a> <!--这是目的位置-->
更推荐利用标签的id属性,因为HTML会显得更干净一些,也不存在任何兼容性问题:
<a href="#1">发展历程></a>
<h2 id="1">发展历程</h2>
2.1.锚点定位行为的触发条件
下面两种情况可以触发锚点定位行为的发生:
(1)URL地址中的锚链与锚点元素对应并有交互行为;
(2)可focus的锚点元素处于focus状态。
比方说,点击一个链接,改变地址栏的锚链值,或者新打开一个链接,后面带有一个锚链值,当然前提是这个锚链值可以找到页面中对应的元素,并且是非隐藏状态,否则不会有任何的定位行为发生。如果我们的锚链就是一个很简单的#,则定位行为发生的时候,页面是定位到顶部的,所以我们一般实现返回顶部效果都是使用这样的HTML:
<a href="#">返回顶部></a>
然后配合JavaScript实现一些动效或者避免点击时候URL地址出现#,而很多人实现返回顶部效果的时候使用的是类似下面的HTML:
<a href="javascript:">返回顶部></a>
然后使用JavaScript实现定位或者加一些平滑动效之类。显然我是推荐上面那种做法的,因为锚点定位行为的发生是不需要依赖JavaScript的,所以即使页面JavaScript代码失效或者加载缓慢,也不会影响正常的功能体验,也就是用户无论在什么状态下都能准确地返回顶部
“focus锚点定位”指的是类似链接或者按钮、输入框等可以被focus的元素在被focus时发生的页面重定位现象。举个很简单的例子,在PC端,我们使用Tab快速定位可focus的元素的时候,如果我们的元素正好在屏幕之外,浏览器就会自动重定位,将这个屏幕之外的元素定位到屏幕之中。再举一个例子,一个可读写的输入框在屏幕之外,则执行类似下面的JavaScript代码的时候:
document.querySelector('input').focus();
这个输入框会自动定位在屏幕之中,这些就是“focus锚点定位”。
虽然都是锚点定位,但是这两种定位方法的行为表现还是有差异的,“URL地址锚链定位”是让元素定位在浏览器窗体的上边缘,而“focus锚点定位”是让元素在浏览器窗体范围内显示即可,不一定是在上边缘。
2.2 锚点定位作用的本质
锚点定位行为的发生,本质上是通过改变容器滚动高度或者宽度来实现的。这里说的是容器的滚动高度,而不是浏览器的滚动高度。
锚点定位也可以发生在普通的容器元素上。而且定位行为的发生是由内而外的。如:我们的页面上有一个
.box {
height: 120px;
border: 1px solid #bbb;
overflow: auto;
}
.content {
height: 200px;
background-color: #eee;
}
<div class="box">
<div class="content"></div>
<h4 id="title">底部标题</h4>
</div>
<p><a href="#title">点击测试</a></p>
由于.content元素高度超过.box容器,因此
元素必然不可见,然后,我们点击下面的“点击测试”链接,则滚动条位置变化(实际上改变了scrollTop值),“底部标题”自动出现了。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d925b5e380ac63e7470a6852694bd00b.png)
“由内而外”指的是,普通元素和窗体同时可滚动的时候,会由内而外触发所有可滚动窗体的锚点定位行为。继续上面的例子,假设我们的浏览器窗体也是可滚动的,则点击“点击测试”链接后,“底部标题”先触发.box容器的锚点定位,也就是滚动到底部,然后再触发窗体的锚点定位,“底部标题”和浏览器窗口的上边缘对齐,如图:
其次就是设置了overflow:hidden的元素也是可滚动的,这也是本小节的核心。说得更干脆点儿就是:overflow:hidden跟overflow:auto和overflow:scroll的差别就在于有没有那个滚动条。元素设置了overflow:hidden声明,里面内容高度溢出的时候,滚动依然存在,仅仅滚动条不存在!
即虽然设置overflow:hidden显示鼠标滚动无法滚动,但是发生锚点定位,你就会发现滚动发生了
.box {
height: 120px;
border: 1px solid #bbb;
overflow: hidden;
}
锚点定位本质上是改变了scrollTop或scrollLeft值,因此,上面的定位效果等同于执行了下面的JavaScript代码: document.querySelector(’.box’).scrollTop = 200; // 随便一个足够大的值即可。
基于URL地址的锚链触发锚点定位实现的选项卡切换效果。
HTML和核心CSS代码如下:
<div class="box">
<div class="list" id="one">1</div>
<div class="list" id="two">2</div>
<div class="list" id="three">3</div>
<div class="list" id="four">4</div>
</div>
<div class="link">
<a href="#one">1</a>
<a href="#two">2</a>
<a href="#three">3</a>
<a href="#four">4</a>
</div>
.box {
height: 10em;
border: 1px solid #ddd;
overflow: hidden;
}
.list {
line-height: 10em;
background: #ddd;
}
此效果乍一看很酷,但却有不少不足之处:其一,容器高度需要固定;其二,也是最麻烦的,就是“由内而外”的锚点定位会触发窗体的重定位,也就是说,如果页面也是可以滚动的,则点击选项卡按钮后页面会发生跳动,这种体验显然是非常不好的。有,还记不记得前面提过有两种方法可以触发锚点定位,其中有一种方法就是“focus锚点定位”,只要定位的元素在浏览器窗体中,就不会触发窗体的滚动,也就是选项卡切换的时候页面不会发生跳动。
可以发现,就算页面窗体就有滚动条,绝大多数情况下,也都不会发生跳动现象,HTML和核心CSS代码如下:
<div class="box">
<div class="list"><input id="one">1</div>
<div class="list"><input id="two">2</div>
<div class="list"><input id="three">3</div>
<div class="list"><input id="four">4</div>
</div>
<div class="link">
<label class="click" for="one">1</label>
<label class="click" for="two">2</label>
<label class="click" for="three">3</label>
<label class="click" for="four">4</label>
</div>
.box {
height: 10em;
border: 1px solid #ddd;
overflow: hidden;
}
.list {
height: 100%;
background: #ddd;
position: relative;
}
.list > input {
position: absolute;
top:0;
height: 100%;
width: 1px;
border:0;
padding: 0;
margin: 0;
clip: rect(0 0 0 0);
}
原理其实很简单,就是在每个列表里塞入一个肉眼看不见的输入框,然后选项卡按钮变成
$('label.click').removeAttr('for').on('click', function() { $('.box').scrollTop(xxx); 'xxx'表示滚动数值 });
知道overflow:hidden元素依然可以滚动,除了可以帮助我们实现无JavaScript的选项卡效果外,还可以帮助我们理解一些现象发生的原因。例如,我之前提到过的使用marginbottom负值加padding-bottom正值以及父元素overflow:hidden配合实现的等高布局,在大多数情况下,这种布局使用是没有任何问题的,但是如果使用dom.scrollIntoView()或者触发窗体视区范围之外的内部元素的锚点定位行为,布局就会飞掉,没错,布局就像长了翅膀一样飞掉了。因为,此时容器的scrollHeight(视区高度+可滚动高度)要远远大于clientHeight(视区高度),而锚点定位的本质就是改变容器的滚动高度,因此,容器的滚动高度不是0,发生了与上面无JavaScript的选项卡类似的效果,产生布局问题。
实现自定义的滚动条效果,因为Windows系统下浏览器的滚动条会占据宽度,而且长得不好看,所以就存在实现自定义滚动条的需求,也就是类似移动端的悬浮式滚动条。传统实现都是父容器设置overflow:hidden,然后子元素使用一个大的
最推荐的实现还是基于父容器自身的scrollTop值改变来实现自定义滚动条效果,其好处有如下这些。
(1)实现简单,无须做边界判断。因为就算scrollTop设为-999,浏览器依然按照0来渲染,要想滚动到底部,直接一个很大的scrollTop值就可以了,无须任何计算。例如: container.scrollTop = 99999; 列表滚动了多少直接就是scrollTop值,实时获取,天然存储。传统实现要变量以及边界更新,很啰嗦。
(2)可与原生的scroll事件天然集成,无缝对接。例如,我们的滚动延迟加载图片效果就可以直接应用,因为图片位置的计算往往都是和scrollTop值相关联的,所以传统实现scrollTop值一直是0,很可能导致这类组件出现异常。
(3)无须改变子元素的结构。传统实现为了定位方便,会给所有的列表元素外面包一层独立的
当然,没有哪种技术是万能的,基于改变overflow:hidden父容器的scrollTop实现自定义滚动条效果也有几点不足:一是无法添加类似Bounce回弹这种动效;二是渲染要比一般的渲染慢一些,但大多数场景下用户都是无感知的。