一, 思考
在移动端越来越重要的背景下, 每位 web 开发者对移动适配都有自己的想法. 是移动优先, 还是 PC 优先, 还是两者兼得? 在实际开发中这个问题是和项目产品定位有关的, 也涉及到 UI 的设计, 不是开发者能决定. 但不管产品如何定位, 作为开发者总是要提供最优的解决方案, 是用一套样式还是多套样式? 网上一搜, 有静态布局, 流式布局, 响应式布局, 自适应布局, 弹性布局等一堆, 云里雾里, 到底要怎么选呢? 看完这篇文章相信心中就有数了.
二, viewport 的使用
1, 最常见的设置, 大多数的框架 (如 Bootstrap) 和知名的站点基本是这个配置
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
2, 这个配置重点在 width=device-width, 就是让视窗口等于设配宽度, 也就是我们开发中能用 document 的宽度, 其它几个 "初始缩放大小"" 最大缩放大小 ""最小缩放大小" 和 "是否允许用户缩放" 可以理解为用来 "固定" 这个设置不被破坏的.
3, 这个设置很简单, 但同时也会带来一些需要解决的问题.
a, 现在的手机都是两倍三倍的 Retina 高清屏, 1px 实际的效果是不止一个像素的, 对不同的设备设置不同
的 initial-scale 可以有比较好的效果, 比如在 2 倍 Retina 的 iphone6(6s,7,8)中设置为 0.5. 一旦
动态设置这个, 也就意味这视窗口不同了, 需要不同样式适配. 这也是分配样式的一套基准, 如何分配样式
后面会有更详细的讲解.
b, 在 PC 端如果有最小宽度的限制, 同样需要配置不同的 width 值.
三, 单位的使用
1,CSS 中单位很多, 这里只介绍最常用的几种:
(1) px: 这个可以理解为 "基准" 单位, 就是不管在什么设备中其值是不会变的, 就像 cm,kg 这些一样
(2) em: 这个是相对父容器的单位, 一般用在字体 font-size 中比较好. 如父容器 font-size 为 16px, 则
1em=16px
(3) rem: 相对于根元素 html 的单位, 如 HTML 的 font-size 为 16px, 则 1rem=16px
(4) vw/vh: 视口宽高为 100vw/100vh, 这个和百分比类似, 只是百分比是相对于父容器, 其相对于视口
2, 移动适配最常用的应该是 rem, 很多框架和淘宝的 flexible 适配都是基于这个单位, 而自己做的话, 一般
在首页加载时全局 JS 设置 HTML 的 font-size 即可, 代码如下:
- (function (doc, win) {
- var docEl = doc.documentElement,
- resizeEvt = 'orientationchange' in Windows ? 'orientationchange' : 'resize',
- recalc = function () {
- var clientWidth = docEl.clientWidth;
- if (!clientWidth) return;
- // 这里根据设计稿为 750, 设置 1rem=100px,
- docEl.style.fontSize = 100 * (clientWidth / 375) + 'px';
- };
- // Abort if browser does not support addEventListener
- if (!doc.addEventListener) return;
- win.addEventListener(resizeEvt, recalc, false);
- doc.addEventListener('DOMContentLoaded', recalc, false);
- })(document, Windows);
3. 如果用了 Sass/Less 等预编译语言可以更灵活的配置的, 在上面方法内配置(设计稿为 750 的情况下):
docEl.style.fontSize = 40 * (clientWidth / 750) + 'px';
在编译函数中配置:
- @function px2rem($px, $base-font-size: 20px) {
- @return ($px / $base-font-size) * 1rem;
- }
这样我们就可以直接使用设计稿的尺寸, 如: px2rem(100px), 省去了自己计算, 如果没用预编译语言(推
荐使用), 编辑器也有插件支持单位转化.
4. 上面是基于屏幕宽度来设置根元素 font-size, 如果设置不同的 initial-scale, 我们需要基于设备像素比设置, 通过 Windows.devicePixelRatio 获取.
四, 页面布局方式
1. 理解 HTML 的文档流方式, 其实就是流式布局, 即横向需要我们设置, 纵向自动叠加. 这个和移动端的设计体验方式是比较像的. 在宽度中就要用自适应的方式, 如百分比, 有设置相对单位的, 可用相对单位, 灵活使用, css3 的 display:flex 也是很好的选择, 现代浏览器和移动设备基本都支持了.
2. 刚才说到体验, 很明显移动端和 pc 端的体验真的很不同, 所以光有上面的自适应是远远不够, 是不是需要对这两个完全不同的体验方式响应不同的布局和样式.
五, 媒体查询
1. 我们除了可以用 JS 来判断不同的设备, 设置相对单位所用的根元素. 另一个强大的方式是可以通过 css3 强大的媒体查询来指定不同的样式.
2. 媒体查询的规则
@media all and ([min-width|max-width|orientation|min-device-width|...]) { ... }
中括号 [] 中表示需要添加的条件, 可匹配宽高 / 横竖屏 / 设备类型等, 比如 min-width:750px, 表示最小宽度为 750px,{}是在匹配模式下的样式. 也有逻辑判断 and/or/not 连接不同的规则
3. 要是引入整个文件, 可以在 link 标签中使用
<link rel="stylesheet" media="screen and (min-width:900px)" href="big.css" type="text/css" />
表示: 当屏幕大于或等于 900px 时, 将采用 big.CSS 样式来渲染 Web 页面.
4.Bootstrap 响应式设计这类栅格布局采用的就是这套方式.
六, 1px 像素边框问题
1. 除了上面说到在 viewport 中设置缩放外, 直接设置一个空元素缩放也是可以的
- p{
- width: 100px;
- height: 1px;
- background: red;
- display: block;
- transform: scaleY(.5);
- }
不足: 圆角无法实现, 实现 4 条边框比较麻烦, 并且只能单独实现, 如果嵌套, 会对包含的效果产生不想要的效果, 所以此方案配合: after 和 before 独立使用较多
2. 利用 CSS 对阴影处理的方式实现 0.5px 的效果
box-shadow:0 1px 1px -1px rgba(0, 0, 0, 0.5);
不足: 颜色不好处理, 黑色 rgba(0,0,0,1) 最深的情况了. 有阴影出现, 不好用大量使用 box-shadow 可能会导致性能瓶颈. 四条边框实现效果不理想.
3. 图片实现, 使用 background-image 实现 1px 有两种方式: 渐变 linear-gradient 或直接使用图片(base64). 渐变 linear-gradient (50% 有颜色, 50% 透明)
- div{
- height: 1px;
- background-image:-webkit-linear-gradient(top,transparent 50%,#000 50%);
- background-position: top left;
- background-repeat: no-repeat;
- background-size: 100% 1px;
- }
不足: 大量使用渐变可能导致性能瓶颈, 代码量大, 多背景图片有兼容性问题
七, 图片高清化
1. 可以使用 srcset 属性设置, 使用看 https://www.zhangxinxu.com/wordpress/2014/10/responsive-images-srcset-size-w-descriptor/
2. 背景图高清
a. 使用上面介绍的媒体查询, 如:
- /* 普通显示屏 (设备像素比例小于等于 1) 使用 1 倍的图 */
- .CSS{
- background-image: url(img_1x.PNG);
- }
- /* 高清显示屏 (设备像素比例大于等于 2) 使用 2 倍图 */
- @media only screen and (-webkit-min-device-pixel-ratio:2){
- .CSS{
- background-image: url(img_2x.PNG);
- }
- }
- /* 高清显示屏 (设备像素比例大于等于 3) 使用 3 倍图 */
- @media only screen and (-webkit-min-device-pixel-ratio:3){
- .CSS{
- background-image: url(img_3x.PNG);
- }
- }
b.image-set 实现高清化
- .CSS {
- background-image: url(1x.PNG); /* 不支持 image-set 的情况下显示 */
- background: -webkit-image-set(
- url(1x.PNG) 1x,/* 支持 image-set 的浏览器的 [普通屏幕] 下 */
- url(2x.PNG) 2x,/* 支持 image-set 的浏览器的[2 倍 Retina 屏幕] */
- url(3x.PNG) 3x/* 支持 image-set 的浏览器的[3 倍 Retina 屏幕] */
- );
- }
c. 很多网页端对图片的要求还是没那么高的, 不像 App 那样, 图片一般用一张 2 倍高清图就行, 最新的设备对以上属性的支持还是可以的, 对于要求高的应用使用
八, 移动端 click 屏幕产生 300ms 的延时响应
1. 原因: 在浏览器需要如何判断快速点击上, 当用户在屏幕上单击某一个元素时候, 例如跳转链接 < a href="#"></a>, 此处浏览器会先捕获该次单击, 但浏览器不能决定用户是单纯要点击链接还是要双击该部分区域进行缩放操作, 所以, 捕获第一次单击后, 浏览器会先 Hold 一段时间 t, 如果在 t 时间区间里用户未进行下一次点击, 则浏览器会做单击跳转链接的处理, 如果 t 时间里用户进行了第二次单击操作, 则浏览器会禁止跳转, 转而进行对该部分区域页面的缩放操作. 那么这个时间区间 t 有多少呢? 在 iOS Safari 下, 大概为 300 毫秒. 这就是延迟的由来. 造成的后果用户纯粹单击页面, 页面需要过一段时间才响应, 给用户慢体验感觉, 对于 Web 开发者来说是, 页面 JS 捕获 click 事件的回调函数处理, 需要 300ms 后才生效, 也就间接导致影响其他业务逻辑的处理.
2. 解决方案:
(1)使用 fastclick.JS, 只要全局加入该文件并设置如下:
FastClick.attach(document.body);
(2) zepto 的 touch 模块, tap 事件也是为了解决在 click 的延迟问题
九, 更改默认样式
- // 使用 appearance 改变 webkit 浏览器的默认外观
- input,select {
- -webkit-appearance:none; appearance: none;
- }
- //winphone 下, 使用伪元素改变表单元素默认外观
- //1. 禁用 select 默认箭头,::-ms-expand 修改表单控件下拉箭头, 设置隐藏并使用背景图片来修饰
- select::-ms-expand {
- display:none;
- }
- //2. 禁用 radio 和 checkbox 默认样式,::-ms-check 修改表单复选框或单选框默认图标, 设置隐藏并使用背景图片来修饰
- input[type=radio]::-ms-check,
- input[type=checkbox]::-ms-check {
- display:none;
- }
- //3. 禁用 pc 端表单输入框默认清除按钮,::-ms-clear 修改清除按钮, 设置隐藏并使用背景图片来修饰
- input[type=text]::-ms-clear,
- input[type=tel]::-ms-clear,
- input[type=number]::-ms-clear {
- display:none;
- }
- // 禁止长按链接与图片弹出菜单
- a,img {
- -webkit-touch-callout: none
- }
- // 禁止 iOS 和 Android 用户选中文字
- HTML,body {
- -webkit-user-select:none; user-select: none;
- }
- // 改变输入框 placeholder 的颜色值
- ::-webkit-input-placeholder {
- /* WebKit browsers */
- color: #999;
- }
- :-moz-placeholder {
- /* Mozilla Firefox 4 to 18 */
- color: #999;
- }
- ::-moz-placeholder {
- /* Mozilla Firefox 19+ */
- color: #999;
- }
- :-ms-input-placeholder {
- /* Internet Explorer 10+ */
- color: #999;
- }
- input:focus::-webkit-input-placeholder{
- color:#999;
- }
- // Android 上去掉语音输入按钮
- input::-webkit-input-speech-button {
- display: none
- }
十, 总结
1. 网站适配的终端可以用 JS 或媒体查询的方式获取, 分配对应的样式.
2. 布局上采用相对单位, 百分比和 flex 的弹性方式.
3. 对移动端的特殊性进行适配, 如 1px 问题, 默认样式等.
来源: https://www.cnblogs.com/paul123/p/11073465.html