此文收集一些 html & css 相关的内容
阻止IOS Safari默认解析电话号码
添加如下 meta 即可
<meta name="format-detection" content="telephone=no">
页面内容下边距
如果用 margin 给页面的内容增加一个主要内容的下边距, 虽然在 PC 端(模拟器) 看是生效的, 但是在很多手机上这部分下边距消失了, 只有用 padding 才是正道。
<main></main>
IE 11 不支持该标签(默认显示成了内联元素)
mobile tap highlight
在移动设备上按下时希望实现触碰元素的高亮效果, 可以给这个元素加 -webkit-tap-highlight-color
; 但是有时需要别的效果, 这个时候可以使用 :active
伪类来实现——然而还是不够, 在 iOS safari 上如此设置仍然没有效果。
后来参考了 weui 的 demo, 发现它给 body 添加了一个空的事件 ontouchbegin
, 配合 active
伪类, 成功的达成目标!
click delay
在移动设备上, 进行点击操作通常有300MS的延迟, 这300MS的延迟带来的操作体验大打折扣。看了weui的代码, 才发现还有 fastclick
这样一个方便的工具。使用方式如下:
import fastclick from 'fastclick'
fastclick.attach(document.body)
height of inline-block with overflow:hidden
给某 inline-block 添加溢出文本 ellipsis 的时候出现的问题, 发现如果加了 overflow:hidden
会平白无故的让父级容器变高一些。
解决办法是给这个 inline-block 添加 vertical-align: top
, 原理在这里
ios webview 无法动态改变 title
有时会通过JS改变页面的 title, 但是据开发说 IOS WEBVIEW 可能需要一个加载动作来触发再次重命名TITLE, 实测IOS 微信中是这样的。以下是一种实现方式:
function setTitle (t) {
setTimeout(() => {
document.title = t
const iframe = document.createElement('iframe')
iframe.style.visibility = 'hidden'
iframe.style.width = '1px'
iframe.style.height = '1px'
iframe.src = '/favicon.ico' // 这里
iframe.onload = () => {
setTimeout(() => {
document.body.removeChild(iframe)
}, 0)
}
document.body.appendChild(iframe)
}, 0)
}
webview 右划返回历史纪录上一条
做前端路由的SPA的时候, 如果用的路由模式是 history
, 那么在微信里无法通过右划返回历史纪录上一条; 但是如果用的是默认的 hash
模式的前端路由, 微信里就可以了。
这两种模式在 IOS safari 内都可以右划返回上一层, 但是用 vue 做的路由页面 transition 时, 会必然触发一次切换路由页面的动画, 会显得不那么好看了。
DIV 里的水平滚动条 平滑滚动
在移动端,DIV 里的水平滚动条表现的很迟钝,不平滑。幸好可以通过以下 css 解决[reference].(https://weblog.west-wind.com/posts/2013/jun/01/smoothing-out-div-scrolling-in-mobile-webkit-browsers):
.scroll-div {
-webkit-overflow-scrolling: touch;
}
如果使用以下代码阻止了移动端页面的上下滚动回弹行为:
document.addEventListener('touchmove', function (e) {e.preventDefault()})
那么该 css 属性会失效。解决办法:设置 html
body
的定位为 position: fixed
,去掉阻止默认滚动的 js 即可。
保留滚动功能,但是隐藏滚动条
::-webkit-scrollbar {
width: 0px; /* remove scrollbar space */
background: transparent; /* optional: just make scrollbar invisible */
}
/* optional: show position indicator in red */
::-webkit-scrollbar-thumb {
background: #FF0000;
}
此方式在 safari 上配合 -webkit-overflow-scrolling: touch;
使用会有bug,导致自定义的滚动条样式没有生效,比如无法隐藏滚动条等等。
Chrome 表单样式
Chrome 浏览器会自动给表单元素加上一些功能样式,比如自动完成、自动填充的黄色背景等等,有时候完全不需要这些功能。以下是一些解决办法(Reference):
-
禁止自动完成:
注意要给
form
input
都加上autocomplete="off"
, 否则 chrome 里可能救不起作用了。<form autocomplete="off"> <input type="whatever" autocomplete="off"/> </form>
-
禁止自动填充:
Chrome 内遇到了带有密码输入框的表单,会自动尝试填充表单的内容。为了避免这种行为,不得不在表单开头添加两个隐藏的输入框,让 chrome 自作聪明的填在那里。
<form> <input type="text" style="display:none;"/> <input type="password" style="display:none;"/> <input type="text" value="" autocomplete="off"/> <input type="password" value="" autocomplete="off"/> </form>
-
自动填充区域的黄色背景:
不得不说自动填充区域的默认的黄色背景简直丑的让人难以忍受,好在可以通过样式解决。
input:-webkit-autofill { -webkit-box-shadow: 0 0 0 500px white inset; }
xhr post 请求弹出下载
通过 xmlHttpRequest
下载文件要注意以下几点:
-
xhr 的响应头通常会设置成
content-disposition: attachment;
, 可以藉由此来判断是否是文件下载的逻辑; -
xhr 的响应体如果不是
blob
对象(字符串), 需要通过new Blob([xhr.response])
手动生成blob
对 -
有了 blob 对象,就可以通过 a 标签的 download 属性设置自动弹出下载或类似的功能了。
-
按照这种方式生成的 csv 文件用 excel 打开,中文字符会变成乱码,据说是因为文件头里缺失了 UTF-8 BOM(byte-order-mark, 字节顺序标记,用以标示文件采用哪种格式的编码)。查询得知UTF-8的 BOM 十六进制表示为
EF BB BF
, 因此可以手动插入这一段 BOM:var blob = new Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), 'Text Content'])
。这样一来, excel 打开中文字符都是正确显示的了。
完整的流程处理如下:
let res = xhr.response
let disposition = decodeURIComponent(xhr.getResponseHeader('content-disposition'))
if (disposition && disposition.indexOf('attachment') !== -1) {
// https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post/23797348#23797348
let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
let matches = filenameRegex.exec(disposition)
let filename = Date.now() + '.csv' // 这里定义一个默认的名字
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, '')
}
let type = xhr.getResponseHeader('content-type')
let blob = (res instanceof window.Blob) ? res : new window.Blob([new Uint8Array([0xEF, 0xBB, 0xBF]), res], {type})
resolve({
blob,
filename
})
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename)
} else {
let URL = window.URL || window.webkitURL
let downloadUrl = URL.createObjectURL(blob)
if (filename) {
// use HTML5 a[download] attribute to specify filename
let a = document.createElement('a')
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location = downloadUrl
} else {
a.href = downloadUrl
a.download = filename
document.body.appendChild(a)
a.click()
}
} else {
window.location = downloadUrl
}
window.setTimeout(function () { URL.revokeObjectURL(downloadUrl) }, 100) // cleanup
}
} else {
try {
res = JSON.parse(res)
} catch (e) {
throw e
}
resolve(res)
}
Chrome 跨域
有以下两种方式:
-
使用 chrome 插件
Allow-Control-Allow-Origin: *
。用这种方式会给所有请求自动添加上跨域的请求头,当跨域发生的时候,浏览器会先发送OPTIONS
请求确认跨域,服务器同意之后才会发送真正的请求。如果服务器不同意或者没有设置对 OPTIONS 的成功响应,跨域仍会失败。 -
完全关闭 chrome后, 使用命令启动:
open -a Google\ Chrome --args --disable-web-security --user-data-dir
通过这种方式是不会发送 OPTIONS 请求的,浏览器完全禁用了这个安全措施。