CSS-定位(position)

266 阅读9分钟

1. 为什么使用定位?

我们先来看一个效果,同时思考一下用标准流或浮动能否实现类似的效果?

  1. 小黄色块在图片上移动,吸引用户的眼球

  1. 当我们滚动窗口的时候,盒子是固定屏幕某个位置的

要实现以上效果,标准流或浮动都无法快速实现,所以,我们脑海应该有三种布局机制的上下顺序:

标准流在最底层 (海底) ------- 浮动的盒子在中间层 (海面) ------- 定位的盒子在最上层(天空)

2. 定位详解

定位也是用来布局的,它有两部分组成:定位模式 + 边偏移

边偏移

简单说,我们定位的盒子,是通过边偏移来移动位置的。

在 CSS 中,通过 topbottomleftright 属性定义元素的边偏移:(方位名词)

边偏移属性示例描述
toptop: 80px顶端偏移量,定义元素相对于其父元素上边线的距离。往下是正,往上是负。
bottombottom: 80px底部偏移量,定义元素相对于其父元素下边线的距离。往上是正,往下是负。
leftleft: 80px左侧偏移量,定义元素相对于其父元素左边线的距离。往右是正,往左是负。
rightright: 80px右侧偏移量,定义元素相对于其父元素右边线的距离。往左是正,往右是负。

定位的盒子有了边偏移才有价值, 一般情况下,凡是有定位地方必定有边偏移。

定位模式(position)

在 CSS 中,通过 position 属性定义元素的定位模式,语法如下:

选择器 { position: 属性值; }

静态定位是css中的默认定位方式,也就是没有定位。在此定位方式中设置:top,bottom,left,right,z-index 这些属性都是无效的。

定位模式是有不同分类的,在不同情况下,我们用到不同的定位模式。

语义
relative相对定位
absolute绝对定位
fixed固定定位

① 相对定位(relative)

相对定位是元素相对于它原来在标准流中的位置来说的(自恋型)。

  1. 相对于自己原来在标准流中位置来移动的。
  2. 原来在标准流的区域继续占有,后面的盒子仍然以标准流的方式对待它。

② 绝对定位(absolute)

绝对定位是元素以带有定位的父级元素来移动位置 (拼爹型)。

  1. 不保留原来的位置,完全脱标,完全不占位置。
  2. 父元素没有定位,则以浏览器可视窗口为准定位。

  1. 父元素要有定位,则元素依据最近的已经定位的父元素进行定位。

子绝父相

刚才咱们说过,绝对定位,要和带有定位的父级搭配使用,那么父级要用什么定位呢? 定位口诀:子绝父相,子级是绝对定位,父级要用相对定位。

疑问:为什么在布局时,子级元素使用绝对定位时,父级元素就要用相对定位呢? 观察下图,思考一下在布局时,左右两个方向的箭头图片以及父级盒子的定位方式。

分析:

  1. 方向箭头叠加在其他图片上方,应该使用绝对定位,因为绝对定位完全脱标,完全不占位置。
  2. 父级盒子应该使用相对定位,因为相对定位不脱标,后续盒子仍然以标准流的方式对待它。如果父级盒子也使用绝对定位,会完全脱标,那么下方的广告盒子会上移,这显然不是我们想要的。

结论:父级要占有位置,子级要任意摆放,这就是子绝父相的由来。

③ 固定定位(fixed)

上面我们说了,绝对定位是元素以带有定位的父级元素来移动位置,如果父元素没有定位,则以浏览器可视窗口为准定位。固定定位是绝对定位的一种特殊形式:固定定位只认浏览器可视窗口 —— 浏览器可视窗口 + 边偏移属性 来设置元素的位置。

  1. 完全脱标,完全不占位置。
  2. 跟父元素没有任何关系,只认浏览器,所以不随滚动条滚动。

补充:定位的盒子层级是最高层的,我们只要保证当前的这个盒子是定位的就会压住标准流和浮动盒子。

3. 定位案例

① 哈根达斯

父元素使用相对定位,左上和右下的两个子元素使用绝对定位。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div {
          width: 310px;
          height: 190px;
          border: 1px solid #ccc;
          margin: 50px auto;  
          padding: 10px;
          position: relative;  /* 根据子绝父相最合适 */
        }
        .topIcon {
          position: absolute; /* 绝对定位 不占有位置 */
          top: 0;
          left: 0;  /* 孩子加了绝对定位,如果父级没有定位,以浏览器为准 */
        }
        .bottomIcon {
          position: absolute;
          right: 0;
          bottom: 0;
        }
    </style>
</head>
<body>
    <div>
        <img src="media/top_tu.gif" alt="" class="topIcon">
        <img src="media/adv.jpg" alt="">
        <img src="media/br.gif" height="54" width="60" alt="" class="bottomIcon">
    </div>
</body>
</html>

② 仿新浪头部和广告

新浪案例分析:

  1. 顶部图片固定在浏览器可视窗口顶部,不会随窗口一起滚动;
  2. 左右两侧的广告图片固定在浏览器可视窗口的左右两侧,不会随窗口一起滚动;
  3. 注意:底部的内容图片初始显示在顶部图片的下方,如何解决?(使用margin)

步骤 1:顶部图片和底部内容

  1. 顶部图片固定在浏览器可视窗口顶部,所以我们使用固定定位,在使用固定定位时,如果盒子中没有内容,需要指定宽度,否则没有东西撑开盒子啊。
  2. 底部内容在顶部图片下方,由于顶部图片是固定定位,不占位置,所以我们设置底部内容图片的顶部 margin,可以让底部盒子初始显示在顶部图片的下方。
.top {
    /* 注意:使用固定定位时,如果盒子中没有内容,需要指定宽度,否则没有东西撑开盒子啊 */
    width: 100%;
    height: 44px;
    background: url(media/top.png) no-repeat top center;
    position: fixed;
    left: 0px;
    top: 0px;
}

.box {
    width: 1002px;
    /* 顶部的 44px 的 margin 可以让 box 显示在顶部图片下方 */
    margin: 44px auto;
}

步骤 2:左右两侧广告

左右两侧的广告图片固定在浏览器可视窗口的左右两侧,所以我们使用固定定位。

.ad-left,
.ad-right {
    position: fixed;
    top: 100px;
}

.ad-left {
    left: 0px;
}

.ad-right {
    right: 0px;
}

4. width、继承、和三种布局机制的联系

  1. 标准流中,块级子元素会继承父元素width属性
  2. 行内(实际上是不能设置宽度)、行内块元素不会继承父元素width属性
  3. 浮动元素脱离标准流,子元素不继承父元素的width属性
  4. 同理,绝对定位、固定定位元素脱离标准流,子元素不继承父元素的width属性,所以绝对定位、固定定位要设置宽度

5. 定位扩展

① 绝对定位的盒子居中

绝对定位、固定定位的盒子不能通过设置 margin: auto 设置水平居中,因为这是标准流的做法。

在使用绝对定位时要想实现水平居中,可以按照下图的方法:

  1. left: 50%;:让盒子的左侧移动到父级元素的水平中心位置。
  2. margin-left: -100px;:让盒子向左移动自身宽度的一半。

② 堆叠顺序(z-index)

上面我们说了,定位的盒子层级是最高的,定位的盒子会压住标准流和浮动盒子。但是当有多个盒子都是定位的时候,可能会出现盒子重叠的情况,加了定位的盒子,默认后来居上,后面的盒子会压住前面的盒子。

使用 z-index 层叠属性可以调整盒子的堆叠顺序,如下图所示:

z-index 的特性如下:

  1. 属性值:正整数、负整数或 0,默认值是 0,数值越大,盒子越靠上。
  2. 如果属性值相同,则按照书写顺序,后来居上。
  3. 数字后面不能加单位。
  4. z-index 只能应用于定位的元素,其他标准流、浮动无效。

③ 定位改变display属性

前面我们讲过,display 是显示模式,可以改变显示模式有以下方式:

  1. 可以用 inline-block 转换为行内块。
  2. 可以用浮动 float 默认转换为行内块(类似,并不完全一样,因为浮动是脱标的)。
  3. 绝对定位和固定定位也和浮动类似,有默认转换的特性,转换为行内块。

所以:

  1. 一个行内元素,如果加了浮动、绝对定位、固定定位,不用转换,就可以给这个盒子直接设置宽度和高度等。
  2. 浮动元素、绝对定位、固定定位的元素都不会触发外边距合并的问题,也就是说,我们给盒子添加了浮动或者定位,就不会有垂直外边距合并的问题了,因为垂直外边距合并的问题只在标准流出现。

6. 综合演练 - 淘宝轮播图

父元素使用相对定位,左右箭头以及下面的指示条使用绝对定位,指示条里面的小li使用浮动。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <style>
          * {
            margin: 0;
            padding: 0;
          }
          ul {
            list-style: none; 
          }
          .slider {
            width: 520px;
            height: 280px;
            background-color: pink;
            margin: 50px auto;
            position: relative;  /* 子绝父相 */
          }
          .arrow-l,
          .arrow-r {
            position: absolute;  /* 绝对定位 */
            width: 24px;
            height: 36px;
            /*display: block; 使用定位之后a标签不用转换,可以直接设置宽高 */
            top: 50%;  /* 这个%是按照父级高度的来进行计算 */
            margin-top: -18px;  /* 上走是负值, 自己高度的一半 */
          }
          .arrow-l {
            left: 0;		
          }
          .arrow-r {
            right: 0;		
          }
          .circle {
            width: 65px;
            height: 13px;
            background: rgba(255, 255, 255, 0.3);/* 盒子背景半透明 */
            position: absolute;
            bottom: 15px;  /* 因为是底边对齐 */
            left: 50%;
            margin-left: -32px;
            border-radius: 6px;
          }
          .circle li {  /* 0011 */
            width: 9px;
            height: 9px;
            background-color: #B7B7B7;
            float: left; 
            margin: 2px;  
            border-radius: 50%;  /* 圆角的做法 */
          }
          .circle .current {  /* 注意权重问题,优先级  0020 */
            background-color: #f40;
          }
        </style>
    </head>
    <body>
      <div class="slider">
        <img src="media/taobao.jpg" alt="">
        <a href="#" class="arrow-l"><img src="media/left.png" ></a>
        <a href="#" class="arrow-r"><img src="media/right.png" ></a>
        <ul class="circle">
          <li class="current">
          <li></li>
          <li></li>
          <li></li>
          <li></li>
        </ul>
      </div>
    </body>
</html>

7. 定位小结

定位模式是否脱标占有位置移动位置基准模式转换(行内块)是否可以使用边偏移使用情况
相对定位relative不脱标,占有位置相对自身位置移动不能可以基本单独使用
绝对定位absolute完全脱标,不占有位置相对于定位父级移动位置可以要和定位父级元素搭配使用
固定定位fixed完全脱标,不占有位置相对于浏览器移动位置可以单独使用,不需要父级

8. 网页布局总结

一个完整的网页,有标准流、浮动、定位一起完成布局的,每个都有自己的专门用法。

  1. 标准流可以让盒子上下排列或者左右排列的。
  2. 浮动可以让多个块级元素一行显示或者左右对齐盒子,浮动的盒子就是按照顺序左右排列 。
  3. 定位最大的特点是有层叠的概念,就是可以让多个盒子前后叠压来显示,但是每个盒子需要有 z-index 数值。