简述移动端常见的布局方式
1、响应式布局:px
- 概念:
响应式网页设计就是一个网站能够兼容多个终端-----而不是为每个终端做一个特定的版本;
其目的是为用户提供更加舒适的界面和更好的用户体验;
- 优缺点:
- 优点:
- 面对不同分辨率设备灵活性强;
- 能够快捷解决多设备显示适应问题;
- 缺点:
- 兼容各种设备工作量大,效率低下;
- 代码累赘,会出现隐藏无用代码,加载时间过长;
- 优点:
- 步骤:
- 设置meta标签(App.vue或者首html文件)
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1,user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="HandheldFriendly" content="true"> //user-scalable属性能够解决ipad切换横屏之后触摸才能回到具体尺寸的问题。
- 通过媒体查询来设置样式media query(media query 是响应式设计的核心,它能够和浏览器进行沟通,告诉浏览器页面如何呈现)
@media screen and (max-width:980px){//设置不同设备中div的布局方式 #head { … } #content { … } #footer { … } }这里面的样式会覆盖掉之前所定义的样式。
- 设置多种视图宽度
/**ipad**/ @media only screen and (min-width:768px)and(max-width:1024px){ } /**iphone**/ @media only screen and (width:320px)and (width:768px){ }
- 字体设置(一般rem更方便使用)https://www.cnblogs.com/YYvam1288/p/5123272.html
@media screen and (min-width: 768px) { html, body { font-size: 8px !important; } } @media screen and (min-width: 992px) { html, body { font-size: 10px !important; } } @media screen and (min-width: 1200px) { html, body { font-size: 14px !important; } } @media screen and (min-width: 1500px) { html, body { font-size: 16px !important; } } html, body { font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; height: 100%; width: 100%; margin: 0px; padding: 0px; } * {//怪异盒模型也就是IE盒模型 box-sizing: border-box; }
- 设置meta标签(App.vue或者首html文件)
- 响应式布局所涉及到的问题:
- 图片液态化:
img{//要保证所有图片最大显示为其自身的100%(即最大只可以显示为自身那么大),不可以使用width:100%,会让图片跟他的容器一样宽 max-width:100%; height:auto; }
- 图片液态化:
2、弹性布局(百分比布局、流式布局)
百分比能够设置的属性是width、height、padding、margin。其他属性比如border、font-size不能用百分比设置的。
如果用百分比写width,那么指的是父元素width的百分之多少。
如果用百分比写height,那么指的是父元素height的百分之多少。
如果用百分比写padding,那么指的是父元素width的百分之(无视padding)多少,无论是水平的padding还是竖直的padding。
如果用百分比写margin,那么指的是父元素width的百分之(无视padding)多少,无论是水平的margin还是竖直的margin。
不能用百分比写border的宽度
3、rem布局(css3新增属性)插件:cssrem(IE8一下不兼容)
- 概念:rem是相对于根元素(html)的字体大小的单位;
em一般都是以<body>的“font-size”为基准(表示父元素的字号的倍数);
body{
font-size:10px;
}
p{
font-size:1.4em;//14px
}
例子:
bootstrap样式表,html {font-size:62.5%;} body {font-size:14px;},
p{font-size:1em;)//14px
- 优点:既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应;
- rem的计算方式:
1、确定基数:一般10px,自己记住就行,不用写进代码里 2、html {font-size:百分数;} 百分数=基数/16 基数10 百分数62.5% 基数14 百分数87.5% 3、px换算rem 公式=想要的px值/基数 也就是说,当你设置 html {font-size:62.5%;},你想给容器里的文字设置字号14px,换算成rem就是14px/10——1.4rem 这样子 (如果自己想要测试的话,拿火狐Firebug测试,因为Chrome下字号低于12px失效哈,如果想设置小于12px的字号,Chrome也有解决方案,自己百度就好)
- 应用于:
- 通常在移动端看新闻的时候,右上角都有个调节字体大小的,可以通过点击调节新闻的字体大小,方便阅读https://blog.csdn.net/u014607184/article/details/79516528
- 移动端适配:
- 只使用rem会出现在retina屏幕上1px线条显示过粗的现象,因为虽然物理尺寸一致,但在普通屏幕下
1
个CSS像素对应1
个物理像素,而在Retina屏幕下,1
个CSS像素对应的却是4
个物理像素。
4、flexible布局(自动通过flexible.js计算页面html
的font-size
的大小,然后在页面布局中使用rem作为单位,而非px)
注意:(手机淘宝推出的,为了解决淘宝H5在移动端的布局)https://www.cnblogs.com/lyzg/p/5058356.html
- 在使用flexible.js的过程中,如果当前页面(app.vue/index.html)指定了meta[name="viewport"],删除meta标签,然后根据js文件重新计算dpr;
- dpr = 物理像素/设备像素(750/375)
- 当设计稿为 750px 的情况下,dpr(设备像素比)=2,根元素字体大小为100px,除font-size外,公式=想要的px值/100 ;
- 而font-size推荐使用px写死
-
工作中做完一个触屏版的页面后,我们会拿iPhone5s、iPhone6、iPhone6s等手机进行测试,他们都是Retina屏,我们当然希望在这些手机型号上看到的文本字号是相同的。也就是说,我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到更多文本(例如iPhone7、iPhone7Plus)。另外,现在绝大多数的字体文件都自带一些点阵尺寸,通常是16px和24px,都是偶数,所以我们不希望出现13px和15px这样的奇葩尺寸。
如此一来,就决定了在制作H5的页面中,rem并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用px作为单位。只不过使用[data-dpr]属性来区分不同dpr下的文本字号大小。//当然这只是针对于描述性的文本,比如说段落文本。但有的时候文本的字号也需要分场景的,比如在项目中有一个slogan,
//业务方希望这个slogan能根据不同的终端适配。针对这样的场景,完全可以使用rem给slogan做计量单位
//移动端的字体选择。对于只需要适配手机设备,使用px即可。对于需要适配各种移动设备,
//例如需要适配iPhone和iPad等分辨率差别比较挺大的设备,就要使用rem了,有时还需要配合媒体查询一起使用。
//方法 定制一个font-dpr()这样的Sass混合宏 @mixin font-dpr($font-size){ font-size: $font-size; [data-dpr="2"] & { font-size: $font-size * 2; } [data-dpr="3"] & { font-size: $font-size * 3; } }
//开发中
@include font-dpr(16px);
-
- iPhone6 上有1px 的滚动条,最后处理方案是通过 viewport 中的 maximum-scale 的值加了0.1,由于设置了
user-scalable=no
,maximum-scale 的值加0.1并不会有什么影响,但是却神奇的解决了这个问题。 - 下面为js代码,只需要将其复制到js文件,并将其命名为flexible.js
(function(win, lib) { var doc = win.document; var docEl = doc.documentElement; var metaEl = doc.querySelector('meta[name="viewport"]'); var flexibleEl = doc.querySelector('meta[name="flexible"]'); var dpr = 0; var scale = 0; var tid; var flexible = lib.flexible || (lib.flexible = {}); if (metaEl) { // console.warn('将根据已有的meta标签来设置缩放比例'); var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/); if (match) { scale = parseFloat(match[1]); dpr = parseInt(1 / scale); } } else if (flexibleEl) { var content = flexibleEl.getAttribute('content'); if (content) { var initialDpr = content.match(/initial\-dpr=([\d\.]+)/); var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/); if (initialDpr) { dpr = parseFloat(initialDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } if (maximumDpr) { dpr = parseFloat(maximumDpr[1]); scale = parseFloat((1 / dpr).toFixed(2)); } } } if (!dpr && !scale) { var isAndroid = win.navigator.appVersion.match(/android/gi); var isIPhone = win.navigator.appVersion.match(/iphone/gi); var devicePixelRatio = win.devicePixelRatio; if (isIPhone) { // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ dpr = 2; } else { dpr = 1; } } else { // 其他设备下,仍旧使用1倍的方案 dpr = 1; } scale = 1 / dpr; } docEl.setAttribute('data-dpr', dpr); if (!metaEl) { metaEl = doc.createElement('meta'); metaEl.setAttribute('name', 'viewport'); metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); if (docEl.firstElementChild) { docEl.firstElementChild.appendChild(metaEl); } else { var wrap = doc.createElement('div'); wrap.appendChild(metaEl); doc.write(wrap.innerHTML); } } function refreshRem(){ var width = docEl.getBoundingClientRect().width; // console.log(width) if (width / dpr > 768) { width = 768 * dpr; } var rem = width / 7.5; docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; } win.addEventListener('resize', function() { clearTimeout(tid); tid = setTimeout(refreshRem, 300); }, false); win.addEventListener('pageshow', function(e) { if (e.persisted) { clearTimeout(tid); tid = setTimeout(refreshRem, 300); } }, false); if (doc.readyState === 'complete') { doc.body.style.fontSize = 12 * dpr + 'px'; } else { doc.addEventListener('DOMContentLoaded', function(e) { doc.body.style.fontSize = 12 * dpr + 'px'; }, false); } refreshRem(); flexible.dpr = win.dpr = dpr; flexible.refreshRem = refreshRem; flexible.rem2px = function(d) { var val = parseFloat(d) * this.rem; if (typeof d === 'string' && d.match(/rem$/)) { val += 'px'; } return val; } flexible.px2rem = function(d) { var val = parseFloat(d) / this.rem; if (typeof d === 'string' && d.match(/px$/)) { val += 'rem'; } return val; } })(window, window['lib'] || (window['lib'] = {}));
- 混合开发需要做到的兼容处理
1.如果dpr=1(如电脑端),则html的font-size为50px,此时 1rem = 50px, viewport 的 initial-scale 、minimum-scale 和 maximum-scale 都为 “1.0” ; 2.如果dpr=2(如iphone 5 和 6),则html的font-size为100px,此时 1rem = 100px, viewport 的 initial-scale 、minimum-scale 和 maximum-scale 都为 “0.5” 3.如果dpr=3(如iphone 6 sp),则html的font-size为150px,此时 1rem = 150px; viewport 的 initial-scale 、minimum-scale 和 maximum-scale 都为 “0.3333333333”
4、常见的适配布局组合:
- rem + 响应式布局(媒体查询)
- em/rem弹性布局(vh/vw)https://blog.csdn.net/qq_24182885/article/details/81479457
- bootstrap布局
- flexible布局
5、参考资料:
北栀女孩儿