【玩转CSS】详解定位

485 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

🔥 本文由 程序喵正在路上原创,在稀土掘金首发!
💖 系列专栏:HTML+CSS
🌠 首发时间:2022年9月6日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
🌟 一以贯之的努力 不得懈怠的人生

学习目标

能够说出为什么要用定位
能够说出定位的 4 种分类
能够说出 4 种定位各自的特点
能够说出为什么常用子绝父相布局
能够写出淘宝轮播图布局

定位

1. 为什么需要定位

浮动可以让多个块级盒子一行没有缝隙排列显示,经常用于横向排列盒子

而定位则是可以让盒子自由地在某个盒子内移动位置或者固定屏幕中某个位置,并且可以压住其他盒子

2. 定位组成

定位:将盒子定在某一个位置,所以定位也是在摆放盒子,按照定位的方式移动盒子

定位 = 定位模式 + 边偏移

定位模式用于指定一个元素在文档中的定位方式,边偏移则决定了该元素的最终位置

定位模式

定位模式决定元素的定位方式,它通过 CSSposition 属性来设置,其值可以分为四个:

语义
static静态定位
relative相对定位
absolute绝对定位
fixed固定定位

边偏移

边偏移就是定位的盒子移动到最终位置,有 topbottomleftright4 个属性

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

3. 静态定位

静态定位是元素的默认定位方式,也就是无定位的意思

语法:

选择器 { position: static; }

  • 静态定位按照标准流特性来摆放位置,它没有边偏移
  • 静态定位在布局时很少用到

4. 相对定位

相对定位是元素在移动位置的时候,是相对于它原来的位置来说的

语法:

选择器 { position: relative; }

相对定位的特点:

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

我们通过一个简单的例子来看一下

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>相对定位</title>
    <style>
        .box1 {
            position: relative;
            top: 100px;
            left: 100px;
            width: 200px;
            height: 200px;
            background-color: skyblue;
        }

        .box2 {
            width: 200px;
            height: 200px;
            background-color: pink;
        }
    </style>
</head>

<body>
    <div class="box1">

    </div>
    <div class="box2">

    </div>
</body>

</html>

运行结果

image.png 因此,相对定位是没有脱标的,其最典型的应用是来限制绝对定位

5. 绝对定位

绝对定位是元素在移动位置的时候,是相对于它祖先元素来说的

语法:

选择器 { position: absolute; }

绝对定位的特点:

  1. 如果没有祖先元素或者祖先元素没有定位,则以浏览器为准定位(Document 文档)

    代码演示

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>绝对定位</title>
        <style>
            .father {
                width: 500px;
                height: 500px;
                background-color: pink;
            }
    
            .son {
                position: absolute;
                top: 100px;
                right: 100px;
                width: 200px;
                height: 200px;
                background-color: #0CF;
            }
        </style>
    </head>
    
    <body>
        <div class="father">
            <div class="son"></div>
        </div>
    </body>
    
    </html>
    

    运行结果

    image.png

  2. 如果祖先元素有定位(相对、绝对、固定定位),则以最近一级有定位的祖先元素为参考点移动位置

    代码演示

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>绝对定位-父级有定位</title>
        <style>
            .grandfather {
                position: relative;
                width: 800px;
                height: 800px;
                background-color: purple;
                padding: 50px;
            }
    
            .father {
                width: 500px;
                height: 500px;
                background-color: pink;
            }
    
            .son {
                position: absolute;
                top: 100px;
                right: 100px;
                width: 200px;
                height: 200px;
                background-color: #0CF;
            }
        </style>
    </head>
    
    <body>
        <div class="grandfather">
            grandfather
            <div class="father">
                father
                <div class="son">son</div>
            </div>
        </div>
    
    </body>
    
    </html>
    

    运行结果

    image.png

  3. 绝对定位不再占有原来的位置

6. 子绝父相的由来

子绝父相 —— 子级是绝对定位的话,父级要用相对定位

① 子级绝对定位,不会占有位置,可以放大盒子里面的任何一个地方,不会影响其他的盒子
② 父盒子需要加定位限制子盒子在父盒子内显示
③ 父盒子布局时,需要占有位置,因此父亲只能是相对定位

这就是子绝父相的由来,所以相对定位经常用来作为绝对定位的父级

总结:因为父亲需要占有位置,因此是相对定位,子盒子不需要占有位置,则是绝对定位

当然,子绝父相不是永远不变的,如果父元素不需要占有位置,子相父绝也会遇到

子绝父相案例实战

实现下面的效果,注意右上角

image.png 我们在之前代码的基础上添加一些代码即可

index.html

image.png

style.css

image.png

7. 固定定位

固定定位是元素固定于浏览器可视区的位置,主要使用场景:在浏览器页面滚动时,让元素的位置保持不变

语法:

选择器 { position: fixed; }

固定定位的特点:

  1. 以浏览器的可视窗口为参照点移动元素
    • 跟父元素没有任何关系
    • 不随滚动条滚动
  2. 固定定位不存在占有原先的位置 固定定位也是脱标的,其实固定定位也可以看做是一种特殊的绝对定位

代码演示

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>固定定位</title>
    <style>
        body {
            height: 2000px;
        }

        .dj {
            position: fixed;
            top: 100px;
            left: 40px;
        }
    </style>
</head>

<body>
    <div class="dj">
        <img src="../images/r_dj.png" alt="">
    </div>
</body>

</html>

运行结果

2022年8月29日16时4分58秒.gif 可以看到,当我们的滚轮滚动时,固定定位的元素是不会动的

固定定位小技巧:固定在版心右侧位置

步骤:

  1. 让固定定位的盒子 left: 50%,走到浏览器可视区(也可以看做版心)的一半位置
  2. 让固定定位的盒子 margin-left: 版心宽度的一半距离,多走版心宽度的一半位置

这样就可以让固定定位的盒子贴着版心右侧对齐了

代码演示

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>固定定位小技巧</title>
    <style>
        .w {
            width: 800px;
            height: 1400px;
            background-color: pink;
            margin: 0 auto;
        }

        .fixed {
            position: fixed;
            left: 50%;
            margin-left: 405px;
            width: 50px;
            height: 150px;
            background-color: #0CF;
        }
    </style>
</head>

<body>
    <div class="fixed"></div>
    <div class="w">版心盒子 800像素</div>
</body>

</html>

运行结果

2022年8月29日16时6分32秒.gif

8. 粘性定位

粘性定位可以被认为是相对定位和固定定位的混合

语法:

选择器 { position: sticky; top: 10px; }

粘性定位的特点:

  1. 以浏览器的可视窗口为参照点移动元素(固定定位特点)
  2. 粘性定位占有原先的位置(相对定位特点)
  3. 必须添加 topleftrightbottom 其中一个才有效
  4. 跟页面滚动搭配使用,兼容性较差

代码演示

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>粘性定位</title>
    <style>
        body {
            height: 3000px;
        }

        .nav {
            position: sticky;
            top: 0;
            width: 800px;
            height: 50px;
            background-color: #0CF;
            margin: 100px auto;
        }
    </style>
</head>

<body>
    <div class="nav">导航栏</div>
</body>

</html>

运行结果

2022年8月29日16时7分38秒.gif

9. 总结

定位模式是否脱标移动位置是否常用
static 静态定位不能使用边偏移很少
relative 相对定位否(占有位置)相对于自身位置移动常用
absolute 绝对定位是(不占有位置)带有定位的父级常用
fixed 固定定位是(不占有位置)浏览器可视区常用
sticky 粘性定位否(占有位置)浏览器可视区当前阶段少

10. 定位叠放次序 z-index

在使用定位布局时,可能会出现盒子重叠的情况。此时,可以用 z-index 来控制盒子的前后次序

语法:

选择器 { z-index: 1; }

  • 数值可以是正整数、负整数或 0,默认是 auto,数值越大,盒子越靠上
  • 如果属性值相同,则按照书写顺序,后来者居上
  • 数字后面不能加单位
  • 只有定位的盒子才有 z-index 属性

代码演示

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>定位的叠放次序</title>
    <style>
        .box {
            position: absolute;
            top: 0;
            left: 0;
            width: 200px;
            height: 200px;
        }

        .one {
            background-color: red;
            z-index: 1;
        }

        .two {
            background-color: green;
            left: 50px;
            top: 50px;
        }

        .three {
            background-color: blue;
            left: 100px;
            top: 100px;
        }
    </style>
</head>

<body>
    <div class="box one">one</div>
    <div class="box two">two</div>
    <div class="box three">three</div>
</body>

</html>

运行结果

image.png

11. 定位的拓展

怎么让绝对定位的盒子居中呢?

加了绝对定位的盒子不能通过 margin: 0 auto; 水平居中,但是可以通过一些技巧实现

代码演示

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>绝对定位水平垂直居中</title>
    <style>
        .box {
            position: absolute;
            left: 50%;
            margin-left: -100px;
            top: 50%;
            margin-top: -100px;
            width: 200px;
            height: 200px;
            background-color: #0CF;
        }
    </style>

</head>

<body>
    <div class="box"></div>
</body>

</html>

运行结果

image.png 定位特殊特性

绝对定位和固定定位也和浮动类似

  1. 行内元素添加绝对或者固定定位,可以直接设置高度和宽度
  2. 块级元素添加绝对或者固定定位,如果不给宽度或者高度,默认大小是内容的大小

脱标的盒子不会触发外边距塌陷

浮动元素、绝对定位(固定定位)元素都不会触发外边距合并的问题

绝对定位(固定定位)会完全压住盒子

浮动元素不同,只会压住它下面标准流的盒子,但是不会压住下面标准流盒子里面的文字(图片)

但是绝对定位(固定定位)会压住下面标准流所有的内容

PS:给图片添加浮动,可以产生文字围绕着图片的效果

综合案例

案例:淘宝焦点图布局

image.png

  • 大盒子类名为:tb-promo
  • 里面先放一张图片
  • 左右两个按钮用链接就好了,左箭头 prev,右箭头 next
  • 底部小圆点 ul,类名为 promo-nav

代码实现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>淘宝网</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        li {
            list-style: none;
        }

        .tb-promo {
            position: relative;
            width: 564px;
            height: 315px;
            margin: 100px auto;
        }

        .tb-promo img {
            width: 564px;
            height: 315px;
        }

        .prev,
        .next {
            position: absolute;
            top: 50%;
            margin-top: -15px;
            width: 20px;
            height: 30px;
            background: rgba(0, 0, 0, .3);
            text-align: center;
            line-height: 30px;
            color: #fff;
            text-decoration: none;
        }

        .prev {
            left: 0;
            border-top-right-radius: 15px;
            border-bottom-right-radius: 15px;
        }

        .next {
            right: 0;
            border-top-left-radius: 15px;
            border-bottom-left-radius: 15px;
        }

        .promo-nav {
            position: absolute;
            bottom: 15px;
            left: 50%;
            margin-left: -35px;
            width: 70px;
            height: 13px;
            background: rgba(255, 255, 255, .3);
            border-radius: 7px;
        }

        .promo-nav li {
            float: left;
            width: 8px;
            height: 8px;
            background-color: #fff;
            border-radius: 50%;
            margin: 3px;
        }

        .promo-nav .selected {
            background-color: #ff5000;
        }
    </style>
</head>

<body>
    <div class="tb-promo">
        <img src="https://img.alicdn.com/imgextra/i2/6000000006499/O1CN01tvAkze1xsanRKfMEu_!!6000000006499-0-octopus.jpg"
            alt="">
        <!-- 左箭头 -->
        <a href="#" class="prev"> &lt; </a>
        <!-- 右箭头 -->
        <a href="#" class="next"> &gt; </a>
        <!-- 小圆点 -->
        <ul class="promo-nav">
            <li class="selected"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
</body>

</html>

运行结果

image.png