Web开发常用布局方式总结

网络图片

一.概述

无论是前端还是客户端开发都离不开页面的展示,而页面是由布局和各种组件构成的。布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦。组件按照布局的要求依次排列,就组成了用户所看见的界面。比如Android开发者常用的布局方式有:线性布局(LinearLayout)、相对布局(RelativeLayout)、绝对布局(AbsoluteLayout)、网格布局(GridLayout)等,IOS开发者常用的布局方式:手写Frame、自动布局(AutoLayout)、xib、storyboard等方式,我们这里主要介绍前端的布局方式。虽然目前大多数网站的构建都是通过成熟的框架搭建的,但是作为前端开发的基础,学习了解一下布局还是很有必要的。

页面布局(Layout):就是对页面的文字、图形或表格进行排布、设计. --- 知乎

研究布局的目的是让我们的页面尽可能的还原UI设计给我们的设计图,适配各种尺寸的屏幕,使其在各种尺寸屏幕上能很好地显示出我们的视图。

我们来看下我们Web开发中常用的几种布局类型:

二.布局类型

1. 普通流布局

这是页面默认布局的方式 ,每个元素都有默认空间,每个元素都是在父元素的左上角出现的,页面中的块元素都是按照从上到下的方式出现,每个块元素独占一行,页面中行内元素都是从左到右的方式排列.
每个元素都有一个默认的 display 值,这与元素的类型有关。对于大多数元素它们的默认值通常是 blockinline 。一个 block 元素通常被叫做块级元素。一个 inline 元素通常被叫做行内元素。比如 div 是一个标准的块级元素,页面在进行渲染时候,遇到块级元素会另起一行,而行内元素会在当前行进行展示。举个简单的例子:

html
<head>
      <title>标题</title>
      <style>
          * {
              padding: 0;
              margin: 0;
              box-sizing: border-box;
          }
          body {
              background-color: white;
          }
          div {
              border: 1px solid red;
          }
          span {
              border: 1px solid green;
          }
          body :nth-child(4) {
              display: inline-block;
              background-color:salmon;
          }
      </style>
  </head>
  <body>
      <div>这是一个div块元素</div>
      <span>这是一个行内元素</span>
      <span>这是另一个行内元素</span>
      <div>
          这是行内块元素
      </div>
      <div>这是还是一个div块元素</div>
  </body>
图片1
  • 可以看到div元素是单独占一行的,而行内元素span不会换行。其他常用的块级元素包括 ph1——h6form 以及Html5中的新元素: headerfootersection 等等。常用的行内元素ainputimglabel等。
  • display 的取值除了为blockinline 外还可以取值inline-block,它表示行内块元素,如果一个块元素的display属性取值为inline-block,那么他就不在换行,比如我们这里的第二个div元素。如果一个行内元素display取值为inline-block那么它就具有了块元素的一些特性,例如我们可以改变它的尺寸。
  • 另一个常用的display值是 none。一些特殊元素的默认display 值是它,例如 scriptdisplay:none 通常被 JavaScript 用来在不删除元素的情况下隐藏或显示元素。它和 visibility 属性不一样。把 display 设置成 none 元素不会占据它本来应该显示的空间,但是设置成 visibility: hidden; 还会占据空间。
  • display 还有一些其他取值,可以看这里

2. 浮动布局

属性:float
取值:
none: 默认,无浮动
left: 左浮动,让元素在父元素的左边,或者挨着已有的浮动元素
right: 右浮动,让元素在父元素的右边,或者挨着已有的浮动元素
我们看下它如何使用,正常情况下的布局:

 <!DOCTYPE html>
<html>
    <head>
        <title>正常布局</title>
        <meta charset="UTF-8">
        <style>
            * {
                margin:  0;
                padding: 0;
                box-sizing: border-box;
            }
            .container {
                background-color: wheat;
            }
            .left {
                width: 100px;
                height: 200px;
                background-color: rosybrown;
            }
            .right {
                width: 100px;
                height: 200px;
                background-color: saddlebrown;
            }
            .last {
                width: 100px;
                height: 200px;
                background-color: red;
            }
        </style>
    </head>

    <body>
        <div class="container">
            <div class="left">左侧</div>
            <div class="right">右侧</div>
        </div>
        <div class="last">后面</div>
    </body>
</html>
图片2

现在我们分别给.left.right 添加浮动属性,添加下面代码

.left {
    float: left;
    width: 100px;
    height: 200px;
    background-color: rosybrown;
   }
.right {
    float: right;
    width: 100px;
    height: 200px;
    background-color: saddlebrown;
}
图片3

看下页面效果,左右两个模块倒是符合我们的预期,但是container元素的背景没有了,我们检查下元素,可以看到container的高度变成了0,last只展示了文字,背景没有了。这就说到float属性的特点了:

特点:

  • 元素将被排除在文档流之外,不在占据页面的空间。其他未浮动元素将会向前占位。
  • 浮动元素会 停靠在父元素的 左边或者 右边,或者其他浮动元素的边缘上。
  • 文本行内文字都是采用环绕方式排列的,不会被浮动元素压地下,而是会巧妙的避开浮动元素。
    解决浮动带来的影响
    (1)可以直接设置父元素的高度,比如直接添加height:300px;
    (2)为父元素设置overflow 取值 hidden或者auto
    (3)使用clear属性,取值both可以解决左右浮动带来的影响。这里注意:这里要给contariner容器添加子元素
    (4)在容器内添加一个CSS伪元素,并将其clear属性设置为both。
<div class="container">
    <div class="left">左侧</div>
    <div class="right">右侧</div>
    <div style="clear:both"></div>
</div>

或者是

.container::after {
  content: "";
  display: table;
  clear: both;
}

看下效果,符合我们的预期了


tupian3

实际上浮动最主要的作用:是可以使块级元素在一行内显示。并且可以使文字可以环绕浮动元素进行排列。

3. 定位布局

  • 属性:position,默认值:static,根据其取值的的不同分为:
    相对定位:position:relative;
    绝对定位:position:absolute;
    固定定位:position:fixed;
    只要是元素的position 属性取值不为static,那么这个元素就被称为已定位元素。这里需要注意,后面在介绍这几种定位时,已定位元素会对他本身的位置有所影响。
  • 偏移属性: topleftrightbottom,取值是以px为单位的数值,取值可以是正数也可以是负数,分别对应不同方向的偏移
    top:取值为正,向下移动,取值为负数,向上移动
    bottom:取值为正,向上移动,负值 向下移动。
    left:取值为正,右移动,负值 左移动
    right:取值为正 左移动,负值 右移动

如何记忆:可以参考下面的图例,取值为正数时,都是向元素的内部进行靠拢,取值为负数时候都是向远离元素的位置移动。


tupian4
(1)相对定位relative

元素相对于他原来的位置进行距离偏移

用法:position:relative;配合 top、left、right、bottom进行位置的微调
我们还是以上面的正常文档流布局为例,现在我们想让右侧块跟左侧块在一行显示,并且在左侧块的右边显示,实现下图的效果

pic5

那么我们可以设置.right的布局如下

.right {
    position: relative;
    top: -100px; 
    left: 50px; 
    width: 50px;
    height: 100px;
    background-color: saddlebrown;
}
(2)绝对定位absolute

元素会相对于离他最近的已定位的(三种定位方式的一中)祖先元素去实现位置的初始化跟偏移,祖先元素就是本元素的父级元素。如果没有已定位的祖先元素,那就相对于body去实现位置的初始化跟偏移。绝对定位元素会变成块级元素。

用法:position:absolute;配合 top、left、right、bottom进行位置的微调
现在我们想让右侧块块叠加在左侧块之上显示,实现下图的效果;

pic7

那么我们可以设置.right的布局如下

.right {
    position: absolute;
    top: 50px;
    left: 0;
    width: 50px;
    height: 100px;
    background-color: saddlebrown;
}
  • 可以看到当子元素元素的postion属性设置为absolute后 原先父元素的高度变化了,说明.right脱离了文档流,不再占据页面空间。注意这里top: 50px;的改变是相对于body改变的,其初始化位置为文档流的左上角,因为其父元素container并不是已定位的元素。
(3)固定定位fixed

固定定位(position:fixed)元素会相对于视窗来定位,这意味着即便页面滚动,它还是会停留在相同的位置。和 relative 一样, top 、 right 、 bottom 和 left 属性都可用。

我们还是拿上面的例子,我们将last固定在页面的右下角,设置last的CSS如下

.last {
    position: fixed;
    right: 0;
    bottom: 0;
    width: 70px;
    height: 75px;
    background-color: red;
}
  • 注意position:fixed的元素也会脱离文档流。
(4)定位补充

一旦将元素设置 已定位元素(position的取值不为static),元素可能会出现堆叠效果,堆叠效果的属性:z-index,取值:无单位的数子,数子越大越靠上

我们以上面绝对定位的例子来说明,设置了right为绝对定位后,rightleft的上面,此时如果想让left在上,right在下,实现下面效果

pic8

设置left的CSS代码

.left {
    position: relative;
    z-index: 10;
    width: 50px;
    height: 100px;
    background-color: rosybrown;
}
  • 注意:只有已经定位的元素可以使用z-index,如果不设置position: relative;是没有效果的,父子元素之间无法调整堆叠效果,子元素压在父上。

4. flex布局

flex布局又叫弹性布局,是一种为一维布局而设计的布局方法。一维的意思是你希望内容是按行或者列来布局。你可以使用display:flex来将元素变为弹性布局。我们直接看例子:
实现7个item横向排列

图片

<!DOCTYPE html>
<html>
    <head>
        <title>flex布局2</title>
        <meta charset="UTF-8">
        <style>
            * {
                margin:  0;
                padding: 0;
                box-sizing: border-box;
            }
            .container {
                display: flex;
                flex-direction: row;
                justify-content: flex-start;
                align-items: flex-end;
                background-color: wheat;
                flex-wrap: wrap;
            }
           .item {
               width: 100px;
               height: 100px;
               border: 1px solid royalblue;
               text-align: center;
               line-height: 100px;
               margin: 10px 10px;
           }
           .item6 {
               flex: 1;
           }
           .item7 {
               flex: 2;
           }
        </style>
    </head>

    <body>
        <div class="container">
            <div class="item0 item">item0</div>
            <div class="item1 item">item1</div>
            <div class="item2 item">item2</div>
            <div class="item3 item">item3</div>
            <div class="item4 item">item4</div>
            <div class="item5 item">item5</div>
            <div class="item6 item">item6</div>
            <div class="item7 item">item7</div>
        </div>
    </body>
</html>

上面的代码基本基本涵盖了我们常用的flex的属性

  • display:flex: 设置container容器为弹性布局

  • flex-direction:决定主轴的方向,项目横向或是纵向排列
    取值:row | row-reverse | column | column-reverse;
    row(默认值):主轴为水平方向,起点在左端。
    row-reverse:主轴为水平方向,起点在右端。
    column:主轴为垂直方向,起点在上沿。
    column-reverse:主轴为垂直方向,起点在下沿。

  • justify-content: 定义Item在主轴上如何对齐。
    取值:flex-start | flex-end | center | space-between | space-around;
    flex-start(默认值):左对齐
    flex-end:右对齐
    center: 居中
    space-between:两端对齐,项目之间的间隔都相等。
    space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

  • align-items:定义Item在交叉轴上如何对齐。
    取值:align-items: flex-start | flex-end | center;
    flex-start:交叉轴的起点对齐。
    flex-end:交叉轴的终点对齐。
    center:交叉轴的中间点对齐。

  • flex-wrap:一条轴线上放不下,决定其是否换行
    取值: nowrap(不换行) | wrap(换行)

  • flex 属性:flex属性是flex-grow, flex-shrinkflex-basis的简写,默认值为0 1 auto。
    flex-grow: 属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。 取值越大,占用剩余空间越大。
    flex-shrink: 属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
    flex-basis:属性指定了flex元素在主轴方向上的初始大小

这里设置item6item7 的flex为1和2,表示当前轴剩余的空间item6占1/3,item7占2/3.

我们访问caniuse查看浏览器对它支持情况,可以看到目前绝大多数浏览器是支持这个属性的。

pic9

更多的关于flex的属性可以查看这里:flex布局

5. grid布局

grid布局又叫网格布局,讲到布局,我们就会想到 flex布局,甚至有人认为既然有flex布局了,似乎没有必要去了解Grid布局。但flex布局和Grid布局有实质的区别,那就是flex 布局是一维布局,Grid布局是二维布局。flex布局一次只能处理一个维度上的元素布局,一行或者一列。Grid布局是将容器划分成了“行”和“列”,产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到我们布局的目的。看下面的例子

图片

<!DOCTYPE html>
<html>
    <head>
        <title>grid2布局</title>
        <meta charset="UTF-8">
        <style>
            * {
                margin:  0;
                padding: 0;
                box-sizing: border-box;
            }
            .container {
                display: grid;
                grid-template-columns: repeat(4,1fr);
                grid-auto-rows: minmax(100px,auto);
                grid-gap: 10px;
                background-color: skyblue;
            }
            .item {
                border: 1px solid cyan;
                text-align: center;
            }
            .item0{
                background-color: slateblue;
                grid-row: 1/2;
                grid-column: 1/5;
            }
            .item1 {
                background-color: slategray;
                grid-row: 2/3;
                grid-column: 1;
            }
            .item2 {
                background-color: springgreen;
                grid-row: 2/3;
                grid-column: 2/3;
            }
            .item3 {
                background-color: teal;
                grid-row: 2/3;
                grid-column: 3/4;
           }
            .item4 {
                background-color: wheat;
                grid-row: 2/4;
                grid-column: 4/5;
            }
            .item5 {
                background-color: #BEE7E9;
                grid-row: 3/4;
                grid-column: 1/3;
            }
            .item6{
                background-color: #E6CEAC;
                grid-row: 3/4;
                grid-column: 3/4;
            }
            .item7{
                background-color: #ECAD9E;
                grid-row: 4/5;
                grid-column: 1/5;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="item0 item">item0</div>
            <div class="item1 item">item1</div>
            <div class="item2 item">item2</div>
            <div class="item3 item">item3</div>
            <div class="item4 item">item4</div>
            <div class="item5 item">item5</div>
            <div class="item6 item">item6</div>
            <div class="item7 item">item7</div>
        </div>
    </body>
</html>

上面的代码基本基本涵盖了我们常用的grid的属性

  • display: grid: 设置container容器为网格布局
  • grid-template-columnsgrid-template-rows:分别设置网格的列宽与行高,取值有多中形式例如:
  /* 声明了三列,宽度分别为 200px 100px 200px */
  grid-template-columns: 200px 100px 200px;
  /*  声明了两行,行高分别为 50px 50px  */
  grid-template-rows: 50px 50px;

或者是这样像我们的例子中使用repeat()函数进行赋值,该函数接受两个参数,第一个参数是重复的次数,第二个参数是所要重复的值。我们的例子中grid-template-columns: repeat(4,1fr); 出现了一个新的单位frfr代表网格容器中可用空间的一等份,类似于flex的flex-grow。如果这样取值grid-template-columns: 200px 1fr 2fr 表示第一个列宽设置为 200px,后面剩余的宽度分为两部分,宽度分别为剩余宽度的 1/3 和 2/3。

  • grid-auto-rowsgrid-auto-columns: 表示超出我们没有定义网络的宽度跟高度取值。例如上面的例子grid-template-columns: repeat(4,1fr); 我们只是显示的指定了列的个数,以及宽度,并没有指定行高,那么grid会取grid-auto-rows: minmax(100px,auto);的值来作为行高。minmax()函数产生一个长度范围,表示长度就在这个范围之中都可以应用到网格项目中,它接受两个参数,分别为最小值和最大值。
  • grid-gap: 表示网格间的间隙大小,也可以单独这行跟列的间隙:grid-row-gap 属性、grid-column-gap.
  • grid-rowgrid-column: 表示单个项目的四个边框的起始网格线跟结束网格线,从而确定单个网格的大小跟位置。我们将项目化分为四行四列的网格,那么横向网格线为从1-5,纵向网格线也为从1-5,这里item0的取值grid-row: 1/2;grid-column: 1/5;表示:行高从第一根网格线到第二跟网格线,列宽度:从第一根网格线到第五根网格线。

看下它的浏览器支持情况,总体兼容性还不错,但在IE10以下不支持.


pic10

更多的关于grid的属性可以查看这里:grid布局

三、布局的应用

通过上面的学习我们了解了Web开发常用的几种布局方式,下面我们将这些布局方式来应用到我们的实际开发中,我们就以最常见的几种布局方式来说明

1.双栏目布局实现

双栏布局在我么的Web开发中间经常用到,例如下面的CSDN的内容详情页。主要特点:一侧栏固定,另一侧栏宽度自适应。

pic21

我们使用float+margin的方式去实现,左侧栏浮动,右侧设置左外边距。

<!DOCTYPE html>
<html>
    <head>
        <title>双栏目布局</title>
        <meta charset="UTF-8">
        <style>
            * {
                margin:  0;
                padding: 0;
                box-sizing: border-box;
            }
            .container {
                background-color: white;
            }
            .left {
                float: left;
                width: 200px;
                height: 200px;
                background-color: rosybrown;
            }
            .right {
                margin-left: 210px;
                height: 100px;
                background-color: saddlebrown;
            }
            .last {
                height: 30px;
                background-color: red;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="left">左侧</div>
            <div class="right">右侧</div>
            <div style="clear:both"></div>
        </div>
        <div class="last">后面内容</div>
    </body>
</html>

实现效果

pic34

注意要给container添加为内容空的子元素<div style="clear:both"></div>,清除浮动带来的影响。

2.三栏目布局实现

三栏布局也是我们经常遇到的布局方式,它的特点主要是:两边定宽,中间自适应。有多种方式实现三栏布局,我们这里介绍其中四种方式


buj
(1)position + margin 实现

实现思路:

  • 设置父元素为相对定位,左右两栏采用绝对定位,分别固定于页面的左右两侧
  • 中间的主体栏用左右margin值撑开距离
.box {
     /*父元素设置相对定位,否则左右栏会相对Body元素进行位置的偏移*/
     position: relative;
     background-color:wheat;
}
.middle {
     height: 100px;
     margin-left: 110px;
     margin-right: 110px;
     background-color:royalblue;
}
.left {
     position: absolute;
     top: 0px;
     left: 0px;
     width: 100px;
     height: 100px;
     background-color:salmon;
}
.right {
    position: absolute;
    top: 0;
    right: 0;
    width: 100px;
    height: 100px;
    background-color:sandybrown;
}
<div class="box">
   <div class="left">左边</div>
   <div class="middle">中间</div>
   <div class="right">右边</div>
</div>
<div>尾部内容</div>

看下实现效果


yup
(2)圣杯布局

实现思路:

  • 中间元素占据第一位置优先渲染,设置该元素 width 为 100%
  • 左中右三个元素分别左浮动,并且进行清除浮动带来的影响
  • 左元素设置左边距为-100%以使得左元素上升一行并且处于最左位置,右元素设置左边距为自身宽度的负值使得右元素上升一行处于最右位置。
  • 设置父元素的左右 padding 为左右两个元素留出空间,以展示中间元素内容。
  • 设置左右元素为相对定位,左元素的 left 和右元素的 right 为内边距的宽度的负值。
    代码实现
<body>
    <div class="box">
       <div class="middle">中间</div>
       <div class="left">左边</div>
       <div class="right">右边</div>
       <div style="clear: both;"></div>
   </div>
<div class="last">后面</div>
</body>

CSS

body {
     /* 设置body的最小宽度 */
     min-width: 800px;
}
.box {
     padding: 0 210px;
     width: 100%;
     background-color:red;
}
.middle {
     float: left;
     width: 100%;
     height: 200px;
     background-color:royalblue;
}
 .left {
     float: left;
     width: 200px;
     height: 200px;
     background-color:salmon;
     /*左边距为-100%以使得左元素上升一行并且处于最左位置*/
     margin-left: -100%;
     /*相对定位*/
     position: relative;
     left: -210px;
}
.right {
     float: left;
     width: 200px;
     height: 200px;
     background-color:sandybrown;
     /*元素设置左边距为自身宽度的负值使得右元素上升一行处于最右位置*/
     margin-left: -200px;
     /*相对定位*/
     position: relative;
     right: -210px; 
}
.last {
     background-color:thistle;
     height: 40px;
}

效果


pic2
(3)双飞翼布局

实现思路:

  • 中间采用嵌套子元素方法,宽度自适应
  • 左中右三个元素分别左浮动,并且进行清除浮动带来的影响
  • 左元素设置左边距为-100%以使得左元素上升一行并且处于最左位置,右元素设置左边距为自身宽度的负值使得右元素上升一行处于最右位置。
  • 设置中间元素的子元素左右边距为左右元素留空位,以展示中间元素内容。
    代码实现
<body>
    <div class="container">
        <div class="middle">中间</div>
    </div>
    <div class="left">左侧</div>
    <div class="right">右侧</div>
    <div style="clear: both;"></div>
    <div class="last">尾部</div>
</body>

CSS

body {
   min-width: 800px;
}
.container{
    float: left;
    /* 整个容器大小 */
    width: 100%;
    height: 200px;
    background: #ddd;
}
.container .middle{
    height: 200px;
    /* 设置左右边距 */
    margin: 0 160px;
    background-color:slateblue;
}
.left{
    float: left;
    width: 150px;
    height: 200px;
    background-color: rosybrown;
    margin-left: -100%;
}
.right{
    float: left;
    width: 150px;
    height: 200px;
    background-color:saddlebrown;
    margin-left: -150px;
}
.last {
     background-color: tomato;
}

效果


pic

圣杯布局跟双飞翼布局的实现上,在前部分是一样的。同样都是左右栏定宽,中间栏自适应。采用浮动和负边距使左右栏与中间栏并排。不同之处大部分在于中间元素的的展示方式上。圣杯布局采用父元素设置内边距的方法,左右元素设置相对定位辅助。而双飞翼布局在中间采用嵌套子元素方法,通过设置子元素外边距来展示。

(4)flex布局实现

对比前面两中实现直接实用flex布局能够比较容易的实现三栏布局

<div class="container">
     <div class="left">左侧</div>
     <div class="middle">中间</div>
     <div class="right">右侧</div>
</div>

CCS

.container {
     display: flex;
     flex-direction: row;
     justify-content: center;
     align-items: flex-start;
     background-color: wheat;
     /* height: 100vh; */
}
.left {
     width: 150px;
     height: 200px;
     background-color: rosybrown;
}
.right {
     width: 150px;
     height: 200px;
     background-color: saddlebrown;
}
.middle {
     /* 宽度沾满剩下的整个区域 */
     flex: 1;
     height: 200px;
     background-color: seagreen;
}
pic

3.响应式布局

响应式布局是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。这个概念是为解决移动互联网浏览而诞生的。

saumang

例如三星网站的设计,当我们改变浏览器大小时,页面的布局会发生相应的改变,那么这些变化是如何实现的呢?我们介绍三种实现方式

(1)媒体查询CSS3-Media Query

使用 @media查询,可以针对不同的媒体类型定义不同的样式。当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。
语法

@media mediatype and|not|only (media feature) {
    CSS-Code;
}
  • mediatype: 媒体类型, 例如:screen:计算机屏幕(默认值),tv:电视类型设备 等
  • and|not|only :逻辑操作符
    and:用来把多个媒体属性组合起来,合并到同一条媒体查询中
    not:用来对一条媒体查询的结果进行取反
    only:表示仅在媒体查询匹配成功时应用指定样式
  • media feature: 多数媒体属性,带有“min-”和“max-”前缀,用于表达“大于等于”和“小于等于”。例如width | min-width | max-width,height | min-height | max-height,aspect-ratio | min-aspect-ratio | max-aspect-ratio

适配进行响应式开发时往往需要针对不同的屏幕添加多个断点,看个例子


toppic
<div class="container">
   <div class="item item0">item0</div>
   <div class="item item1">item1</div>
   <div class="item item2">item2</div>
   <div class="item item3">item3</div>
   <div class="item item4">item4</div>
   <div class="item item5">item5</div>
   <div class="item item6">item6</div>
   <div class="item item7">item7</div>
</div>

CSS

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<style>
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
    }
    body {
        background-color: white;
    }
    /* 当屏幕尺寸大于等于1025 样式 */
    @media only screen and (min-width: 1025px){
        body {
            background-color: wheat;
        }
        .item {
            float: left;
            border: 1px solid skyblue;
            width: 300px;
            height: 50px;
            line-height: 50px;
            text-align: center;
            margin: 10px 30px;
        }
    }
    /** iPad 屏幕尺寸大于等于768 小于等于1024 竖屏**/
    @media only screen and (min-width: 768px) and (max-width: 1024px) {
        body {
            background-color: rosybrown;
        }
        .item {
            float: left;
            border: 1px solid skyblue;
            width: 200px;
            height: 50px;
            line-height: 50px;
            text-align: center;
            margin: 5px 20px;
        }
    }
    /** iPhone 屏幕尺寸小于等于767 竖屏样式**/
    @media only screen and (max-width: 767px){
        body {
            background-color:royalblue;
        }
        .item {
            float: left;
            border: 1px solid skyblue;
            width: 100px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            margin: 5px 10px;
        }
    }    
</style>
  • <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">这句代码的作用是禁止用户进行手动的放大缩小页面
  • 设置了三个断点,根据不同的屏幕宽度展示不同的样式。
  • 还需要注意@media 不支持IE9及以下的浏览器,如果要支持需要添加额外的代码
  <!--[if lt IE 9]>
    <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
    <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
(2)grid实现响应式布局

第二种方式主要是利用grid的特性来实现响应布局。假如有这样的需求:我们不希望Item过小,需要有最小宽度限制,并且当视口宽度增加时我们不希望看到右侧有空白区域的出现。实现下面效果

pic

<!doctype html>
<html>
  <head>
     <title>响应式布局2</title>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
       <style>
           * {
               padding: 0;
               margin: 0;
               box-sizing: border-box;
           }
           body {
               background-color: white;
           }
           .container {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
                grid-gap: 10px 20px;
                grid-auto-rows: 50px;
           }
           .item {
                border: 1px solid skyblue;
                text-align: center;
                margin: 10px 30px;
                height: 50px;
                line-height: 50px;
          } 
       </style>
  </head>
    <body>
        <div class="container">
            <div class="item item0">item0</div>
            <div class="item item1">item1</div>
            <div class="item item2">item2</div>
            <div class="item item3">item3</div>
            <div class="item item4">item4</div>
            <div class="item item5">item5</div>
            <div class="item item6">item6</div>
            <div class="item item7">item7</div>
        </div>
    </body>
</html>
  • 关于grid的属性我们再上面已经介绍过了这里不再赘述。唯一没有介绍的是auto-fit关键字,repeat()函数的作用是重复创建多个Item,第一个参数数个数,第二个是大小,这里取值auto-fit的意思是数量是自适应的,只要容纳得下,就会往上排列。
(3)Columns栅格系统

Columns栅格系统往往需要依赖某个UI库,如Bootstrip或者是Element UI等。

  • Bootstrap来自Twitter,是一个用于快速开发 Web 应用程序和网站的前端框架。它提供了一套响应式、移动设备优先的流式网格系统,随着屏幕或视口(viewport)尺寸的改变,系统会自动将视口分为最多12列。它根据当前视口的大小添加多个媒体查询断点,可以让开发者方便的根据视口大小调整每个网格所占整体视口的宽度。
  • Bootstrap(5.0)有六种默认响应尺寸:xssmmdlgxlxxl,对应关系如下
    duandian

它的基本的网格结构

<div class="container">
   <div class="row">
      <div class="col-*-*"></div>
      <div class="col-*-*"></div>      
   </div>
   <div class="row">...</div>
</div>

使用规则

  • 行必须放置在 .containerclass 内,以便获得适当的对齐(alignment)和内边距(padding)
  • 使用行来创建列的水平组,内容应该放置在列内,且唯有列可以是行的直接子元素
  • 预定义的网格类,比如 .row 和 .col-xs-4,可用于快速创建网格布局。
  • 网格系统是通过指定您想要横跨的十二个可用的列来创建的。例如,要创建三个相等的列,则使用三个 .col-xs-4。

例子:

<!doctype html>
<html lang="zh-CN">
  <head>
    <!-- 必须的 meta 标签 -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap</title>
    <!-- Bootstrap 的 CSS 文件 -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <style>
        .item {
            height: 50px;
        }
    </style>
  </head>
  <body>
      <div class="container">
          <div class="row g-1">
              <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 item bg-light border">item0</div>
              <div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 item bg-light border">item0</div>
              <div class="col-xs-12 col-sm-12 col-md-4 col-lg-3 item bg-light border">item0</div>
              <div class="col-xs-12 col-sm-12 col-md-12 col-lg-3 item bg-light border">item0</div>
          </div>
      </div>
  </body>
</html>

效果

pic

其他官方示例,Element UI的响应式布局与Bootstrap是相似的工作原理,这里不再赘述。
想了解更多关于BootstrapElement UI相关内容点击他们

四、总结

作为前端小白,学习完Html、CSS、JavaScript等一堆东西,等到真正开始写Web页面还是一头雾水,回忆刚学习写客户端时肯定要从基础的页面布局来入手,于是有了这篇文章。因此这篇文章主要面向的是前端初学者,还请大神勿喷。当然由于作者水平有限,难免出现纰漏,如有问题还请不吝赐教。文章涉及源码
参考资料:
Bootstrap
Element UI
CSS布局
Grid 布局完全指南

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

推荐阅读更多精彩内容