移动端页面布局相关问题
做了一组移动端的页面,在布局时遇到了一些问题,总结下以避免再次掉坑。
遇到的问题:
1.图片及带背景图片的块宽高等比缩放布局
2.margin,padding百分比布局
图片及带有背景图片的块的图片宽高等比缩放
纯图片可以使用img标签,将其宽度设置成百分比,高度会自动按比例缩放。控制起来很方便。
带背景图片的div就有点麻烦了,背景图可以使用background-size设置宽度百分比值,高度默认auto会按比例缩放。块宽度可以使用百分比,但高度如果不设置具体像素数,会按照内容大小自动布局,这个问题处理起来有点点小麻烦。
解决方案1是使用边框图片布局,可以对图片进行拉伸,但是也需要注意就是这个方案也只适用于边框图片是可拉伸或平铺形状的布局。LZ的图片刚好是一个不规则形状的图,拉伸之后就变形了,也没有办法平铺,不能用这个方案的,555~
border-image对于现代浏览器及移动端浏览器支持良好,在移动端是可以使用的,但是要加前缀。
可以具体看下边框图片怎么用:
border-image常设置的属性是图片url,剪裁位置,重复性。
其中:
剪裁位置:没有单位的时候默认像素,支持百分比,百分比值大小相对于边框图片而言,假设边框图片大小为400px*300px,则20%的实际效果就是剪裁了图片的60px 80px 60px 80px的四边大小。顺序是顶部区域、右侧区域、底部区域、左侧区域,裁剪图示如下所示。
重复性:可以填repeat(重复),round(平铺)和stretch(拉伸)。其中,stretch是默认值。
拉伸效果(默认拉伸):
.border_image{ width:400px; height:100px; -moz-border-image:url(../image/border.png) 27; -webkit-border-image:url(../image/border.png) 27; border:double orange 1em; }
平铺效果:
.border_image{ width:400px; height:100px; -moz-border-image:url(../image/border.png) 27 round; -webkit-border-image:url(../image/border.png) 27 round; border:double orange 1em; }
由于图片剪裁可以使用百分比(相对于图片尺寸的百分比),就可以做到按比例缩放,按照内容大小进行适应。
解决方案2使用图片占位符,此图片的大小是需要的比例。例如2:1就把占位符做成2px*1px,例如5:3就把占位符做成5px*3px。然后放入img标签里,设置宽度 100%,这样高度就自动撑开,进而撑开外层父div。img平级放个子div,相对父div绝对定位,宽高100%,这样子div的大小就和img一样 大,实现等比缩放了。很纠结的一个方法。但这个方法也有问题。img标签的大小,得里面的图片占位符解析出来,才可以撑开父div。这就导致网页一打开时,父div高度为0,等到图片占位符解析完毕后,父div才得以撑开,所以网页会闪动,体验不好,也会影响js的计算模块高度等问题。而且还增加一个src,这个图片是完全对用户不可见的,除了固定尺寸没有任何用处,网页会多出一次请求。LZ不会去用这纠结的方法。
在流式布局中,高度通常设置固定px,但是这样做,在小屏设备和大屏设备中,有较明显的差异。
解决方案3是使用百分比padding将块支撑起来,但具体的百分比padding如何计算,下一块详解。
margin,padding百分比布局
这个主题其实就一个关键问题:margin,padding的百分比是按照谁的百分比计算的。
可以先想一下一个相关的问题:一个具有宽高的块,设置margin:auto;上下左右都可以居中吗?像下面这样:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>test</title> <style type="text/css"> #content{width:300px;height:200px;background:pink;margin:auto;} </style> </head> <body> <div id="content"></div> </body> </html>
没错,它只有左右居中了,上下并没有居中。
另外一个问题,假设一个块级包含容器,宽1000px,高600px,块级子元素定义margin:10% 5%;那么margin的top,right,bottom,left各是多少?
也可能很多人给出的答案是100px 30px 100px 30px,可以看看实际的情况:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>test</title> <style type="text/css"> #wrap{width:1000px;height:600px;background:pink;margin:auto;} #wrap p{margin:10% 5%;} </style> </head> <body> <div id="wrap"> <p>Yes.It is me.</p> </div> </body> </html>
看下结果:
是的,结果是100px 50px 100px 50px,上下左右边距都是按照父元素的width计算的!
没错,这是正确的实现,居然和我想象的不一样.
规范中注明了margin的百分比值参照其包含块的宽度进行计算。当然,这只发生在writing-mode: horizontal-tb和direction:ltr的情况下。书写模式是纵向的情况下,它会按照块的高度来计算,就像下面这样设置:
#wrap{ -webkit-writing-mode: vertical-rl; writing-mode: tb-rl; /* for ie */ }
这样的设置,使得在水平和竖直方向上可以有相同尺寸的留白。
这其实更多的要从CSS设计意图上去想,因为CSS的基础需求是排版,而通常我们所见的横排文字,其水平宽度一定(仔细回想一下,如果没有显式的定义宽度 或者强制一行显示,都会遇到换行,而不是水平延展),垂直方向可以无限延展。但当书写模式为纵向时,其参照就变成了高度而不再是宽度了。
padding的计算也是类似的,默认情况按照宽度来的。
再回头想想,为什么margin:auto;不能在垂直方向上居中?其实原因也是上面所说的,因为纵向是可以无限延展的,所以没有一个一定的值可以被参照被用来计算。
另外在微信浏览器里面,有标题栏,所以设计的时候需要考虑这几十像素的标题栏,这和用模拟器略微有差别。其他软件浏览器也类似,需要考虑。
参考:
- http://dev.w3.org/csswg/css-box/#the-margin-properties
- http://dev.w3.org/csswg/css-box/#ltpercentagegt
- http://dev.w3.org/csswg/css-box/#Calculating