CSS 日常开发问题集锦(含H5)

1,240 阅读6分钟

关键词:FAQ 飞行手册

绝对定位元素与非绝对定位元素的宽高百分比计算的区别

绝对定位: 宽高百分比相对于临近的 position 不为 static 的祖先元素的 PaddingBox 计算。

非绝对定位元素: 宽高百分比相对于父元素的 ContentBox 计算。

style 标签写在 body 后与 body 前有什么区别?

写在 body 后会出现页面闪烁问题。

首先页面加载自上而下,写在body标签后由于浏览器以逐行方式对HTML文档进行解析,当解析到写在尾部的样式表(外联或写在style标签)会导致浏览器停止之前的渲染,等待加载且解析样式表完成之后重新渲染。

如何水平垂直居中

水平垂直居中

  • 绝对定位(margin/transform/inline-block)
  • flex
  • grid
/* margin auto 方法 */
div {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  /* 固定宽高 */
  width: 300px;
  height: 300px;
  margin: auto;
}

/* margin 宽高一半 或者 translate */
div {
  position: absolute;
  width: 500px;
  height: 300px;
  top: 50%;
  left: 50%;
  /*外边距为自身宽高的一半*/
  margin: -150px -250px;
  /* 或者 利用 translate */
  /* transform: translate(-50%, -50%); */
}

/* text-align 方法 */
.wrap {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  text-align: center;
  vertical-align: middle;
}

.wrap::after {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}

.box {
  display: inline-block;
  width: 500px;
  height: 400px;
  background-color: pink;
  white-space: normal;
  vertical-align: middle;
}

/* flex */
.container {
  display: flex;
  align-items: center;
  justify-content: center;
}
.container div {
  width: 100px;
  height: 100px;
}

/* grid */
.wrap {
  background-color: rgba(102, 103, 171, 1);
  width: 100px;
  height: 100px;
  overflow: hidden;
  resize: both;
  /*  key code  */
  display: grid;
  place-items: center;
}
.center {
  background-color:rgba(245, 223, 77, 1);
  width: 60px;
  height: 20px;
  border-radius: 5px
}

li 与 li 之间有看不见的空白间隔是什么原因引起的?有什么解决办法?

问题的本质是 inline-block 元素间间距换行写会占用一个字符的宽度。

不仅仅是 li 会有这个问题。

<!-- 无空白 -->
<li>测试一下</li><li>测试一下</li><li>测试一下</li>
  
<!-- 有空白 -->
<li>测试一下</li>
<li>测试一下</li>
<li>测试一下</li>

解决方法:

  1. 塞在一行写。不足:代码不美观
  2. float: left 设置浮动。不足:有些业务场景不能使用浮动。
  3. ul 设置 font-size: 0,重新再 li 设置字符大小。不足:Safari 依然会出现空白间隔
  4. 推荐 ul 设置 letter-spacing: -8px,重新设置 liletter-spacing: normal

清除浮动

.clear::after {
  content: '';
  display: block; 
  clear: both;
  overflow: hidden;
  height: 0;
}

如何修改 chrome 记住密码后自动填充表单的黄色背景?

chrome 表单自动填充后,通过审查元素可以看到 chrome 默认给表单加上了 input:-webkit-autofill 私有属性,并且写入了样式。

/* chrome 自动写入的样式 */
input:-webkit-autofill {
  background-color: rgb(250, 255, 189) !important;
  background-image: none !important;
  color: rgb(0, 0, 0) !important;
}
/* 解决方案:使用足够大的纯色内阴影来覆盖样式 */
input:-webkit-autofill,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-box-shadow: 000px 1000px white inset;
  border: 1px solid #CCC !important;
}

单行/多行缩略

两栏布局

三栏布局

自定义表单组件

单选、复选、输入框

多行文本展开收起

修改选中文本的样式::selection

多行文本收起展开

图片适配容器大小,等比例缩放

打字特效

图片马赛克效果

让页面里的字体变清晰,变细用 CSS 怎么做?

MDN 字体平滑

webkit 实现了 -webkit-font-smoothing

Firefox 实现了 -moz-osx-font-smoothing

div {
  font-smooth: always;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

H5 overflow:scroll 不能平滑滚动的问题怎么处理?

结合使用两种方案

  • 设置 -webkit-overflow-scrolling: touch;,但是可能导致固定定位的元素随着页面一起滚动
  • 设置 overflow,外部设置 hidden,内容元素为 auto
div {
  /* 当手指从触摸屏上移开,会保持一段时间的滚动 */
  -webkit-overflow-scrolling: touch; 
  /* 当手指从触摸屏上移开,滚动会立即停止 */
  -webkit-overflow-scrolling: auto;
}

body {
  overflow-y: hidden;
}
.wrap {
  overflow-y: auto;
}

H5 iOS 上拉边界下拉出现白色空白

iOS 手指按住屏幕上下拖动会触发 touchmove 事件。这个事件触发的对象是整个 webview 容器,容器被拖动,剩下的部分就会成空白。 解决方案:

  • 监听事件禁止滑动
document.body.addEventListener('touchmove', function(e) {
    if(e._isScroller) return;
    // 阻止默认事件
    e.preventDefault();
}, {
    passive: false
});
  • 将下拉出现白色空白做成功能,比如下拉刷新

H5 固定定位在 android 下无效怎么处理?如何限制页面缩放?

因为移动端浏览器默认的 viewport 为 layout viewport。 在移动端显示时,因为 layout viewport 的宽度大于移动端屏幕的宽度,所以页面会出现滚动条左右移动,fixed 的元素是相对layout viewport 来固定位置的,而不是移动端屏幕来固定位置的,所以会出现感觉 fixed 无效的情况。

<meta name="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"/>

设置该属性还能解决一个问题:限制页面缩放。HTML 本身会产生放大或缩小的行为,通过设置就能控制缩放。

H5 click 点击事件延时与穿透

监听元素 click 事件,点击元素触发时间延迟约 300ms。

解决方案:

import FastClick from 'fastclick';

FastClick.attach(document.body, options);

H5 软键盘将页面顶起来、收起未回落问题

布局中会有个固定的底部。安卓一些版本中,输入弹窗出来,会将解压 absolute 和 fixed 定位的元素。导致可视区域变小,布局错乱。

// 记录原有的视口高度
const originalHeight = document.body.clientHeight || document.documentElement.clientHeight;

window.onresize = function(){
  var resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
  if(resizeHeight < originalHeight ){
    // 恢复内容区域高度
    // const container = document.getElementById("container")
    // 例如 container.style.height = originalHeight;
  }
}

const isWechat = window.navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i);
if (!isWechat) return;
const wechatVersion = wechatInfo[1];
const version = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
 
 // 如果设备类型为iOS 12+ 和 wechat 6.7.4+,恢复成原来的视口
if (+wechatVersion.replace(/\./g, '') >= 674 && +version[1] >= 12) {
  window.scrollTo(0, Math.max(document.body.clientHeight, document.documentElement.clientHeight));
}

H5 页面生成为图片和二维码问题

// 二维码
import QRCode from 'qrcode';
// 使用 async 生成图片
const options = {};
const url = window.location.href;
async url => {
  try {
    console.log(await QRCode.toDataURL(url, options))
    // TODO: 赋值给图片url
  } catch (err) {
    console.error(err);
  }
}

// 图片
import html2canvas from 'html2canvas';
// 移动端生成出来的图片比较模糊,需要多倍生成 
// 根据需要设置 scaleSize 大小
const scaleSize = 2;
const newCanvas = document.createElement("canvas");
const target = document.querySelector('div');
const width = parseInt(window.getComputedStyle(target).width);
const height = parseInt(window.getComputedStyle(target).height);
newCanvas.width = width * scaleSize;
newCanvas.height = widthh * scaleSize;
newCanvas.style.width = width + "px";
newCanvas.style.height =width + "px";
const context = newCanvas.getContext("2d");
context.scale(scaleSize, scaleSize);
html2canvas(document.querySelector('.demo'), { canvas: newCanvas }).then(function(canvas) {
  // 简单的通过超链接设置下载功能
  document.querySelector(".btn").setAttribute('href', canvas.toDataURL());
}

H5 调试

import Vconsole from 'vconsole'

new Vconsole()

或者通过 代理 + spy-debugger

  1. npm install spy-debugger -g
  2. 手机与电脑置于同一 wifi 下,手机设置代理,设置手机的 HTTP 代理,代理 IP 地址设置为 PC 的 IP 地址,端口为spy-debugger的启动端口

spy-debugger 默认端口:9888

Android :设置 - WLAN - 长按选中网络 - 修改网络 - 高级 - 代理设置 - 手动

IOS :设置 - Wi-Fi - 选中网络, 点击感叹号, HTTP 代理手动

  1. 手机打开浏览器或者 app 中 H5 页面
  2. 打开桌面日志网站进行调试,点击控制台监听地址。查看抓包和 H5 页面结构

参考资料

几种常见的CSS布局

移动端 H5 相关问题