1、实现非中文字的垂直居中
writing-mode: vertical-lr;
对于非中文的语言中,很容易实现垂直文本。lr 代表 从左到右 (Left to right)
2、用font-size:0 来清除间距
inline-block的元素之间会受空白区域的影响,也就是元素之间差不多会有一个字符的间隙。如果在同一行内有4个25%相同宽度的元素,会导致最后一个元素掉下来(如图)。你可以利用元素浮动float,或者压缩html,清除元素间的空格来解决。但最简单有效的方法还是设置父元素的font-size属性为0。
*{
box-sizing: border-box;
}
.items {
font-size: 0;
> .item {
display: inline-block;
width: 25%;
height: 50px;
border: 1px solid #ccc;
text-align: center;
line-height: 50px;
background-color: #eee;
font-size: 16px; //不要忘了给子元素设置字号
}
}
<div class="items">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
3、用垂直方向的padding来实现等比缩放的盒子
固定图片百分比是一个针对响应式布局很有效的方案,尤其是在移动端,可以说是一个刚性需求。简单来说,就是根据容器的宽度,按照宽高比例自动计算出容器的大小,并且让容器内的如img等子元素自适应宽高。
需求
移动端的商品列表展示,每行显示两个商品,使用懒加载技术来加载商品的缩略图,需求规定了商品必须有序整齐的排列,并且加载时要使用默认图片来占位缩略图,在加载过程中,页面的高度不能有抖动。当然,缩略图是大小是UI固定了比例的,假设比例是4:3;此时,你可能的做法是给图片容器固定高度(图片可能会变形),或者使用JS,利用屏幕的宽度和图片比例计算出图片的高度(要用到JS,要考虑屏幕旋转后宽度的变化)。
解决方案
不妨考虑考虑如下方案,本博客实验室列表页使用了该方案。
图片父容器宽度100%,父容器的高度百分比为:100*3 / 4 = 75% ; 图片absolute并且完全铺满父容器。
.image-aspect-ratio {
width: 100%;
position: relative;
padding-top: 75%;
> img {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
}
<figure class="image-aspect-ratio">
<img src="http://via.placeholder.com/640x384">
</figure>
OK,UI只需要做一张4:3的占位图,然后利用图片懒加载技术来在页面滚动过程中加载商品图片,加载过程中页面完全不会抖动,屏幕旋转后,图片高度也随之变化,没有使用JS,一切完美解决
4、用pointer-event来禁用事件
pointer-event属性更像是一个JavaScript事件,利用该属性,可以做如下的事情:
1、阻止任何点击动作的执行
2、使链接显示为默认光标(cursor:default)
3、阻止触发hover和active状态
4、阻止JavaScript点击事件的触发
//使用该类,任何点击事件将无效
.disabled { pointer-events: none; }
5、用max-width来防止图片撑破容器
针对内容性的文案,图片大小都是未知的,为了防止图片过大而撑破容器,可以通过设置图片的max-width:100%来处理;
img {
display:inline-block;
max-width: 100%;
}
6、用伪类来显示打印时a标签的链接
@media print {
a[href]:after {
content: " (" attr(href) ") ";
}
}
7、未知高度容器的多种垂直居中方法
在已知父子高度的情况下,实现垂直居中是很容易的事。margin , padding,absolute + 负margin , 甚至于 line-height都是可行的方案。这里不再展开,文章主要来介绍在父容器高度固定,自容器高度自适应的情况下,来实现其垂直居中于父级盒子的几种方案。为了使案例更真实,我们来模拟一个垂直居中于页面中的弹出层(modal)。
定义如下模态框的基本样式(部分样式使用bootstrap)
.vh-modal {
height: 640px;
border: 1px solid #ccc;
position: relative;
.vh-modal-content {
min-width: 50%;
max-width: 80%;
background: #fff;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
}
.vh-modal-title {
padding: 20px;
font-size: 20px;
border-bottom: 1px solid #ccc;
text-align: left;
margin: 0;
}
.vh-modal-body {
padding: 20px;
text-align: left;
}
.vh-modal-foot {
text-align: right;
padding: 20px;
border-top: 1px solid #ccc;
}
}
8、(伪)元素占位方案 推荐
利用(伪)元素和display:inline-block的方案来实现垂直居中是我个人常用的也是推荐大家使用的方法。
.vh-modal-1 {
text-align: center; //水平居中
font-size: 0; //消除空隙, 见 https://smohan.net/blog/6gr77h
&::before,
>.vh-modal-content {
display: inline-block;
vertical-align: middle;
font-size: 14px;
}
&::before {
content: '';
height: 100%;
}
}
<div class="vh-modal vh-modal-1">
<div class="vh-modal-content">
<h3 class="vh-modal-title">模态框</h3>
<div class="vh-modal-body">...</div>
<div class="vh-modal-foot">
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
如上图中的::before你也可以使用一个真实的元素代替。
9、absolute + transform方案
使用absolute绝对定位子元素,并且设置其top:50%; left:50%,然后再利用css3的transform: translate(-50%, -50%); 设置负值偏移回来也是一种有效的垂直居中方案,但要注意其兼容性以及不要将子容器置于父容器半个像素的位置上(如500.5px),否则子容器会出现模糊。
vh-modal-2 {
>.vh-modal-content {
//尽可能的不要让该元素的宽度或者高度出现奇数,否则可能会导致模糊
display: inline-block; //为了自适应宽度,可以固定宽度
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
transform法还有一个缺点,就是当子容器高度超出视窗高度的时候,它会被直接截断(如下图),而不是想象中的随着浏览器滚动到顶部而滚动显示完全(模态框的头部被截掉了)。
11、table-cell方案
使用div来模拟table的行为也可以实现垂直居中。缺点是要在子容器外层再包裹一个父元素vh-modal-cell用来模拟table-cell。
.vh-modal-3 {
display: table;
width: 100%;
.vh-modal-cell {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.vh-modal-content {
display: inline-block;
}
}
<div class="vh-modal vh-modal-3">
<div class="vh-modal-cell">
<div class="vh-modal-content">
...
</div>
</div>
</div>
<!--
模拟了table布局
<table style="width: 100%;">
<tr>
<td style="text-align: center; vertical-align: middle;">
类似于直接使用table布局
</td>
</tr>
</table>
-->
12、用counter来模拟/装饰有序清单
就如截图中圈出的那样,类似这种多层级的数字,我们大概第一反应是使用JavaScript循环列表,利用其index拼接而成的。事实上,仅仅使用css的counter属性也可以实现该功能,甚至实现起来更高效。博客的【热门文章】栏目的索引就是使用counter属性实现的。
ol {
counter-reset: decimal;
list-style-type: none; //去掉默认的list-style
li {
&::before {
counter-increment: decimal;
content: counters(decimal, '.') ' ';
}
}
}
就像图上那样,我们很早就已经将counter属性用在真实项目中了,而这仅仅只是counter属性一个简单的使用场景,它甚至可以帮助你完成一个简单的购物车计费场景(如图,当然,真实项目中没有人这么干)。
CSS计数器是CSS2.1中自动计数编号部分的实现。作为由CSS维护的变量,counter属性还有很多有趣的使用场景,具体就不展开了。请参考MDN上的使用CSS计数器章节。
13、用table-layout来控制表格单元格宽度
你也许遇到过给表格设置了宽度,但是不起作用的问题。这是因为单元格的宽度是根据其内容进行调整的。刨根揭底,是因为表格有个叫做table-layout的属性,其浏览器默认值是auto在作怪。当我们把这个值设置为fixed的时候,我们给th/td标签设置的宽度就起作用了。用法很简单:
table {
table-layout: fixed;
width: 100%;
}
14、用user-select来禁用文本选中
在远古时代,如果你不想让别人选中你页面的内容,JavaScript是不可或缺的。而在文明社会中,只需要一句user-select:none的CSS样式就可以解决。IE6-9不支持该属性,可以通过给body添加 onselectstart="return false;"的内联JavaScript语句搞定。
body{
user-select: none; //页面中的文本不能被选中
}