容易使人蒙圈的几个经典css问题_ios


一、CSS篇

1.1 元素默认蓝色边框

​input​​​标签元素(如​​button​​​、​​text​​​ 、​​areatext​​​)的一些事件(如​​click​​​、​​focus​​​等),在很多浏览器下默认会有蓝色边框出现,如把一个普通​​button​​​的​​background​​​和​​border​​​都设置为​​none​​后,触发点击后样式如下:


容易使人蒙圈的几个经典css问题_解决方案_02

这是由元素默认的轮廓线产生的,这是浏览器的一种防护机制,起到突出元素的作用,把它干掉就行了,方法如下:

// 方法1:
outline: none / medium;


// 方法2:
outline-width: 0

1.2 背景透明,文字不透明

我们通常是使用 ​​opacity​​来做背景的透明化处理,该属性被所有浏览器支持,可以大胆使用,透明度从0.0(完全透明)到1.0(完全不透明),​但该方法会使其所有子元素都透明​,此时若只想让背景透明,其他不透明,则可以使用​​rgba​​处理背景:

background-color: rgba( red , green , blue , alpha )

其中这个​​alpha​​ 即设置透明度,取值在0~1之间。​该方法除IE9以下不可用外,其他浏览器均可用​,看一下效果:

容易使人蒙圈的几个经典css问题_ios_03

同理,我们也可以用这个方法把整个背景做透明了,即多写一个​​div​​作为modal层做透明处理,可以明显看到上面文字并未透明:

容易使人蒙圈的几个经典css问题_行内元素_04

上述种效果代码如下:

// html
<section>
<div class="item-pic">
<header class="header1">
<h4>你会微笑放手,说好不哭让我出新专辑</h4>
</header>
</div>
<div class="item-pic">
<header class="header2">
<h4>你会微笑放手,说好不哭让我出新专辑</h4>
</header>
</div>
<div class="item-pic">
<div class="handle-opacity"> <!-- 透明罩 -->
<header>
<h4>你会微笑放手,说好不哭让我出新专辑</h4>
</header>
</div>
</div>
</section>
<style lang="less">
.header1 {
opacity: .6;
}
.header2 {
background-color: rgba(0, 0, 0, 0.45);
}
.handle-opacity {
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.45);
header {
background-color: rgba(0, 0, 0, 0.45);
}
}
</style>

1.3 div内置img元素,底部总有间距

用一个​​div​​​包裹一个​​img​​​,会出现​​img​​​不能完全覆盖​​div​​空间,总会在底边留下一点空隙。

容易使人蒙圈的几个经典css问题_ios_05

这种现象产生的原因是img​​是行内元素,浏览器为下行字符(如:g、y、j、p、q)留下的一些空间,这些字符是会比其他字符多占据底部一些空间(具体以当前字体大小有关),这种规则会影响行内元素img​​标签(其默认垂直对齐方式是依照基线来的,即vertical-align: baseline​​),同样行内元素都会和外部元素留这么一丢丢安全距离。上图右侧就是加了文字的效果,这样就更说明一切了。

现在我们知道这种现象主要是由于下行字符串保护机制和​​img​​是行内元素这两个因素导致的,那解决方案就从这两处入手,整理如下:


  1. div​​设置font-size: 0​​line-height: 0​​,进而行高为0;
  2. img​​设置 vertical-align: top 或者 middle/​​,使其不再以默认基线为对齐方式;
  3. img​​设置 display:block​​,使其变成块级元素。

综上,个人认为方法3是最好用的,方法1不推荐使用。


1.4 元素自动填充上背景色

该现场多在表单输入等场景上会出现,初次看到确实很怪异,效果如图:


容易使人蒙圈的几个经典css问题_ios_06


即当浏览器(chrome)给输入框自动填充内容后,也会自动给输入框带上背景(黄或灰蓝),该问题是由于chrome会默认给自动填充的input​​select​​textarea​​等加上:-webkit-autofill​​私有伪属性造成的,比较好的解决方案就是做样式覆盖,代码如下:

input:-webkit-autofill{
box-shadow: 0 0 0px 1000px white inset !important;
}
select:-webkit-autofill{
box-shadow: 0 0 0px 1000px white inset !important;
}
textarea:-webkit-autofill{
box-shadow: 0 0 0px 1000px white inset !important;
}

比较渣的办法是设置禁止自动填充,但还是别那样做了...


1.5 transform 基数值导致字体模糊

transform作为CSS3最为自豪的属性,已经成为了当前前端开发中不可或缺的方法,但它有个渲染的问题,即当元素设置有transform,且其值为基数或小数,同事其整体高度也有基数时,其内部文字会变模糊,如图:

容易使人蒙圈的几个经典css问题_解决方案_07

上图上模糊状态下的,下图是修正过的,具体原因经查可能是因为transform​​变换会在浏览器上单独创建一个绘画层并重新进行渲染,在此渲染过程中也处理了周围的文字,如果高度为奇数的文字可能会存在半个像素的计算量,浏览器对这半个像素会进行优化渲染,所以边缘会出现模糊的情况。解决方案即:


  1. 不要给transform属性值设置基数和小时值;
  2. 调整整体元素高度不要为基数。


1.6 :last-child 和 :last-of-type

作为CSS常用伪类选择器,​​:last-child​​​经常会被用到,但有时遇到极端情况,它会意外失效,让人摸不着头脑,例子如下:3个​​img​​​标签包裹在​​card​​中,当前需求是使最后一张图的边框呈粉色,代码如下:

// html
<div class="card">
<img
v-for="(item,i) in pics"
:key="i"
:src="item"
/>
</div>
// css
<style lang="less">
.card {
> img {
width: 150px;
margin-right: 10px;
&:last-child {
border: 5px solid pink;
}
}
}
</style>

同理用​​:last-of-type​​也能实现:

.card {
> img {
width: 150px;
margin-right: 10px;
&:last-of-type {
border: 5px solid pink;
}
}
}

效果如下:

容易使人蒙圈的几个经典css问题_解决方案_08

现在要往​​img​​​后加一个​​span​​​,发现​​:last-child​​已失效:

// html
<div class="card">
<img
v-for="(item,i) in pics"
:key="i"
:src="item"
/>
<span>next is ...</span>
</div>
// css
<style lang="less">
.card {
> img {
width: 150px;
margin-right: 10px;
&:last-child {
border: 5px solid pink;
}
}
}
</style>


容易使人蒙圈的几个经典css问题_ios_09

而此时​​:last-of-type​​依然没问题:

容易使人蒙圈的几个经典css问题_ios_10

现在得出结论:


  1. :last-child​​选取一群兄弟元素中的最后一个元素,且最后的这个元素必须是所声明的指定元素(注意2个条件);
  2. :last-of-type​​选取一群兄弟元素中的最后一个指定类型的元素。

可知,​​:last-of-type​​​更严谨一些,不容易产生意外bug,我更推荐使用它。同理适用于​​:nth-last-child(n)​​​和​​:nth-last-of-type(n)​


二、DOM篇

这部分我会叙述一些DOM操作遇到的一些容易被忽视的问题。


2.1 IOS日期显示问题

经常做H5移动端开发的朋友我想对这个问题肯定不陌生,那就是在部门IOS版本(IOS5及以下)中,对以“-”间隔的字符串时间格式的解析是不成功的,比如我们写了这么一个鸡肋时间格式适配器:

function DateFormat(date) {
if(!date) return null;
date = new Date(date);
let Y = date.getFullYear();
let M = (date.getMonth() >= 0 && date.getMonth() <= 8) ? `0${date.getMonth() + 1}` : `${date.getMonth() + 1}`;
let D = (date.getDate() >= 0 && date.getDate() <= 9) ? `0${date.getDate()}`: `${date.getDate()}`;
return `Y-M-D`
}

此时如果在IOS5及以下版本的iphone下,传入 "2019-12-31"就会呈现出 ​​NaN-NaN-NaN​​,而其他IOS版本及安卓系统都是没问题的。

针对上述问题,要做兼容适配,即把以"-"间隔的事件字符串替换成以"/"即可,同样是这个适配器,添加一段代码:

function DateFormat(date) {
if(!date) return null;
if(typeof date === 'string' && date.indexOf('T')!=-1 && date.indexOf('+')!=-1) {
date = date.replace(/-/g, '/').replace('T',' ').substring(0,date.indexOf('.'))
}
date = new Date(date);
let Y = date.getFullYear();
let M = (date.getMonth() >= 0 && date.getMonth() <= 8) ? `0${date.getMonth() + 1}` : `${date.getMonth() + 1}`;
let D = (date.getDate() >= 0 && date.getDate() <= 9) ? `0${date.getDate()}`: `${date.getDate()}`;
return `Y-M-D`
}

2.2 ENTER键使当前页刷新

这个真的很诡异的问题,当在一个表单中执行了ENTER键提交后,如果是打开新页面显示提交结果,则会发现当前表单页面也跟着刷新了,这种体验当然是很糟糕的。经查证,该问题的产生条件为:​​Form​​​中只有一个​​input​​时,此时执行ENTER键会自动提交表单并刷新页面。解决方案也很粗暴,直接在input输入框附近写一个隐藏标签,这样就有2个input了,即避免了产生默认刷新的bug,实例如下:

<form>
<input
type="text"
v-model.trim="searchText"
placeholder="搜索您感兴趣的内容"
@keyup.enter="goSearch"
/>
<input
id="hidden"
type="text"
style="display:none"
@keyup.enter="goSearch"
/>
</form>


扫码关注,不错过任何一个干货


容易使人蒙圈的几个经典css问题_解决方案_11

-- 前端技术江湖 --