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

转眼间,2019年还有不到12个小时就要完全过去,回顾本身这一年来,收获与失落并存。在这最后时刻,发一篇文章送给社区,也送给本身。css

本文摘自这一年来本身在工做中经历的几个比较好的CSS问题(不必定复杂,但我的以为都挺值得一说),这些CSS问题平时不多遇到,即便遇到后也不必定知道解决方案,即便知道解决方案也不必定知道产生的原理,同时也准备了2个JS问题(以前有整理过一篇较长的JS问题文章,在此不作推新)。本文会更新下去,但愿帮到各位朋友。期待您的点赞,谢谢。html

1、CSS篇

1.1 元素默认蓝色边框

input标签元素(如buttontextareatext)的一些事件(如clickfocus等),在不少浏览器下默认会有蓝色边框出现,如把一个普通buttonbackgroundborder都设置为none后,触发点击后样式以下:前端

rgba

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

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

// 方法2:
outline-width: 0
复制代码

1.2 背景透明,文字不透明

咱们一般是使用 opacity来作背景的透明化处理,该属性被全部浏览器支持,能够大胆使用,透明度从0.0(彻底透明)到1.0(彻底不透明),但该方法会使其全部子元素都透明,此时若只想让背景透明,其余不透明,则可使用rgba处理背景:chrome

background-color: rgba( red , green , blue , alpha )
复制代码

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

rgba

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

总体背景透明

上述种效果代码以下:bash

// 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空间,总会在底边留下一点空隙。less

div底部间隙

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

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

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

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

1.4 元素自动填充上背景色

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

默认颜色

即当浏览器(chrome)给输入框自动填充内容后,也会自动给输入框带上背景(黄或灰蓝),该问题是因为chrome会默认给自动填充的inputselecttextarea等加上:-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,且其值为基数或小数,同事其总体高度也有基数时,其内部文字会变模糊,如图:

模糊

上图上模糊状态下的,下图是修正过的,具体缘由经查多是由于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;
      }
   }
}
复制代码

效果以下:

有效

如今要往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>
复制代码

失效

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

有效2

如今得出结论:

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

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

2、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>
复制代码

终于在2020年到来前夕发了一篇比较赶的文章,结束个人2019之旅。本文会一直更新下去,若有不一样看法和问题,请留言指出,期待您的点赞。最后祝您2020好运连连。

相关文章
相关标签/搜索