什么是响应式?响应式的页面在不一样的屏幕有不一样的布局,换句话说,使用相同的html在不一样的分辨率有不一样的排版。以下图所示:css
传统的手机端适配常见有三种解决方案,第一种是bootstrap的columns布局;第二种是使用全局的rem,先根据屏幕换算1rem等于多少个px,而后设置html标签的font-size为多少个rem,屏幕越大,则font-size越大,而后页面全部的元素的宽高和字体大小都用rem等比例缩放;第三种是阿里的flex box,这种方案和第二种相似,不一样点是页面内容的字体大小是用的px,而不是比例缩放的rem。第一种须要额外引入一个框架。第三种相对第二种来讲应该更合理点,由于正文的字体经常使用的为14px或者16px,若是一个页面在这个手机字号是15.5px,在另一个手机又变成了14.9px,这样可能会有点奇怪。html
而使用响应式布局就不须要进行rem的换算,下面经过上图的那个例子一步一步地分析怎么作响应式。前端
首先一个页面的主体内容有最大的宽度,当屏幕超过这个宽度时这个中间的主体内容最大就这么大了,不会再变大了,也就是说它固定一个最大宽度,而后居中显示,如最大为1080px。而后当大于1024px时,页面主体内容最小宽为960px,两边自动留白;在500px到1024px之间两边保持留白40px;而当小于500px时就认为是手机,两边留白20px。因此计算一下,container的代码以下:android
当屏幕变小或者浏览器窗口拉小时,中间内容的宽度就不能保持1080px,它得跟着变小,而在变小的过程当中,每每要保持一边不变,另外一边随页面变窄,以下图所示:bootstrap
左栏的宽度变小应该怎么变呢?有一个原则,就是要保持中间的间距固定,而两边的内容宽度相应缩小,以下图所示:浏览器
input{
width: calc((100% - 20px) / 2)
}复制代码
calc的兼容性IE10及以上支持,android 4及如下不支持,因此考虑到不支持的设备,能够简单作个兼容,以下代码所示:框架
input{
width: 48%;
width: calc((100% - 20px) / 2);
}复制代码
若是不支持calc就用48%,这样差异其实不是很大,就是否是很精确。真的须要的话,你能够多写几个媒体查询变得更精确。布局
当屏幕拉得很小的时候,左栏已经缩得很小了,再变小就不协调了,因此这个时候要把左右布局改为上下布局,把右边的内容往下面放。由于右栏在大屏的时候是float: right,因此在中屏的时候覆盖掉这个浮动的属性,变成float: none就能够了。本来右栏的内容有四行,都比较短,能够考虑把它下面的三行排成一行,即让它们浮动。以下面代码所示:字体
.cal-result{
float: right;
width: 330px;
}
@media (max-width: 800px){
.cal-result{
float: none;
width: 100%;
}
.cal-result .result{
float: left;
width: 33%;
}
}复制代码
让每个result占1/3,而后浮动,效果以下:flex
特别是当内容是列表ul形式的时候,排不下的li应当自动换到下一行。固然也能够手动控制,以下:
@media (max-width: 800px){
.result{
width: 33%;
}
}
@media (max-width: 400px){
.result{
width: 50%;
}
}复制代码
在屏幕宽度小于400的时候,每一个结果就占50%,这样就排成两行了。这也是一种经常使用的办法,可是在咱们这个例子,若是数字比较小,在iPhone6 375px的屏幕上仍是排得下的,若是能保持在一行相对比较美观。并且固定50%,若是当数字比较大时也有可能会有重叠的危险,这个也有办法,就是别写死宽度,而是写死min-width为50%,这样当内容比较长时,float的元素同一行排不下就会自动换行。可是最好仍是要个办法让它能根据内容长度自动换行,固然能够用JS计算,可是有点麻烦。
这个时候flex就派上用场了,很简单,只要设置两个属性:
.result-container{
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}复制代码
space-between让子元素挨着容器的两边等间距排列,而wrap属性让子元素自动换行,当容器宽度不够的时候,就有了如下的效果:
.result:not(:last-child) {
margin-right: 10px;
}复制代码
效果以下:
还有从大屏变成成小屏的时候有些字号主要是标题的字号和间距要相应调小,这种变小是阶梯变化的,而不是像rem同样连续变化,并且这种阶梯通常只要有两个就够了,一个大屏的,一个小屏的。若是你须要作不少阶梯的话,那你的排版极可能有问题。
如相同的头图,在电脑上须要使用大图,可是手机上面使用小图就行了,否则会形成手机上加载慢浪费流量等问题,一个办法是使用backgound-image结合媒体查询,以下所示:
.banner{
background-image: url(/static/large.jpg);
}
@media (max-width: 500px){
background-image: url(/static/small.jpg);
}复制代码
这种方法的缺点是对SEO不太友好,由于若是使用img标签还能够写个alt属性。
第二种经常使用办法是使用img的srcset或者picture标签作响应式图片,这个我在《Effective前端7:加快页面打开速度》已经提到,这里再也不重复。
这种响应式图片除了大小屏以外,还能够兼顾视网屏即dpr为2及以上的和普通屏dpr为1的屏幕,即在高dpr的屏幕使用2倍图,而普通屏幕使用1倍图。
有些地方大小屏的排版差别比较大,例若有些内容大屏的时候是挨在一块儿,而小屏离得比较远,这个时候你可能得重复html,写两份的标签,大屏的时候隐藏掉小屏的html标签,小屏的时候隐藏掉大屏的html标签。而且这种状况不该该是常例,若是你常常要写两套,那说明你这个页面可能不太适合写响应式,还不如直接写两套呢。
还有个问题,有时候你可能要借助rem/transform: scale作大小缩放,但这必定是下策,咱们的原则仍是要保持字号和间距不变,当屏幕的跨度不是很大的时候。使用transform的后果是屏幕拉小的时候,内容跟着变小了,可是因为transform不会形成重排,它占据的高度仍是那么大,下面的内容不会跟上来。这样就得手动计算内容的高度。另外若是使用rem,就和响应式的思想冲突了。若是页面的一部分字号使用了rem,另外一部分字号使用了px,这样就不协调了,若是你所有写rem那就不须要使用响应式开发了。 这个时候你可能要想想,是否是UI出得有问题。让UI从新调整。
还有,有时候可能会用到高度的媒体查询,例如在高度小于多少的时候,不能让弹框超出页面的高度;在高度大于多少的时候,让footer的定位fixed在底部,否则footer的下面可能会留白。
最后,本文总结了响应式开发的一些思想,它的好处是不用大屏写一套,小屏写一套,方便维护,缩短开发时间,缺点是兼容性不是特别好,而且效果没有专门出一个小屏的UI和交互来得好。可是整体来讲,使用响应式仍是颇有优点的,只要设计得好,小屏上也是挺好看的。如今响应式开发已经愈来愈流行,它能够兼容PC/Pad/手机三端的屏幕,这个优势是没法超越的,你只需写一套html和一套JS逻辑,无论多大的屏幕都能适用。