CSS3 媒体查询与响应式布局
第一章 序论
现今每天都有更多的手机和平板电脑问市。消费者能够拥有可想象到的各种规格和形状的设备,但是网站开发人员却面临一个挑战:如何使他们的网站在传统浏览器、手机和平板电脑浏览器上有很好的效果,如何在各种大小的屏幕上提供一流的用户体验?
答案是:采用响应式设计。
响应式设计可以随所显示的屏幕大小而改变。实现响应式设计的主要方法是使用 CSS 媒体查询。
Bootstrap的栅格系统就是通过媒体查询来实现的。
第二章 回顾媒体类型 media type
HTML4 和 CSS2支持根据媒体类型(media type)加载。
比如,如果是'屏幕设备',则加载screen.css
,如果是'打印设备',则加载print.css
。
HTML4和CSS2 支持媒体类型来决定使用CSS样式,例:
<link rel="stylesheet" type="text/css" media="screen" href="sans-serif.css">
<link rel="stylesheet" type="text/css" media="print" href="serif.css">
我们同样可以在CSS样式表中,声明条文适用于某些媒体类型。
@media screen {
* { font-family: sans-serif }
}
可以在使用@import导入CSS时使用媒体查询,有条件地向当前样式表中加载其他样式表。
@import url("serif.css") screen;
print
和screen
媒体类型是HTML4中定义的.
HTML4定义的媒体类型如下:
- screen 屏幕
- print 打印机
- all 所有
- aural 声音
- braille 盲文
- handheld移动设备
- projection 投影仪
- tty 打字机
- tv 电视
- embossed 盲文打印
令人尴尬的是,除了前3种类型,剩下的几乎没人用,实际已经废弃了.
第三章 媒体查询 media query
媒体查询是评估 True 或 False 的一种表达。如果为 True,则继续使用样式表。如果为 False,则不能使用样式表。这种简单逻辑通过表达式变得更加强大,使我们能够更灵活地对特定的设计场景使用自定义的显示规则。
媒体查询(media query)则根据媒体类型(medir type)和由媒体特征(media features)值组成的表达式.
媒体特征值如: width
, height
,color
,即宽,高,色彩等.
共有13种特征(重点记住前3种) , 如下:
设 备 特 性 | 是否允许 min/max 前缀 | 特 性 的 值 | 说 明 |
---|---|---|---|
width | 允许 | 含单位的数值 | 指定浏览器窗口的宽度大小, 如480像素 |
height | 允许 | 含单位的数值 | 指定浏览器窗口的高度大小, 如320像素 |
orientation | 不允许 | 字符串值 | 指定移动设备浏览器的窗口方向。 只能指定portrait(纵向)和landscape (横向)两个值 |
device-width | 允许 | 含单位的数值 | 指定移动设备的屏幕分 辨率宽度大小,如480像素 |
device-height | 允许 | 含单位的数值 | 指定移动设备的屏幕分 辨率高度大小,如320像素 |
aspect-radio | 允许 | 比例值 | 指定移动设备浏览器窗口的 纵横比例,如16:9 |
device-aspect-radio | 允许 | 比例值 | 指定移动设备屏幕分辨率的 纵横比例,如16:9 |
color | 允许 | 整数值 | 指定移动设备使用多少位的颜色值 |
color-index | 允许 | 整数值 | 指定色彩表的色彩数 |
monochrome | 允许 | 整数值 | 指定单色帧缓冲器中每像素的字节数 |
resolution | 允许 | 分辨率值 | 指定移动设备屏幕的分辨率 |
scan | 不允许 | 字符串值 | 指定电视机类型设备的扫描方式。 只能指定两种值:progressive表 示逐行扫描和interlace表示隔行扫描 |
grid | 不允许 | 整数值 | 指定设备是基于栅格还是基于位图。 基于栅格时该值为1,否则为0 |
第四章 媒体查询实战
@media screen and (width: 600px){
body {
background: gray;
}
}
上例指,对于屏幕且浏览器宽600px像素时,启用指定的css.
缩放浏览器试一下, 当浏览器窗口恰好是600px
宽时,背景变灰.
上例中的媒体查询不是很实用,因为宽度恰好400px
像素的条件太苛刻.
在实战中,用范围表达宽度更普遍.
@media screen and (min-width: 600px){
body {
background: gray;
}
}
上例指:对于屏幕且最小600宽(>=600px)的浏览器时,启用指定的css.
拖动浏览器试一下?
同时,打印预览再看一下背景色,想一想为什么?
@media (orientation:portrait){
body {
background: gray;
}
}
@media (orientation:landscape){
body {
background: blue;
}
}
上例中,指屏幕height>width
时,如手机竖直时,和屏幕width>height
,如手机横放时,启动指定的css。
在针对所有设备的媒体查询中,可以使用简写语法,即省略关键字all(以及紧随其后的and)。换句话说,如果不指定关键字,则关键字就是all。
第五章 复杂表达式
媒体查询表达式还可以更复杂。
5.1 and联查
在表达式中,我们可以根据自己的喜好和需求使用任意数量的 and 条件。如果想要增加其他条件来检查特定的屏幕方向,只需添加另一个 and 关键词,后跟 orientation 媒体查询。
@media screen and (min-width:768px) and (max-width:1200px) and (orientation:landscape){
*{
background:blue;
}
}
5.2 or条件
媒体查询中使用逗号分隔效果等同于 or 逻辑操作符。当使用逗号分隔的媒体查询时,如果任何一个媒体查询返回真,样式就是有效的。逗号分隔的列表中每个查询都是独立的,一个查询中的操作符并不影响其它的媒体查询。
@media (width:768px), screen and (orientation:portrait) {
* {
background: blue;
}
}
5.3 not条件
not 关键字应用于整个媒体查询,在媒体查询为假时返回真,但仅能应用于整个查询,而不能单独应用于一个独立的查询。所有的not判断都在媒体查询的最后进行。
注意区分:
@media not all and (min-width:768px) {
*{
background:blue;
}
}
等价于:
@media not (all and (min-width:768px)) {
*{
background:blue;
}
}
虽然这么写也是错误的,我们只是用来理解not的判断顺序。
而不是:
@media (not all) and (min-width:768px){
*{
background:blue;
}
}
第六章 响应式布局
6.1 思路
响应式布局即根据浏览器或屏幕的大小,调整页面的布局方式.
例:
先尝试做一些"不响应式"的div
来,只考虑定义12个类,宽分别是1/12,2/12...12/12,且分别左浮.
*{
box-sizing: border-box;
}
.col-xs-1,
.col-xs-2,
.col-xs-3,
.col-xs-4,
.col-xs-5,
.col-xs-6,
.col-xs-7,
.col-xs-8,
.col-xs-9,
.col-xs-10,
.col-xs-11,
.col-xs-12 {
min-height:1px;
float:left;
}
.col-xs-12 {
width: 100%;
}
.col-xs-11 {
width: 91.66666667%;
}
.col-xs-10 {
width: 83.33333333%;
}
.col-xs-9 {
width: 75%;
}
.col-xs-8 {
width: 66.66666667%;
}
.col-xs-7 {
width: 58.33333333%;
}
.col-xs-6 {
width: 50%;
}
.col-xs-5 {
width: 41.66666667%;
}
.col-xs-4 {
width: 33.33333333%;
}
.col-xs-3 {
width: 25%;
}
.col-xs-2 {
width: 16.66666667%;
}
.col-xs-1 {
width: 8.33333333%;
}
<div class="row">
<div class="col-xs-3">第一列</div>
<div class="col-xs-3">第二列</div>
<div class="col-xs-3">第三列</div>
<div class="col-xs-3">第四列</div>
</div>
<div class="row">
<div class="col-xs-4">第五列</div>
<div class="col-xs-4">第六列</div>
<div class="col-xs-4">第七列</div>
</div>
无论我们怎么拖动浏览器的宽窄,这四列始终相对位置不变.
来一堆div
<div class="row">
<div class="col-sm-4">三一列</div>
<div class="col-sm-4">三二列</div>
<div class="col-sm-4">三三列</div>
</div>
注意看类名col-sm-4
,由于我们没有定义这个类,因此呈现div的默认效果,即宽100%,因此都是竖直方向堆积显示.
6.2 "响应式"布局
我们假设当浏览器变到768px
宽时,col-sm-4
变为25%宽,且左浮.
程序表达:
if(width>=768px) {
.col-sm-4 {
25%px;
float:left;
}
}
结合前面学的媒体查询Media Query,我们写如下代码:
@media (min-width: 768px) {
.col-sm-1 {
width: 8.333333%;
}
.col-sm-2 {
width: 16.666667%;
}
.col-sm-3 {
width: 25%;
}
.col-sm-4 {
width: 33.333333%;
}
.col-sm-5 {
width: 41.666667%;
}
.col-sm-6 {
width: 50%;
}
.col-sm-7 {
width: 58.333333%;
}
.col-sm-8 {
width: 66.666667%;
}
.col-sm-9 {
width: 75%;
}
.col-sm-10 {
width: 83.333333%;
}
.col-sm-11 {
width: 91.666667%;
}
.col-sm-12 {
width: 100%;
}
.col-sm-1,
.col-sm-2,
.col-sm-3,
.col-sm-4,
.col-sm-5,
.col-sm-6,
.col-sm-7,
.col-sm-8,
.col-sm-9,
.col-sm-10,
.col-sm-11,
.col-sm-12 {
position: relative;
float: left;
}
}
分析: 当浏览器width>=768px
时,对应的css发挥作用,把col-sm-*
的宽度按百分比设置,且左浮,形成了响应效果。
第七章 Bootstrap细节处的技巧
Container
有两个作用:
在随时可能的宽度变化(响应式)中提供宽度限制。当页面宽度变化,container 的宽度也随之变化。并且其中的 column 的宽度是基于百分比,所以他们的值不需要变化。
提供一个水平方向的 padding,使其内部的内容不会接触到浏览器的边界,大小为15px,就是图片中粉红色的部分,作用会在下面说。
注意,不需要也不应该在 container 中嵌套另一个 container。
Row
Row 是 column 直接存在的容器,按照文档描述 row 中最多可有12个 column,不过可以通过套嵌的方式灵活扩展。同时作为都是左浮动的 column 的容器,自带清除浮动的性质。
同时 row 还有一个很特殊的地方,就是左右各有 -15px 的 margin,就是图片中的蓝色部分。这样也就抵消了上面提到的 container 中15px的 padding,那么为什么要这么折腾呢?接着看往下读。
注意:千万记住要把 row 放到 container 的内部,这样才能保证正常。
Column
注意,每个column 也会有15px的水平方向的 padding,也就是图片中黄色的部分,还记得上面提到的 row 的作用吗,column 只能在 row 中生存,由于 row 的 margin 为-15px,那么位于两边的 column 就碰到了 container 的边界。但是 colunmn 本身又有 15px 的 padding 使得它其中的内容并不会碰到 container,同时 不同column的内容之间就有了30px的槽。结合图片看一下就一目了然了。
注意:一定要把 column 放到 row 里使用。
Nesting
当把上面一系列的 container, row, column 都设置好,就可以通过套嵌 扩展它的栅格系统了,也就是在 column 中直接嵌套 row,而不需要再套一层 container:
还记得 container 和 column 都有15px的 padding 吗,对在套嵌的时候 column 的作用也相当于 container 了,这样就可以实现任意的嵌套了。
1px
根据我们上面完善后的boolstrap,写一个最简单的布局:
<style type="text/css">
.container{
background:gray;
}
</style>
<div class="container">
<div class="row">
<div class="col-sm-3"></div>
<div class="col-sm-9">右面有九个</div>
</div>
</div>
但是实际效果并不是我们想象的那样:
左侧的3列并没有显示。
这是因为,我们的列都是左浮的,当左侧元素没有内容的时候,右侧的列会直接占据其位置。我们只需要给列一个最小的行高,即可解决这个问题。
.col-md-1,
.col-md-2,
.col-md-3,
.col-md-4,
.col-md-5,
.col-md-6,
.col-md-7,
.col-md-8,
.col-md-9,
.col-md-10,
.col-md-11,
.col-md-12{
min-height:1px;
padding:0px 15px;
}
列偏移
使用 .col-md-offset-*
类可以将列向右侧偏移。这些类实际是通过使用选择器为当前元素增加了左侧的边距(margin)。
我们可以类似下面的方法实现列偏移:
.col-md-offset-4{
margin-left:33.333%;
}
对于列排序,则是通过相对定位,重新定位列的位置。
Container和Container-fluid
通过分析源码,我们可以得知在Bootstrap中,container是阶梯状增长的,用于固定宽度并支持响应式布局的容器。
@media (min-width: 768px) {
.container {
width: 750px;
}
}
@media (min-width: 992px) {
.container {
width: 970px;
}
}
@media (min-width: 1200px) {
.container {
width: 1170px;
}
}
而container-fluid则是用于 100% 宽度,占据全部视口(viewport)的容器。
我们设定container-fluid为
.container-fluid{
width:100%;
padding:0px 15px;
}
还有很多方法可以实现响应式布局 比如我们学过的弹性盒模型和display:table-cell