记录在CSS的使用过程中,越来越深入理解的一些具体应用的积累与总结,持续更新!
等比缩放
最近碰到一个使用CSS绘制正方形的问题,你可能会说这个有什么难得,我想说我的具体需求是一行放3个元素,此时每个元素都要是一个正方形,且自适应手机,手机屏幕越宽,正方形也就越大。项目中使用padding-top解决这个问题。
CSS3中新增弹性盒子模型之后,简直就是CSS前进路上的一大步,对于本人来说,简直就是一个利器,以至于在页面布局的时候第一反应总是使用弹性盒子,以至于那些能用CSS2解决的布局知识,都被我抛弃在脑后了,其实我觉得这也不好吧,因为在PC上极有可能碰见兼容性问题,即便一些问题可以通过增加前缀的方式解决,由于目前主要工作内容为hybird app开发,在移动端兼容性问题并不是那么突出,可能很多原因都是由于手机迭代比较快吧。
存在问题
之前的解决办法为书写了一个heightEqualWidth
指令,指令的代码很简单,具体如下:
.directive('heightEqualWidth', ["$timeout", function ($timeout) {
return {
restrict: 'AE',
link: function (scope, element) {
$timeout(function () {
element[0].style.height = element[0].offsetWidth + 'px';
});
}
}
}])
这里存在的问题是一开始元素是没有高度的,在使用js修改高度之前,页面可能就完成了绘制,同时由于容器是用来绘制canvas的原因,子元素变大,可父元素并没有变大,这里猜测canvas容器不能动态设定高度值
,页面可能会错乱。
百分比参照
margin、padding使用百分比时候参照物的问题
当父元素有宽度的时候,margin与padding的百分比都是相对于其父元素的width而言,padding/margin-top/bottom并不依赖于父元素的height。
绝对定位时top、left百分比问题
不管是absolute或是relative定位,当父元素高度,宽度已知时,left是相对于父元素的宽度width,top是相对于父元素的高度height。
transform:translate(10%,10%)
参照物是要偏移对象本身的宽度widht与height而不是其父元素。
问题解决
有了padding百分比参照物为父容器的宽度时,项目中碰到了问题也就有了新思路,设置父元素的样式如下:
.container{
padding-top: 33%;
position: relative;
}
设置一个子元素作为中间层充满父元素,样式如下:
.middle{
position: absolute;
top: 0;
bottom: 10px;
left: 0;
right: 0;
}
此时中间层的宽高平分给三个子元素,这样一来,三个子元素的就表现为一个自适应宽度的正方形啦,是不是很6!
计算属性
CSS新增的取值函数,主要用户动态计算长度值,将一些工作中需要使用js才能解决的问题,通过这个函数也可以解决了,参数可以是百分比、em、px和rem单位值,如width: calc(100% - 22px)
。甚至可以是vw或者vh,分别表示窗口的宽度和高度,如width: calc(100vw - 100px)
,表示宽度为窗口宽度减去100px。v表示viewport的意思,不知道你有没有惊讶,反正我知道这玩意的时候我是很惊讶的,哈哈。
vw和vh是相对窗口而言,这个很明显,那么使用%比的时候是相对什么而言呢。空说无凭,写个demo测试下就好啦,第一直觉%应该是相对父元素而言,可是会不会和absolute定位一样,是相对第一个具有相对定位属性的父元素而言呢。demo结果表明,%相对父元素而言,且父元素并没有设置相对定位,流式定位也是可以滴。
calc()函数支持 +, -, *, / 运算,可以单一单位 或者 混合单位使用。但是使用中注意运算符号前后需要空格。
盒模型
正常情况下我们设置的容器的宽度和高度,是设置其content的宽高,容器的实际宽高应为content+padding+border。很多时候由于这种情况下,容易造成盒子的溢出,解决移除问题可以通过calc函数解决,也可以通过box-sizing设置计算模式。
语法 content-box | border-box | inherit
- content-box:缺省模式,css设置宽高即为内容区域的宽高,不包括padding和border
- border-box:css设置宽高为content+padding+border
有些人说还有一个padding-box属性,不知道是不是网友想当然还是咋滴,觉得padding-box应该是content+padding。但是实际上我在google浏览器上测试,并且是带有前缀的方式下,padding-box都是没有效果诶。
文本处理
文本溢出显示省略号
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap
允许指定行数,超过显示省略号
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:2;
overflow:hidden
最近在vue项目中发现设置-webkit-box-orient:vertical
后,代码总是不生效,经查阅发现是autoprefixer
的一个小bug,autoprefixer不仅会帮你加-webkit-之类的prefixer, 它还会帮你删除你自己写在 css/sass/less里的样式,关闭autoprefixer的自动删除功能才可以生效
/*! autoprefixer: off */
-webkit-box-orient: vertical;
/* autoprefixer: on */
或者你可以通过增加remove: false这个配置项,全局关闭自动移除功能
postcss([ autoprefixer({ remove: false }) ]);
对于这两个文本处理方式,使用非常频繁,但是并不好记,写起来还啰嗦,我们可以通过 sass 的 mixin 帮助我们简写
// 不换行
@mixin no-wrap {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
// 扩展点击区域
@mixin extend-click {
position: relative;
&::before {
content: '';
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
}
}
@mixin line-number($n: 2) {
display: -webkit-box;
/*! autoprefixer: off */
-webkit-box-orient: vertical;
/* autoprefixer: on */
-webkit-line-clamp: $n;
overflow: hidden;
}
设置了超过两行显示省略号后,如果某些内容只有一行,在流式布局下,这样样式就看上去不对齐,如何保证即使一行内容也有两行的高度呢,这里有个妙用记录一下,即加上如下css
line-height: 1.4em;
min-height: 2.8em;
这里主要利用了em单位相对属性的特点。
内联盒模型
font-size:0妙用
可以用font-size:0来清除间距。比如inline-block的元素之间会受空白区域的影响,也就是元素之间差不多会有一个字符的间隙。如果在同一行内有4个25%相同宽度的元素,会导致最后一个元素掉下来。你可以利用元素浮动float,或者压缩html,清除元素间的空格来解决。但最简单有效的方法还是设置父元素的font-size属性为0。
奇怪的IMG
使用DIV包裹图片,DIV比其包裹的img要大:需要把img设置为block,原因:img是一种类似text的元素,在结束的时候,会在末尾加上一个空白符,所以就会多出大约3px
overflow清除浮动
除了著名的clearfix清除浮动类,利用overflow属性也可以清除浮动。
@mixin clearfix() {
&::after {
display: block;
clear: both;
content: "";
}
}
overflow除了定义溢出元素内容区的内容会如何处理外,还可以做一些有用的事,如:
- 创建块格式化上下文(BFC:Block Formatting Contexts)
- 清除浮动
禁用事件
这是一个很神奇的熟悉哈,找了很久才找到工作中碰到的问题,在Ionic中,模态框出现后会在body元素上添加modal-open
样式,内容为pointer-events: none;
,导致我在模态框的基础上又出现一个ActionSheet组件,但是ActionSheet却无法响应,甚至审查元素都只能直接定位到模态框的DOM,可以我明明设置我的ActionSheet的z-index
比模态框高呀!这是怎么回事呢?后来发现模态框之所以能响应事件,是因为模态框添加了pointer-events: auto;
属性,因此当我在ActionSheet上同样重置pointer-events属性为auto时,一切就都很美好了!
pointer-event属性更像是一个JavaScript事件,利用该属性,可以做如下的事情:
- 阻止任何点击动作的执行
- 使链接显示为默认光标(cursor:default)
- 阻止触发hover和active状态
- 阻止JavaScript点击事件的触发
超牛的 pointer-event(update in 20210327)
- auto:与未指定时的表现效果相同
- none:除了指示该元素不是鼠标事件的目标之外,值 none 表示鼠标事件“穿透”该元素并且指定该元素“下面”的任何东西。
指定为 none 值在有些时候能够发挥巨大的威力,比如你需要在 canvas 上操作,最终会有些效果需要使用到 dom,比如显示鼠标跟随的 tooltip,这时候你就可以设置一个 div 盖在 canvas 上,设置 pointer-event 为 none 值,这样还是可以在 canvas 上绑定事件。
移动端CSS
fixed布局在移动端会有各种各样的问题,还是尽量避开。
解决移动端点击事件延迟(300ms):touch-action: manipulation;
禁止长按文本选中:user-select:none;
禁止触摸点击阴影:-webkit-tap-highlight-color: transparent;
禁止输入框浏览器默认行为:-webkit-appearance:none;
禁止长按弹出列表栏:-webkit-touch-callout:none;
滚动优化
在移动端,如果仅设置了 overflow:auto|scroll,手指离开屏幕就会立即停止滚动,这对于移动端而言很不友好。
控制元素在移动设备上是否使用滚动回弹效果:-webkit-overflow-scrolling
- auto:使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止。
- touch;使用具有回弹效果的滚动, 当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果。继续滚动的速度和持续的时间和滚动手势的强烈程度成正比。同时也会创建一个新的堆栈上下文。
在实际使用中,碰到z-index失效的BUG,在这里列举它可能存在的问题
- 滚动中 scrollTop 属性不会变化
- 手势可穿过其他元素触发元素滚动
- 滚动时暂停其他 transition
- 布局抖动
- 偶尔卡住或不能滑动
- 这个堆叠上下文会导致下面子元素z-index失效。解决办法:添加 overflow:hidden
追踪用户
CSS 是可以出发请求的,因此我们可以使用 CSS 追踪用户相关数据,甚至可以通过 CSS 创建 Key Logger 监听用户的密码。