如何构建一个响应式网站

什么是响应式web网站

以前我写网的网页习惯的网页都是定宽的,比如最外层设置一个宽度为980px的盒子,这是因为那时候的网页主要显示在pc端上,而pc端显示器的大小差异不会特别大。于是固定宽度的样式写法成为了流行趋势。但是随着移动互联网的到来,设备类型的增多,如智能手机,平板。那么屏幕大小的差异也就凸显出来了,如果每一个屏幕设备宽度写一个样式的话,会发现存在大量重复的样式代码,且工作量会很大,于是我们需要一种减少重复样式,让样式能够自动适应屏幕的解决方案就出来了:"响应式"。
我们知道不同的设备拥有不同屏幕大小即视口(viewport),那么我们不可能一个样式适应所有的屏幕大小,那么响应式解决的就是网站自动去识别不同屏幕,然后去使用对应的样式去适应屏幕。

注:“视口”(viewport),指显示网页的区域

响应式的核心技术

1.viewport属性

为了能够让我们的网页去适应屏幕的大小,我们需要添加一个meta属性

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  • width=device-width:把宽度设置为设备宽度(自动适应屏幕宽度)
  • user-scalable:不允许用户缩放 (允许用户缩放视口大小,会增加复杂度)
  • initial-scale=1.0:初始化缩放比例
  • minimum-scale=1.0:最小缩放比例

2.媒体查询

至此我们解决了让网页自动适应不同的视口大小,但是不同的视口大小要显示不同的样式,我们还需要借助媒体查询来完成。
CSS3规范分成很多模块,媒体查询(3级)只是其中一个模块。利用媒体查询,可以根据设备的能力应用特定的CSS样式。比如,可以根据视口宽度、屏幕宽高比和朝向(水平还是垂直)等,只用几行CSS代码就改变内容的显示方式。媒体查询得到了广泛实现。除了古老的IE(8及以下版本),几乎所有浏览器都支持它。

媒体查询的语法

说了这么多媒体查询长什么样子呢,我们来看一点示例代码。

div {
    background:green
}

@media screen and (min-width:350px){
    div {
        background:red
    }
}

@media表示媒体查询代码,上面的内容含义是,如果是屏幕设备,并且视口宽度大于等于350px那么就会把div的背景颜色设置为红色,由于代码是由上向下循序解析的,所以,背景色红色会覆盖上面的背景色绿色的代码。

注:因为我们接触的设备都是有屏幕的所以screen可以省略

  • 在 link 标签中使用媒体查询
<link rel="style sheet" type="text/css" media="(min-width:350px)" href="index.css">

这里会告诉浏览器,视口宽度大于等于350px时才加载index.css样式文件。

  • @import 中使用媒体查询
@import url("base.css") screen and (max-width:350px);

css中可以通过import来导入其他的样式文件,这里告诉浏览器视口宽度大于等于350px时才加载base.css样式文件。

  • 在css中使用媒体查询
@media screen and (min-width:350px){
    div {
        background:red
    }
}

这里告诉浏览器视口宽度大于等于350px时把div的背景色设置为红色。

媒体查询中支持的属性

其他媒体查询最常用的属性就是min-width和max-width,其他的属性你可能一辈子都用不上

  • width:视口宽度。
  • height:视口高度。
  • max-width:最大视口宽度
  • min-width:最小视口宽度
  • device-width:渲染表面的宽度(可以认为是设备屏幕的宽度)。
  • device-height:渲染表面的高度(可以认为是设备屏幕的高度)。
  • orientation:设备方向是水平还是垂直。
  • aspect-ratio:视口的宽高比。16∶9的宽屏显示器可以写成aspect-ratio:16/9。  color:颜色组分的位深。比如min-color:16表示设备至少支持16位深。
  • color-index:设备颜色查找表中的条目数,值必须是数值,且不能为负。
  • monochrome:单色帧缓冲中表示每个像素的位数,值必须是数值(整数),比如
    monochrome: 2,且不能为负。
  • resolution:屏幕或打印分辨率,比如min-resolution: 300dpi。也可以接受每厘
    米多少点,比如min-resolution: 118dpcm。  scan:针对电视的逐行扫描(progressive)和隔行扫描(interlace)。例如720p HD TV(720p
    中的p表示progressive,即逐行)可以使用scan: progressive来判断; 而1080i HD TV
    (1080i中的i表示interlace,即隔行)可以使用scan: interlace来判断。
  • grid:设备基于栅格还是位图。

3.响应式图片

开发者不可能知道或预见浏览网站的所有设备,只有浏览器在打开和渲染内容时才会知道使用它的设备的具体情况(屏幕大小、设备能力等)。另一方面,只有开发者(你和我)知道自己手里有几种大小的图片。比如,我们有同一图片的三个版本,分别是小、中、大,分别对应于相应的屏幕大小和分辨率。浏览器不知道这些,我们得想办法让它知道。
简言之,难点在于我们知道自己有什么图片,浏览器知道用户使用什么设备访问网站以及最合适的图片大小和分辨率是多少,两个关键因素无法融合。

使用picture元素

<picture> 
 <source media="(min-width: 750px)" srcset="source-medium.jpg"> 
 <source media="(min-width: 350px)" srcset="source-small.jpg"> 
 <img src="source.jpg"> 
</picture>

以上代码会根据视口宽度来适应使用不同的图片,如果视口宽度大于等于750px那么使用source-medium.js图片,否则,如果视口宽度大于等于350px使用source-small.jpg图片,否则都不满足条件使用source.jpg图片。这里source的顺序很重要,根据min-width大小按顺序进行编写,相反如果使用max-width就需要倒序编写。这样就可以根据不同大小视口使用不同大小的图片。

虽然<picture>很好用,但浏览器支持并不是全面。幸运的是,您可以在不支持此元素的浏览器中使用,方法就是使用Picturefill.js,下载地址: https://scottjehl.github.io/picturefill

<script>document.createElement("picture");</script>
<script src="js/picturefill.min.js" async></script>

第一个<script>块用于无法识别<picture>元素的浏览器,如果浏览器在Picturefill完成加载之前用HTML解析它们,就可以防止出现问题。然后第二个块加载Picturefill库。

使用用Modernizr有条件地加载Picturefill:
Modernizr (http://modernizr.com)是一个健壮的特性检测库,它提供了一种简单的方法来检测浏览器对一组特性的支持,并且它的大小也只有1.8k。

<script src="js/modernizr.custom.min.js"></script>
<script>
 if(Modernizr.srcset === false || Modernizr.picture === false){
 var picturefill = document.createElement("script");
 picturefill.src = "js/picturefill.min.js";
 document.body.appendChild(picturefill);
 }
</script>

以上代码表示如果你的浏览器支持picturesrcset属性那么久不下载pictruefill.js,反之亦然。

max-width

img { 
 max-width: 100%; 
}

这里声明max-width,就是要保证所有图片最大显示为其自身的100%(即最大只可以显示为自身那么大)。此时,如果包含图片的元素(比如包含图片的body或div)比图片固有宽度小,图片会缩放占满最大可用空间。

为什么不用width:100%?
如果使用width:100%的话那么,图片的宽度就会是父容器的宽度,如果父容器的宽度大于图片的真实宽度,那么图片就会被拉伸变形。而max-width:100%则不会,因为宽度默认是auto那么会显示真实宽度,如果宽度大于父容器宽度,也会等比例缩放到父容器宽度

4.弹性布局

在很早很早之前,网站的宽度大都以百分比形式定义。百分比布局使得网页宽度能够随着查看它们的屏幕窗口大小变化,因而得名弹性布局。后来出现了固定宽度的布局方式,现如今,我们要做响应式设计了,又得回头捡起弹性布局设计。相信前端人员都用过flexbox,使用起来也非常的爽,之前垂直居中,瀑布流等写起来非常痛苦,但flexbox就很方便的解决了这些问题。

前缀

flexbox是css3中的属性,所以为了兼容各种浏览器需要添加各种浏览器对应的前缀,一下提供自动加前缀的方法:

主要属性

  • display:flex
    声明你的盒子是一个flexbox
  • flex-direction
    声明主轴的方向

flex中没有水平和垂直的说法,只有主轴和侧轴的说法,比如,flex-direction:row,那么你的主轴方向为水平方向,侧轴方向为垂直方向,于是,justify-content: center以主轴方向对齐即当前为水平方向对齐,align-content: center以侧轴方向对齐即当前为垂直方向对齐,flex-direction:clunm反之亦然

  • flex-wrap
    主轴方向是否支持换行
  • justify-content
    主轴方向对齐方式
  • align-content
    侧轴方向对齐方式
  • flex
    子盒子在父盒子中占的比例

举例:

垂直居中

<style>

    div{
        width: 400px;
        height: 300px;
        margin: 200px auto;
        display: flex;
        flex-direction: row;  //默认主轴方向是row即水平方向
        flex-wrap: wrap; //允许换行
        align-content: center;  //设置侧轴方向居中
        background-color: paleturquoise;
    }
    p{
        width: 100px;
        height: 100px;
        line-height: 100px;
        background-color: rebeccapurple;
        text-align: center;
    }
</style>
<div>
    <p>hello world</p>
</div>

QQ截图20200727171509.png

水平偏移

<style>
    ul{
        list-style: none;
        padding: 0;
        margin: 0;
        display: flex;
        flex-wrap: nowrap;
        /*flex-direction: row-reverse;*/
        align-content:center;
        background-color: deeppink;
    }
    li{
        width: 100px;
        height: 50px;
        text-align: center;
        line-height: 50px;
        margin-right: 1px;
    }
    li:last-child{
        margin-left: auto;
    }
</style>
<ul>
    <li>首页</li>
    <li>动画</li>
    <li>电视剧</li>
    <li>电影</li>
    <li>联系我们</li>
</ul>
批注 2020-07-27 182950.png

flexbox的详细教程请看下期 “神奇的flexbox“

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343