阅读 64

CSS页面布局的几种方法

在网页开发中,有多种方式来实现页面布局。想要清楚知道选择哪种布局方式来更好的实现布局,需要了解各种布局类型的特点和基本使用方式。

弹性布局

弹性布局是为一维布局设计的方法,可以将内容按行 或者 列 来布局。

弹性布局是使用display: flex来将元素变为弹性盒子,然后该元素里的直接子元素会变为弹性项(flex item)。如果不设置弹性盒子的高度,则其高度由其内部子元素决定。

    <div class="container">
      <p>文本1 </p>
      <p>文本2 </p>
      <p>文本3 </p>
    </div>
复制代码
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: flex;
}

p {
  margin: 1em;
  height: 50px;
  background-color: #ff00ff;
}

.container :first-child {
  height: 100px;
  background-color: #ff0000;
}
复制代码

为了实现更灵活的弹性布局效果,还需要组合其他弹性布局相关属性

作用flex 元素上的有

  • flex-direction属性
    一个弹性盒子,需要确定一个主轴,这个主轴是水平方向还是垂直方向是由flex-direction的属性值决定的。flex-direction值默认是row。可能的值有4个:
    row:主轴的方向是水平方向向右,子元素排列顺序从左到右
    row-reverse:主轴的方向是水平方向向左,子元素排列顺序从右到左
    column:主轴方向是垂直方向向下,子元素排列顺序从上到下
    colum-revers:主轴方向是垂直方向向下,子元素排列顺序从下到上
    .container {
      flex-direction: column;
    }
    复制代码

  • flex-wrap属性定义了子元素的换行方式。
    nowrap:默认值,不换行, 水平布局时只会展示一行。 wrap:换行,从上到下 wrap-reverse:换行, 从下到上

  • justify-content属性定义了子元素在主轴方向上的对齐方式。
  • align-items属性定义子元素在交叉轴方向上对齐方式。
  • align-content: 多行/列 情况下子元素在交叉轴方向上对齐方式。

作用于弹性项(子元素)上的有

  • align-self属性:定义在交叉轴上的拉伸方式。
  • flex-basis属性: 为弹性项设置未拉伸和压缩时的初始大小
  • flex-grow属性: 指定了 flex 元素的伸展规则。如果flex-grow的值是任意的正数,那么弹性项会被允许拉伸来占据更多的空间。
  • flex-shrink属性: 指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。注意:如果元素不是弹性盒对象的元素,则 flex-shrink 属性不起作用。当父元素的宽度小于所有子元素的宽度的和时(即子元素会超出父元素),子元素如何缩小自己的宽度的。 flex-shrink的默认值为1,当父元素的宽度小于所有子元素的宽度的和时,子元素的宽度会减小。值越大,减小的越厉害。如果值为0,表示不减小。

flex-grow、flex-shrink 和 flex-basis 可以简写成flex。第一个值代表flex-grow,第二个是flex-shrink,而第三个则是flex-basis。

  <div class="container">
    <div>1</div>
    <div>2</div>
    <div class="special">3</div>
    <div>4</div>
  </div>
复制代码
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

* {box-sizing: border-box;}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  height: 300px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
  display: flex;
  justify-content: space-between; /*主轴对齐方式*/
  align-items: flex-start; /*交叉轴顶部对齐*/
}

.special {
  align-self: stretch; /*交叉轴拉伸*/
}

.container > div {
  padding: 10px;
  background-color: rgba(111,41,97,.3);
  border: 2px solid rgba(111,41,97,.5);
}
复制代码

浮动布局

浮动可以将元素置于左侧或右侧,让内容环绕其展示。另外还可以用来对一系列元素设置宽度并浮动,从而实现创建 多栏/网格 布局,

  • 设置浮动
    CSS属性:float,默认值为none。 元素的float属性设置为left或right时,可以进行浮动。浮动元素只能在父元素内浮动。

    .item {
        float: left
    }
    复制代码
  • 清除浮动
    CSS属性:clear 一旦对一个元素应用了浮动,所有接下来的元素都会环绕它直到内容处于它下方才开始应用正常文档流。如果想要避免这种情况,可以为元素设置clear属性,设置left 或 right 或both。

    .clear {
        clear: both;
    }
    复制代码

因为浮动元素是在父元素内浮动。但是可能父元素容器比较小,导致容器外的接下来的元素会出现在浮动元素的下方

解决这个问题有几种方法:

  • 一是在容器最后添加一个空元素并设置clear属性。
  • 二是在容器内添加一个CSS伪元素,并将其clear属性设置为both。第二种方法是最常用的。
.container::after {
  content: "";
  display: table; /* 指定对象作为块元素级的表格,相当于html标签<table> */
  clear: both;
}
复制代码
  • 在容器内创建BFC(Block Formatting Context,块级格式化上下文),BFC元素可以包裹住它内部的所有元素,包括浮动元素,所有浮动元素是不会超出父元素的。创建BFC的常用方法是为元素设置overflow属性,值只要不是visible就可以。或者是设置display: flow-root。

定位布局

想要改变元素在正常文档流中的位置,可以使用CSS中的position属性。正常文档流布局中,元素的position属性为static。在块级维度上元素会一个个的排列下去,元素也会随着页面滚动。 CSS属性: position,不同position值对应的偏移量的参照点不一样。

  • position: relative
    相对定位,相对于其正常位置进行定位,也就是说偏移量的参考位是元素原本在正常文档流中的位置,然后可以使用top、left、bottom和right属性来相对其正常流位置进行移动(position: relative 元素在正常文档流中的位置会被保留),另外页面中其他元素不会受到该元素位置变化的影响。 top:基于正常位置顶部往下移动
    bottom:基于正常位置底部往上移动
    left:基于正常位置左侧往右移动
    right: 基于正常位置右侧往左移动

示例:item会基于自己原本的位置往右往下分别移动1em

.item {
  position: relative;
  top: 1em;
  left: 1em;
}
复制代码

  • position: absolute
    给元素设置position: absolute 会让元素脱离页面正常文档流, 相对于视口(最外层容器元素)的左上角进行定位。然后可以使用top、left、bottom和right属性来相对左上角位置进行移动。 (position: absolute 会让元素从正常文档流中被移除,不会保留它所占据的空间)
.container1 {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.container2 {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.container3 {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.item {
  width: 100px;
  height: 100px;
  margin: 0 20px 20px 0;
  background-color:#00ffff;
}

p {
  margin: 0 0 1em 0;
  background-color: #ff00ff;
}
复制代码
  <div>
      <div class="container1">
        <p>container1第一行文本 </p>
        <p>container1第二行文本 </p>
      </div>
      <div class="container2">
        <p>container2第一行文本 </p>
        <p>container2第二行文本 </p>
        <div class="container3">
          <p>container3第一行文本 </p>
          <p>container3第二行文本 </p>
          <div class="item"></div>
      </div>
      </div>
    </div>
复制代码

给item元素设置position: absolute后

.item {
  position: absolute;
  top: 2em;
  left: 0em;
 }
复制代码

如果想相对某个容器元素定位(兄弟元素不行),可以给相对容器元素设置除了static之外的值,通常是position: relative。

.container2 {
  position: relative;
}
复制代码

  • position: fixed
    想要让一个元素规定在页面的某个位置,可以给元素设置position: fixed。该属性值跟absolute一样,会让元素脱离页面正常文档流, 相对于视口(最外层容器元素)的左上角进行定位。然后可以使用top、left、bottom和right属性来相对左上角位置进行移动。同样的,position: fixed 会让元素从正常文档流中被移除,不会保留它所占据的空间。 不同的是,当页面内容超过一屏在滚动的时候,fixed元素会固定在相对视口的位置,不随着页面内容一起滚动,而absolute则会随着页面内容滚动。
.item {
  position: fixed;
}
复制代码
  • position: sticky position: sticky是一个结合了 position:relative 和 position:fixed 两种定位功能于一体的特殊定位,适用于一些特殊场景。可让元素可以先随着页面滚动,但当其滚动到相对于视口的某个特定位置时才会固定在屏幕上。 position:sticky的生效是有一定的限制的,总结如下:
  1. 须指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。
  2. 设定为position:sticky元素的任意父节点的 overflow 属性必须是 visible,否则position:sticky不会生效。
  3. 达到设定的阀值。也就是设定了position:sticky的元素表现为relative还是fixed是根据元素是否达到设定了的阈值决定的。

网格布局

网格布局是一种用来进行二维布局的技术,在行和列两个维度上排列内容。
网格布局需要给元素设置display: grid,并且使用grid-template-columns和grid-template-rows属性来控制网格中的行与列。

  <div class="container">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
  </div>
复制代码
body {
  padding: 20px;
}

.container {
  display: grid;
  grid-template-columns: 50px 100px 150px; /*对应列的宽度*/
  grid-template-rows: 50px 100px;/* 对应行的宽度*/
}
复制代码

参考资料

一篇全面的CSS布局学习指南 [译]

position:sticky

表格布局display: table的妙用