Open Lenny-Hu opened 5 years ago
在我开始写移动端页面至今,一直有2个疑问困扰着我,我只知道结果但不知道为什么
问题1:为什么设计师给的设计稿总是640px或750px(现在一般以Phone6为基准,给的750px)
问题2:为什么我们拿到640px和750px的设计稿,在编码的时候都要除以2,
(比如设计稿上有一个图标宽高是4040,我们需要先除以2,实际编码时候宽高要写成2020)
结论:pt和px的关系就是—— 1pt 里面有几个像素点
(比如 1pt里面有1个px,也可以有2个,3个,分别对应上图的@1x,@2x,@3x)
下图的Reader就是反应它们之间的比例,即 pt 和 px为1:2
还是拿iPhone6举例,下图 pt 宽高是375667,px 宽高是7501334,px的宽高是pt的2倍。
所以这里的Reader关系是@2x,也就是2倍
所以为什么设计稿640px和750px要除以2,就是因为设计师给的640px和750px是物理像素
而我们在浏览器模拟调试移动端的时候看到的像素是逻辑像素
https://www.cnblogs.com/tu-0718/p/9596894.html
使用vw + rem布局
/* 移动端页面设计稿宽度 */
$design-width: 640;
/* 移动端页面设计稿dpr基准值 */
$design-dpr: 2;
/* 将移动端页面分为10块 */
$blocks: 10;
/* 缩放所支持的设备最小宽度 */
$min-device-width: 320px;
/* 缩放所支持的设备最大宽度 */
$max-device-width: 640px;
// 公共
@mixin bg-image($url, $width, $height) {
background-image: url("/" + $url + "@2x.png");
background-size: $width $height;
background-repeat: no-repeat;
}
/* html根元素的font-size定义,简单地将页面分为$blocks块,方便计算 */
/* 当移动端X方向宽度在320-640px之间时,html 的fontsize使用的单位才是vw */
@mixin root-font-size() {
font-size: 100vw / $blocks;
body {
@include container-min-width();
}
/* 最小宽度定义:这时候html的fontsize 为 16px */
@media screen and (max-width: $min-device-width) {
font-size: $min-device-width / $blocks;
}
/* 最大宽度定义:这时候html的fontsize 为 64px */
& {
body {
@include container-max-width();
}
@media screen and (min-width: $max-device-width) {
font-size: $max-device-width / $blocks;
}
}
}
@function strip-units($number){
@return $number / ($number * 0 + 1);
}
/* 单位px转化为rem */
@function px2rem($px) {
@return #{strip-units($px) / $design-width * $design-dpr * $blocks}rem;
}
/* 适用于相对于版心容器转换 */
@function px2remByBox($px, $box-width: $center-width) {
@return #{strip-units($px) / $box-width * $design-dpr * $blocks}rem;
}
/* 百分比转换 */
@function px2per($px, $box-width: $center-width) {
@return #{strip-units($px) / $box-width * 100%};
}
/* 设置容器拉伸的最小宽度 */
@mixin container-min-width() {
margin-right: auto;
margin-left: auto;
min-width: $min-device-width;
}
/* 设置容器拉伸的最大宽度 */
@mixin container-max-width() {
margin-right: auto;
margin-left: auto;
max-width: $max-device-width;
}
@for $var from 12 to 60 {
.f-fs-#{$var} {
font-size: px2rem($var);
}
.f-lh-#{$var} {
line-height: px2rem($var);
}
}
$colorList: '000', 'fff', 'ccc', '009754', 'FF6000', '5D4646', 'FF5050', '2DBE7F', '607FD9', 'F137E6', '272727', 'FF2C4F', '232323', '004728', '006438', 'FF392A', 'ECECEC', '1E7459', 'FF476A';
@each $var in $colorList {
.s-fc-#{$var} {
color: unquote('##{$var}');
}
.s-bgc-#{$var} {
background-color: unquote('##{$var}');
}
}
// 重置
* {
box-sizing: border-box;
}
img {
max-width: 100%;
height: auto;
}
/* function */
.f-cb:after,.f-cbli li:after{display:block;clear:both;visibility:hidden;height:0;overflow:hidden;content:".";}
.f-cb,.f-cbli li{zoom:1;}
.f-ib{display:inline-block;*display:inline;*zoom:1;}
.f-dn{display:none;}
.f-db{display:block;}
.f-fl{float:left;}
.f-fr{float:right;}
.f-pr{position:relative;}
.f-prz{position:relative;zoom:1;}
.f-oh{overflow:hidden;}
.f-ff0{font-family:arial,\5b8b\4f53;}
.f-ff1{font-family:"Microsoft YaHei",\5fae\8f6f\96c5\9ed1,arial,\5b8b\4f53;}
.f-fs1{font-size:12px;}
.f-fs2{font-size:14px;}
.f-fwn{font-weight:normal;}
.f-fwb{font-weight:bold;}
.f-tal{text-align:left;}
.f-tac{text-align:center;}
.f-tar{text-align:right;}
.f-taj{text-align:justify;text-justify:inter-ideograph;}
.f-vam,.f-vama *{vertical-align:middle;}
.f-wsn{word-wrap:normal;white-space:nowrap;}
.f-pre{overflow:hidden;text-align:left;white-space:pre-wrap;word-wrap:break-word;word-break:break-all;}
.f-wwb{white-space:normal;word-wrap:break-word;word-break:break-all;}
.f-ti{overflow:hidden;text-indent:-30000px;}
.f-ti2{text-indent:2em;}
.f-lhn{line-height:normal;}
.f-tdu,.f-tdu:hover{text-decoration:underline;}
.f-tdn,.f-tdn:hover{text-decoration:none;}
.f-toe{overflow:hidden;word-wrap:normal;white-space:nowrap;text-overflow:ellipsis;}
.f-csp{cursor:pointer;}
.f-csd{cursor:default;}
.f-csh{cursor:help;}
.f-csm{cursor:move;}
.f-usn{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;}
// 组件样式
.m-dialog-box,
.m-loading-box {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1050;
background: rgba(0, 0, 0, 0.5);
}
.m-dialog-body {
position: relative;
.close {
position: absolute;
right: px2rem(5);
top: - px2rem(46);
width: px2rem(42);
height: px2rem(42);
@include bg-image('close', px2rem(42), px2rem(42));
background-position: center;
background-repeat: no-repeat;
}
}
.m-loading-inner {
border-radius: px2rem(8);
padding: px2rem(14);
.img-box {
margin-bottom: px2rem(4);
}
}
.m-no-data {
display: block;
width: 100%;
opacity: 0.8;
}
在一些pc到移动端的自适应中,可能整体缩小在移动端字体会很小,有2种方法可以处理:
使用媒体查询,然后用px2remByBox覆盖一遍尺寸定义,缺点是得多写一遍,例如:
.a {
width: px2rem(100);
font-size: px2rem(20);
$box: 700;
@media screen and (max-width: 768px) {
width: px2remByBox(100, $box);
font-size: px2remByBox(20, $box);
}
}
$fs: 20; // 最小的字体,移动端最小显示为12px。
@function px2em ($px, $_fs: $fs) {
@return #{$px / $_fs}em;
}
// 按比例设置最小字体,小屏幕最小设置为12px字体
@function getminfs ($target, $base: $fs) {
@return #{round(12 / $base * $target)}px;
}
@mixin mobile-screen($width: 768px)
{
@media screen and (max-width: $width)
{
@content;
}
}
// 设置最小字体
@mixin minFontSize ($size: 12px) {
@include mobile-screen () {
font-size: $size;
}
}
font-size: px2rem($fs); @include minFontSize;
.a { padding: px2em(50, 26) 0 0; font-size: px2rem(26); // 这是为了适应pc-768px之间的屏幕
@include minFontSize(getminfs(26)); // 按比例缩小的字体,20px的字在小屏幕显示为12px,那么26px的字相对于这个比例 }
关于移动端rem与px换算的计算方式
(function(base, min, max, scaling){
var cacheWidth = 0;
var timer;
var docEl = document.documentElement;
var resizeEvt = 'onorientationchange' in window ? 'orientationchange' : 'resize';
var recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
clientWidth = Math.min(clientWidth, max);
clientWidth = Math.max(clientWidth, min);
if(cacheWidth !== clientWidth) {
clearInterval(timer);
cacheWidth = clientWidth;
docEl.style.fontSize = scaling * (clientWidth / base) + 'px';
}
}
if (!document.addEventListener) return;
window.addEventListener(resizeEvt, function() {
timer = setInterval(recalc, 10);
});
recalc();
})(375, 300, 768, 100);
其设计图为 750,尺寸计算公式为 1rem = 100px, 3.75rem = 375px,sass计算函数如下
// 移除单位
@function strip-units($number){
@return $number / ($number * 0 + 1);
}
/* 单位px转化为rem */
@function px2rem($px) {
@return #{strip-units($px) / 2 / 100}rem; // 如果设计图已经按375标注了,无需除以2
}
使用px写各种尺寸,利用js动态设置mete的viewport来达到适配的效果
(function () {
var phoneScale = parseInt(window.screen.width) / 375;
document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=375, minimum-scale=' + phoneScale + ', maximum-scale=' + phoneScale + ', user-scalable=no');
})();
利用该方法可以使网页自动缩放,达到简单粗暴的适配效果,可能存在以下问题:
淘宝所用的rem方案
https://github.com/amfe/lib-flexible/tree/master
使用文档 https://github.com/amfe/article/issues/17
其它使用文章
https://www.cnblogs.com/well-nice/p/5509589.html.
再聊移动端页面的适配 布局方案测试页
细说移动端 经典的REM布局 与 新秀VW布局 https://github.com/imwtr/rem-vw-layout
移动端vw布局详解
css3支持测试页面
PC端适配屏幕尺寸
利用视口单位实现适配布局-京东