原书: 响应式Web设计实践
目录:
第2章 流动布局
1. 布局选项
- 传统的固定布局中存在很多问题, 随着屏幕大小的越来越多元化, 固定布局已经不能适用了.
- 在流动布局中, 度量的单位不再是像素, 而是变成了百分比.
- 弹性布局与流动布局类似, 但是通常情况下, 弹性布局中会以em来作为单位. 带来一个好处是随着用户增大或减小字体, 适用弹性布局的元素的宽度也会等比例地变化. 但是其也可能出现水平滚动条
- 混合布局
媒体查询:
媒体查询允许根据设备的信息----诸如屏幕宽度, 方向或者分辨率等属性来使用不同的样式
断点:
那些被指定的,开始应用某一新的媒介查询的点. 例如, 一个在980px处的断点的意思是, 当浏览器宽度大于或小于这一数值时, 新的媒介查询将被触发
2. 字体大小
- 像素: 不够灵活
- em: 可缩放, 可级联
- 百分比: 可缩放, 可级联
- rem(root em): rem的大小与根元素---html元素有关. 移动平台尚不支持
3. 网格布局
- 一个流动布局的实现:
#container{ width: 95%; padding: .625em 1.05% 1.5em; /*10px/16px 10px/948px 24px/16px*/ margin: auto 0; } .main{ float: left; margin-right: 2.53%; /* 24/948 */ width: 65.823%; /*624/948*/ } .aside{ float: right; width: 31.645%; /*300/948 */ }
- 流动世界中的固定宽度对象: 图片
aside img, .main img, .slats img{ width:100%; max-width: 100%; }
不可以在html中定义img的height和width的属性值, 如果设定了这些值, 就不能按比例缩放图片了.
4. 混合固定宽度和流动宽度
目的: 固定右边边栏, 只让主栏流动
方法: 使用表格布局
.main{ display: table-cell; padding-right: 2.53%; /* 24/948 */ } aside{ display: table-cell; width: 300px; }
使用条件注释来为IE 7 及以下版本的IE浏览器提供备用样式: (!IEMobile的条件判断是因为Windows Phone 7 也会加载这个备用样式)
<!--[if (lt Ie 8) & (!IEMobile)]> <link rel="stylesheet" type="text/css" href="css/ie.css" media="all"> <![endif]-->
第3章 媒介查询
1. 视口
在移动设备上, 很多设备都会给浏览器返回一个数值较大的布局视口.
视口标签:
<meta name="viewport" content="directive, directive" />
视口的属性:
-
可以将视口设置为某一特定的宽度, 或者设置为设备屏幕的宽度
最佳选择是在width声明中使用device-width<meta name="viewport" content="width=device-width" />
- height: 允许指定一个特定的高度. 最好将布局视口的高度等于屏幕的高度.
但是一般不会经常用到height, height有用时候就是在不想让页面垂直滚动的时候
<meta name="viewport" content="height=device-height" />
- user-scalable: 告诉浏览器是否允许用户在页面上进行缩放. 默认值是yes, 即运行缩放
<meta name="viewport" content="user-scalable=no" />
- initial-scale: 可以通过给这个参数赋值为0.1(10%)到10.0(1000%)之间的某个数来设置页面初始化时的缩放层级
<meta name="viewport" content="initial-scale=.5, width=device-width" />
如这个例子中, width属性被设成设备的宽度, 同时initial-scale被设置为.5, 这意味着浏览器将会缩小显示所有东西: 例如在一个320px宽的设备上, 页面会显示为640px
- maximum-scale: 浏览器允许用户放大页面到什么程度. 在移动端Safari中, 其默认值是1.6(160%), 可以指定0.1-10.0. 如果将其设为1.0, 则意味着禁止用户缩放页面
- minimum-scale: 告之浏览器允许用户将页面缩小到什么程度. 在移动端Safari中, 其默认值是0.25, 可指定0.1-10.0. 如果将其设为1.0, 则意味着禁止用户缩小页面
2. 媒介查询结构
媒介查询可以通过问询浏览器来确定特定的表达式是否为真. 如果为真, 就加载一些特殊的, 适用于这种情况的样式, 从而达到调整布局的目的.
媒介查询的一般形式为:
@media [not|only] type [and] (expr) { rules }
包含四个基本组成部分:
- 媒介类型: 特定的目标设备类型
- 媒介表达式: 测试某一特性是否为真
- 逻辑关键词: 可以用关键词(例如 and, or, not, only) 来创建出更多复杂的表达式
- 规则: 调整显示效果的基本样式
1) 媒介类型:
每一种媒介类型都会告诉用户代理(例如浏览器)是否要加载特定的样式表. 例如, 如果知道screen媒介类型, 那么所有通过计算机显示器来浏览页面的用户代理都会加载相应的样式. 如果是print媒介类型, 那么相应的样式将会在打印或打印预览时进行加载.
十种类型:
all | 所有设备(默认) |
braille | 盲文触觉反馈设备 |
embossed | 分页盲文打印机 |
handeld | 手持设备(通常为小屏幕并且可能是黑白屏幕) |
打印或打印预览 | |
projection | 投影仪 |
screen | 彩色计算机屏幕 |
speech | 语言合成器 |
tty | 使用固定字符间距的设备(终端或打印设备) |
tv | 电视机 |
样式中的查询语句如下:
@media print {
}
也可以采用外部样式文件的形式, 并在link元素内指定媒介属性:
<link rel="stylesheet" href="print.css" media="print" />
无论哪种方法, 被引用的CSS的效果只有在打印或打印预览时才能看到.
每条媒介查询都必须包含一种媒介类型,如果没有设置媒介类型, 该条查询将使用默认值all, 但在不同浏览器中的实际行为是各不相同的.
2) 媒介表达式
判断设备视口的宽度是否大于320px:
@media screen and (min- 320px){
}
先检测访问页面的设备是否属于screen, 然后测试设备的视口宽度----宽度至少为320px
可以使用的媒介特性, 并且min-和max-前缀也都适用于这些特性
特性 | 描述 | 值 | 可以指定最小或最大 |
width | 描述设备显示区域的宽度 | <长度>(例如320) | 是 |
height | 描述设备显示区域的高度 | <长度>(例如600) | 是 |
device-width | 描述设备渲染界面的宽度 | <长度>(例如320) | 是 |
device-height | 描述设备渲染界面的高度 | <长度>(例如600) | 是 |
orientation | 指定设备处于竖直(高度大于宽度)或者水平(宽度大于高度)状态 | portrait | landscape | 否 |
aspect-ratio | width属性和height属性的比值 | <比值>(例如16/9) | 是 |
device-aspect-ratio | device-width属性和device-height属性的比值 | <比值>(例如16/9) | 是 |
color | 设备的每个颜色分量的比特数 | <整数>(例如1) | 是 |
color-index | 设备的颜色查找表中的条目数 | <整数>(例如256) | 是 |
monochrome | 黑白屏幕设备每个像素的比特数(如果不是黑白屏幕将返回0) | <整数>(例如8) | 是 |
resolution | 设备的分辨率(像素密度), 可以以点每英尺[dpi]或者点每厘米[dpcm]来表示 | <分辨率>(例如118dpcm> | 是 |
scan | "tv"类设备的扫描过程 | progressive | interlace | 否 |
grid | 返回该设备是网格设备(1)还是位图设备(0) | <整数>(例如1) | 否 |
3) 逻辑关键词
@media screen and (color) {} /*判断设备是否配备有彩色屏幕*/ @media not screen and (color){} /*等于 not (screen and (color))*/ @media screen and (color), projection and (color) /*逗号表示or */ /*很多浏览器支持媒介类型, 但不支持媒介查询, 有时这会导致浏览器去尝试下载那些你不希望用户看到的样式. 这时候就可以用only关键字, 对那些较老浏览器隐藏媒介查询, 这样它们就并不会识别出相应的样式了. 而支持only关键字的浏览器则会继续处理带有only关键字的查询语句*/ @media only screen and (color) /* 如果设备不支持媒介查询, 那么它将会忽略这条查询. 如果设备支持媒介查询, 那么设备将会将上面这条查询与下面这条查询等效对待 @media screen and (color)
3. 内嵌样式与外部样式
媒介查询既可以写在页面内部, 也可以通过link元素的media属性被包含到页面中去.
- 内嵌式媒介查询:
- 优点: 只需要一个http请求
- 缺点: 所有样式都会被下载, 不论是否用到. 而且单个css文件会变得很大
- 外部媒介查询
- 不论是否会用到, 其实也会下载所有的样式. 目的在于, 如果浏览器的窗口的大小或者方向发生了改变, 它的各自样式已经各就各位了
- 优点: 文件变得很小, 利于维护
4. 媒介查询顺序
- 从桌面端向下设计
-
@media all and (max- 768px){ } @media all and (max- 320px){ }
- 缺点: 移动设备对媒介查询的支持不够完善
-
- 从移动端向上设计
-
@media all and (min- 320px){ } @media all and (min- 768px){ }
-
能获得浏览器更好的支持,
-
且可以降低css文件的复杂性
-
5. 创建核心体验
6. 确定断点
传统的做法: 使用一些固定的标准宽度: 320px(iphone和其他一些设备), 768px(ipad)和1024px
存在的问题是: 可能会忽视在这些宽度之间的设备.
1) 更好的做法是 追随内容:
根据内容来决定应该在哪里设置断点以及需要设置多少个断点.
其实就是缩放浏览器, 然后缓慢拉宽窗口直到有些东西需要调整时设置断点.
2) 增加对大屏幕的支持.
3) 使用em为媒体查询增加灵活性
即使用em为单位来设置断点
7. 导航栏
- 什么都不做
- 转换为下拉列表
- 切换式菜单
第四章 响应式多媒体
优先为移动平台创建.
-
有选择地为手机提供图片
- 不在html里下载图片, 对较大的屏幕来讲使用js代码来让图片恢复. 比如设置html5的data-属性为: data-src="images/ball.jpg"
-
自定义数据属性: 专门为页面存储自定义数据并具有data-前缀的属性, 通常出于脚本编程的目的而设置
- display:none 的解决方案并不可行. 虽然它从视觉上隐藏了图片, 但是图片仍然会被请求被下载.
-
- html代码:
<ul class="slats"> <li class="group" data-src="images/ball.jpg"> <a href="#"> <h3>sssssssssss</h3> </a> </li> <li class="group" data-src="images/ball1.jpg"> <a href="#"> <h3>sssssssssss</h3> </a> </li> <li class="group" data-src="images/ball2.jpg"> <a href="#"> <h3>sssssssssss</h3> </a> </li> </ul>
js代码:
-
//添加一个用来帮助快速选取元素的工具函数 q: function(query){ //HTML5向Web API新引入了document.querySelector以及document.querySelectorAll两个方法用来更方便地从DOM选取元素,功能类似于jQuery的选择器。 //两个方法使用差不多的语法,都是接收一个字符串参数,这个参数需要是合法的CSS选择语法。其中参数可以包含多个css选择器, 用逗号隔开 //使用这两个方法无法查找带伪类状态的元素 //其中, querySelectorAll会返回所有满足添加的元素, 结果是个nodeLists集合 //querySelector返回满足条件的单个元素,按照深度优先和先序遍历的原则使用参数提供的css选择器在DOM进行查找,返回第一个满足条件的元素 if(document.querySelectorAll) { var res = document.querySelectorAll(query); } else { //addRule()貌似是IE中的方法. DOM中用insertRule() var d = document; a = d.styleSheet[0] || d.createStyleSheet(); a.addRule(query, 'f:b'); //遍历文档的所有元素, 如果已经添加了属性(f:b)的话, 意味着这个元素存在. 将其push到数组c中 for(var l=d.all, b=0, c=[], f=l.length; b<f; b++){ l[b].currentStyle.f && c.push(l[b]); a.removeRule(0); var res = c; } return res; } } //加载图片 var lazy = Utils.q('[data-src]'); for(var i=0; i<lazy.length; i++){ var source = lazy[i].getAttribute('data-src'); //创建image var img = new Image(); img.src = source; //插入 lazy[i].insertBefore(img, lazy[i].firstChild); }
addRule()参考: insertRule()与addRule()创建规则 - matchMedia
- 这是js内部自带的方法, 可以将css媒介查询作为参数传递给它, 它会返回相关媒介查询是否匹配的信息.
- 函数会返回一个MediaQueryList对象, 该对象具有两个属性: matches和media.
- matches属性可以是true(如果媒介查询匹配) 或者false.
- media属性的值就是刚刚传递的参数, 例如对于window.matchMedia("(min- 200px)")来说media属性将会返回"(min- 200px)"
- 支持浏览器: Chrome, Safari 5.1+, Firefox 9, Android 3+ 以及 ios5+
- 不支持的浏览器可以使用一个polyfill(为不支持相关功能的浏览器提供支持能力的代码片段)[http://github.com/paulirish/matchMedia.js]
//这样,在手机上或其他小窗口浏览器中加载页面时, 就不会请求图片了 if (window.matchMedia("(min- 37.5em)").matches) { //load in the images var lazy = Utils.q('[data-src]'); for(var i=0; i<lazy.length; i++){ var source = lazy[i].getAttribute('data-src'); var img = new Image(); img.src = source; lazy[i].insertBefore(img, lazy[i].firstChild); } }
- 不在html里下载图片, 对较大的屏幕来讲使用js代码来让图片恢复. 比如设置html5的data-属性为: data-src="images/ball.jpg"
-
响应式图片策略
也就是如何下载大小合适的图片- 和浏览器比赛: 在浏览器下载到错误的图片前, 这些方法要尽最大努力切换到应该被下载的正确的图片上----越来越难
- 默许浏览器的行为: 先使用默认的方法下载小屏幕可以使用的图片, 然后在需要的时候为大屏幕下载较大的图片----会产生两次请求. 不理想
- 找服务器帮忙
- 其他方法
- 第三方服务: Sencha.io Src: 在图片前加上这个服务的连接, 然后该服务会使用发起请求的设备的用户代理字符串来计算出设备屏幕的大小, 然后根据该数值来缩放图片
- 自适应图片: [Matt Wilcox]创建
-
对于高分辨率屏幕(比如Retina)
- 媒介查询
min-resolution //非WebKit. 需要两个值中的一个, 第一个值是屏幕分辨率, 单位可能是每英寸的点数, 也可以是每厘米的点数. 或者新的每像素的点数(dppx) -webkit-min-device-pixel-ratio //Webkit. 需要赋予一个十进制的表示像素比的值
- SVG(可伸缩矢量图形)
- 是用XML定义的矢量图形, 也就是可以在不增加实际文件大小的前提下自如缩放
- 问题在于: 浏览器的支持情况不理想 以及 相应工具的缺乏
- 媒介查询
-
其他固定宽度的内容
- 视频
- 广告
中间两章讲设计.
其中涉及到一个模型的问题:
我之前了解的是使用图形处理软件来创建初始模型(比如PS). 但是静态模型对响应式设计并没有任何帮助. 所以应当到浏览器中去设计.
第7章 响应式内容
1. 从内容开始
2. 内容类型
3. 在什么时候显示什么内容
- 删除内容
- 加强内容: 这是一种更好的方法. 即先单独设计每种体验, 然后再通过加强内容来使其能按计划做出不同的响应
4. 何时改变内容的顺序
5. 构建API
第8章 RESS(响应式设计和服务器端组件)
1. 用户代理检测
- 用户代理检测是通过检测浏览器的用户代理字符串来决定为设备提供哪种站点的方法, 这一过程是在服务器端完成的.
- 用户代理字符串是在浏览器请求某一页面时发送出去的一种http头, 其目的在于辨识使用中的客户端(浏览器)
- 优点:
- 提供了详细的设备信息
- 因为是在服务器端运行的, 所以可以删掉页面中不必下载到设备删更多内容
- 缺点:
- 由于浏览器长期以来的欺骗行为, 使用不当的话结果就会不可靠
- 需要使用第三方服务来获取详细的设备信息, 增加了额外的项目成本
2. 功能检测
- 在客户端进行. 不必再纠缠于复杂的用户代理字符串中了. 而只需用JS来检测某一特定功能是否被支持
return !!window.JSON; //检测设备是否原生支持JSON
- Modernizr: 一个可以通过功能检测的脚本.
- 可测试超过40种不同功能, 还能提供另外三样有助于开发的东西
- 会创建一个包含测试结果的js对象
- 会在html元素中增加类名, 以表明对于功能的支持情况
- 提供一个脚本加载器, 就可以有条件地加载polyfill
- 将这个脚本放在文档的头部, 也可以为页面的html元素增加一个nojs的类
- 可测试超过40种不同功能, 还能提供另外三样有助于开发的东西
- 服务器端Modernizr
- 优点:
- 不依赖于用户代理字符串
- 允许基于不同的需求在js库中定制功能
- 缺点
- js有可能被禁用, 或者浏览器压根不支持js
- 浏览器常常会夸大自己的能力, 并且其支持程度也不仅仅是支持或不支持
- 如果在客户端实现, 就无法有效做到内容适应; 如果在服务器端实现, 就又需要额外加载一次页面
3. 将用户代理检测和功能检测相结合
4. RESS
- 将服务器端检测和响应式设计结合起来, 叫做RESS.
- 首先为所有设备创建一个核心站点, 然后再在服务器端针对特定的设备定制并渲染单独的组件
- 优点:
- 响应式设计使得布局是设备无关的, 因此相比简单的独立站点而言, 这种站点能够支持广泛的设备
- 服务器端检测减少了用户下载的数据量, 并将用户从不必要的且漫长的下载时间中解救了出来
- 可替换的组件允许你针对不同设备来定制体验, 以达到与设备相适应的目的
此外参考: Media Queries 媒体查询常见设备断点