定位position详解(一)

本文详细介绍了CSS中的浮动和定位机制,包括浮动元素的影响、清除浮动的必要性以及绝对定位的原理和应用。重点讲解了浮动元素如何影响布局,如何防止元素重叠,以及绝对定位元素的包含块和偏移属性。通过实例解析了定位元素的大小调整和内容剪裁,帮助理解CSS定位的复杂性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0.简介

首先记得p h1 div 等是称为块级元素,它们会生成”块框”。
而strong em span等是行内元素,它们生成“行内框”

CSS 有3种基本的定位机制

浮动 绝对定位 普通文档流
除非指定,否则所有框都在普通流中定位!

普通流:块级框一个一个垂直排列,由元素在HTML中的位置决定。

对于行内框
水平padding 内边距,margin外边距,border可以调整他们的水平间距。
但是垂直padding margin border不影响行内框的高度。
only 行高line-height影响

Position 属性
这里写图片描述

Position:

  • static
    元素框正常生成。 块级元素生成一个矩形框,作为文档流的一部分,行内元素会创建一个或多个行框,置于父元素中。
  • absolute;
    元素框从文档流完全删除,并相对于其包含块定位,包含块可能是文档中另一个元素或者是初始包含块。
    元素原先在正常文档流中所占的空间会关闭,就好像该元素原来不存在一样。 元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框.
  • fixed;
    元素框的表现类似于将position设置为absolute,但是其包含块是视窗本身。
  • relative;
    元素框偏移某个距离。 元素仍保持其未定位前的形状,它原本所占的空间仍保留。 这也是一种定位!

1. 浮动

声明浮动, 浮动到一侧,然后允许其他内容“围绕“ 该浮动元素。
这里写图片描述

CSS支持任何元素的浮动。

举例:

<img src="xx.gif" style="float:left;" alt="b4">

这使得图像“浮动” 到浏览器窗口的左边。文本则围绕着图像。这是你期望的。

浮动元素:
  • 首先,会以某种方式将浮动元素从文档的正常流中删除。(不属于正常流)
    它还是会影响布局,这跟定位元素不一样。 它会采用CSS特有的方式!!!

  • 一个元素浮动时,其他内容会“环绕”这个元素。 对于浮动图像来说,这种行为我们很熟悉,不过要知道元素浮动时也同样如此。

浮动一个段落

p{float:right; width:15em; margin:0 1em 1em; padding:0.25em; border:1px solid;}

这里写图片描述

有趣的地方
浮动元素的周围的 margin 外边距 不会合并!
换句话说,如果你浮动一个margin:20px 的元素,它的周围就至少有20px的空间。
其他元素与此图像相邻,这些元素也有margin,它们不会合并!

float:left;margin:25px;

这里写图片描述

浮动一个非替换元素,这必须为这个元素声明一个width。否则根据CSS 元素宽度趋向0
然后假设浏览器的最小width是1个字符,那么浮动段落可能只有1个字符宽。

这里写图片描述

不浮动
none
我们float的默认值是 none。
要让一个元素不浮动,不声明即可。 要得到正常的非浮动行为必须要有这个值;如果没有这个none值,所有元素都会以某种方式浮动。

什么时候可能用到?
当你在使用一个服务器端的样式表,这个样式表让图像浮动。不过在某个特定的页面你不希望浮动。 而只需要在文档的 嵌套样式表()中增加 float:none

浮动的详细内幕!
浮动元素的 包含块: 是其最近的块级祖先元素

例如:

<p>xxxx<img src="test.gif" style="float:right;">xxx</p>

浮动元素的包含块Containing block 就是包含该 浮动元素的段落元素:

浮动元素 的 块级框

此外,浮动元素也会生成一个块级框!不管这个元素本身是什么!
所有的元素不管行内or块, 设置成浮动就会成为 块级元素一样摆放和表示。

控制元素浮动的规则

  1. 浮动元素的左右外边界(margin) 不能超过其包含块的左右 内边界(padding)
    这里写图片描述

  2. 浮动元素的左(右)外边界 必须是源文档中之前出现的左浮动(或右浮动)元素的右(左)外边界,除非后出现的浮动元素的顶端 在先出现浮动元素的底端下面。
    这个规则的意义:
    防止浮动元素彼此“覆盖” 如图:
    这里写图片描述
    第2个浮动是靠在1左边,因为它是后放置的元素。
    而第3个元素是后出现的浮动元素,所以不能超过第二个浮动元素的底端~
    也就是说 所有浮动内容都是可见的! 不必担心一个浮动元素与另一个浮动元素重叠。

  3. 左浮动元素的右外边界 不会在 其右边右浮动元素的 左外边界的右边。
    同理,一个右浮动元素的左外边界不会在其左边任何左浮动元素的右外边界的左边。
    如图:
    这里写图片描述
    所以这会导致另一个图像向下浮动~~ 直到顶端在上一个图像的底端!

  4. 一个浮动元素的顶端不能比其 父元素的内顶端更高。
    如果一个浮动在两个合并外边距之间,放置这个浮动元素时就好像在两个元素之间有一个块级父元素。

    • 第一部分:防止浮动元素一直浮动到文档的顶端。
    • 第二部分:对某些情况下的对齐进行微调。

正确行为
这里写图片描述

5.浮动元素的顶端不能比之前所有浮动元素或块级元素的顶端更高
浮动元素的顶端也不可能比之前出现的浮动元素的顶端更高~
不能越过之前的浮动元素! 所以这里第三个元素只能是和第二个元素的顶端对齐.

这里写图片描述

6.如果源文档中一个浮动元素之前出现另一个元素,浮动元素的顶端不能比包含该元素所生成框的任何行框的顶端更高。

这里写图片描述
包含该元素所生成的任何行框 ,就是如果它是一个行内元素被设置成浮动了,那么这个浮动元素不能超过行框

7.左(或右)浮动元素的左边(右边)有另一个浮动元素,前者的右外边界不能在其包含块的右(左)边界的右边(左边)。
这里写图片描述

浮动元素不能超出不能超出其包含元素的边界,除非它太宽,本身都无法放下
这就能放置出现: 水平上不够空间
当多个浮动元素在同一个水平行上,远远超过其包含块的边界。
相反,如果浮动元素出现在另一个浮动元素的旁边,而因此可能导致超出包含块的话,这个浮动元素就会向下浮动到之前浮动元素的下面的某一点。

8.浮动元素必须尽可能高地放置
这里写图片描述
在满足了前面规则的前提下,浮动元素会尽可能上浮,
顶端应该与其标记所在行框的顶端对齐。
遗憾的是: 浏览器的实现各不同。

  1. 左浮动元素必须尽可能向左,右浮动必须尽可能向右边!
    位置越高就会向左or向右越远。。

这里写图片描述


实用行为

浮动元素比其父元素高时会有什么结果?
可能会超出父元素。

这里写图片描述
不过这里你会发现,浮动图像超出了父元素的底端。 其实在第一个例子中也是如此,只不过它不明显!
所以:其实上面的9个规则只是处理了 浮动元素和 其父元素的 左、右和上边界,而没有涉及下边界。 这个遗漏是故意的!

浮动元素会延伸,从而包含其所有后代浮动元素。 (但浮动无继承性!)

例如:

<div style="float:left;width:100%;">
<img src="hay.gif" style="float:left;">
The 'div' will stretch around the floated image
</div>

负外边距
eg:图像有-15px 的margin, 被一个div包含,这个div没有padding border margin!
负外边距可能导致浮动元素 移到父元素的外面。
这看上去与之前的规则矛盾!

从技术上说,这是允许的: 一个浮动元素的外边界必须在父元素内。 不过呢,由于外边距是负的,放置浮动元素的内容时就好像覆盖了自己的外边界一样。

数学描述:
div的 上内边界在100px处。 为了得出浮动元素的上内边界,浏览器计算:
100px+(-15px)margin+0padding=85px
因此浮动元素的上内边界应当在85px处,所以上移了。
这里写图片描述
这看上去很“犯规”。 但是这与 负外边距使 正常元素(非浮动元素)视觉上比其父元素还要宽(看上去)是一样的。 浮动元素框 4个边都是:如果将margin设置为负值,内容就会超出外边界。

另一个问题:
使用负margin时,如果浮动元素超过其父元素,文档会如何显示?
例如一个图像可能浮动太远,超出了浏览器已显示的一个段落。这种情况下要由浏览器决定文档是否重新显示。
一般来说,它可能只是重叠覆盖了原有的内容。
另一方向,浏览器也可能让内容环绕浮动元素重新显示
但是这都不是确定的行为,为浮动元素设置负margin的作用会受到限制。

另一种使浮动元素超过其父元素的方法
设置浮动元素的width,使其比父元素更宽!
这里写图片描述


浮动元素、内容和重叠

如果一个浮动元素与正常流中的内容发生重叠会怎样?

规则:

  • 行内框与一个浮动元素重叠时,其边框、背景和内容都在该浮动元素“之上”显示
  • 块框与一个浮动元素重叠时候,其边框,背景在该浮动元素在“之下”显示内容在“之上”显示

即行内元素是覆盖浮动元素的!
而块元素则背景在下,内容在上!

这里写图片描述


清除 (非常有用)

原因
你可能并不总是希望内容流过浮动元素,可能要避免这种行为。
你不希望浮动元素浮动到另一个元素之中。 你希望将每小节的第一个元素设置为禁止浮动元素出现在它旁边

clear工作原理: 增加元素的margin-top ,使之最后落在浮动元素的下面,这实际上忽略为清除元素(设置了clear的元素)顶端设置的 外边距宽度。
也就是说这个元素的margin-top 可能会调整!

清除区域 clearance
CSS2.1 中引入了清除区域。 清除区域是在元素margin-top之上增加的额外间隔,不允许任何元素进入这个范围内。 这意味着元素设置clear属性时,它的外边距并不改变。 之所以会向下移是这个清除区造成的!

img.sider{float:left;margin:0;}
h3{border:1px solid gray; clear:left;margin-top:15px;}
<img src="box.gif" class="sider" height="50" width="50">
<img src="stripe.gif" height="10" width="100">
<h3>Why Doubt Salmon?</h3>

这里写图片描述

h3 上边框与浮动图像下边框之间没有间隔,因为在h3的上外边距之上增加了25px的清除区域,将h3的上边框边界推到刚好越过浮动元素的下边界

问题是:
当然大多数情况无法知道一个元素周围多大范围内不允许有浮动元素。 要如何确保一个清除元素的顶端与一个浮动元素的底端之间有一定空间?
解决
可以为浮动元素本身设置一个margin-bottom。 这个下外边距会增加浮动框的大小.而且由于清除元素必须推到浮动框下面的某个点以下,浮动框大小的增加会使得这个点下移。

img.sider{float:left;margin:0 0 15px;}
h3{border:1px solid gray;clear:left;}

因为浮动框的边界是浮动元素的外边距定义的


2.定位

static
元素框正常生成。 块级元素生成一个矩形框,作为文档流的一部分,行内元素会创建一个或多个行框,置于父元素中。
relative
元素框偏移某个距离。 元素仍保持其未定位前的形状,它原本所占的空间仍保留。 这也是一种定位!
偏移是相对它原来所在的位置(起点)进行偏移。

absolute (块级框)
元素框从文档流完全删除,并相对于其包含块定位,包含块可能是文档中另一个元素或者是初始包含块。
元素原先在正常文档流中所占的空间会关闭,就好像该元素原来不存在一样。 元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。

fixed
元素框的表现类似于将position设置为absolute,但是其包含块是视窗本身。

包含块

Note 对于浮动元素来说包含块:最近的块级祖先元素

初始包含块准确定义:

The containing block in which the root element lives is a rectangle called the initial containing block. For continuous media, it has the dimensions of the viewport and is anchored at the canvas origin; it is the page area for paged media. The ‘direction’ property of the initial containing block is the same as for the root element.

  • “根元素”的包含块(初始包含块)由用户代理建立。在HTML中,根元素就是html元素,不过有些浏览器会使用body作为根元素。 初始包含块:是一个视窗大小的矩形,包含根元素的这个矩形是初始包含块。
  • 对于一个非根元素,如果其position值是 relative 或static ,包含块则由最近的块级框、表单元格或行内祖先框的内容边界构成。 relative或普通文档是:内容边界
  • 对于一个非根元素,如果其position是absolute,包含块设置为 最近的position值不是static的祖先元素。 但是绝对元素是 边框为界
    • 如果这个祖先是块级元素,包含块则设置为该元素的padding内边距边界;换句话说,就是由边框界定的区域。 (边框作为包含边界) padding-box
    • 如果这个祖先是行内元素,包含块则设置为该祖先元素的内容边界。
      祖先是行内元素 包含块的边界
      1) 从左向右读的语言中,包含块的上边界和左边界是该祖先元素中第一个行内框(inline-box)内容区的上边界和左边界,包含块的下边界和右边界是最后一个框(inline-box)内容区的下边界和右边界。
      2)从右向左读的语言中,包含块右边界对应第一个框的右内容边界,包含块的左边界则取自最后一个框的左内容边界。上下边界一样。
      如果没有祖先,元素的包含块定义为初始包含块

注意区分:内容边界(width heigth,不包括边框,内外边距) 边框界(padding-box)是内边距!

偏移属性
这里写图片描述

relative absolute fixed 使用了4个属性来描述 定位元素 各边相对于其包含块的偏移。 这些属性描述了距离包含块最近边的偏移offset

top bottom 相对于包含块的高度
left right相对于包含块的宽度

定位元素: position值不是static的元素

  • top 描述定位元素的 上外边距边界离其包含块的顶端多远。 正值就是把定位元素的上外边距边界 下移,负值则移到包含块的顶端之上。
  • 类似地:left描述了定位元素的左外边距边界 距离包含块的左边界的距离。
    正值就是把定位元素外边距边界 移到包含块的 左边界右边,负值移到左边!

注意对于定位元素 left right top bottom
偏移外边距边界,带来的影响是元素的所有一切包括内容 padding margin border等都会在定位的过程中移动! 设置padding margin border等都会随着定位元素一直保留,并包含在偏移属性定义的区域内。

偏移属性是相对于边的偏移
偏移属性定义了距离包含块相应边的偏移! 而不是距包含块左上角的偏移!

所以填充一个包含块右下角:

top:50%;bottom:0;left:50%;right:0;

这里写图片描述
这个例子中,定义元素的左外边界放在包含块中间的位置上,这是距包含块左边界的偏移。 不过定位元素的右外边界没有从包含块的右边界偏移,所以两者不矛盾。

需要说明的是,定位元素的背景色不同如果有外边距,边框和偏移边界之间就会出现空白。 看上去好像没有填充,实际上它填满了这个区域,以下两组样式的外观效果相同,有margin的话就把margin也算进去作为一个整体,再计算偏移:

通过负值,可以将一个元素定位到其包含块之外。 out of containing block

top:-5em;bottom:50%;left:75%;right:-3em;

这里写图片描述
除了长度值和百分比还可以是auto。

宽度和高度
前提
如果你设置宽度和高度为 auto
那么设置top right bottom left就会改变宽度和高度来适应你的偏移。

当然如果元素有margin boder padding,然后显式为height和width指定值,就不同了:

top:0;bottom:0;left:0;right:50%;width:50%;height:100%;padding:2em;

这里写图片描述
发生这种情况的原因,是内容区增加了内边距padding,而且内边距的大小由height和width的值确定。


内容剪裁 (前提overflow设置不是 visible)

如果一个绝对定位元素的内容溢出其内容框,而且overflow设置为要求剪裁该内容,通过使用属性clip可以改变剪裁区域的形状!
默认值 auto表示元素的内容不应剪裁。

形状 rect(top,right,bottom,left)
rect的值不是边偏移,而是距元素左上角的距离(对于从右向左的语言是元素右上角)
因此,如果一个剪裁矩形涵盖元素左上角20x20px的一个正方形:
rect(0,20px,20px,0)

rect只允许长度值和auto
将剪裁边界设置为适当的内容边界,因此:
clip:rect(auto,auto,10px,1em);

由于clip中心中的所有偏移都是距左上角的偏移,所以不允许有百分数,实际上不可能创建一个”中心”剪裁区域,除非你知道元素本身大小。
clip:rect(1em,4em,6em,1em);

这里写图片描述

clip让你指定一个绝对定位的元素,该元素被剪裁成这种形状并显示。
不过可以设置负长度值,这会使剪裁区延伸到元素框之外。 如果你想将剪裁区域向上向左移动0.25 in

clip:rect(-0.25in,auto,auto,-0.25in);
  • 第一个参数top:是距离左上角 为 -0.25in
  • 第二个参数right 也是距离左上角,所以它包括了元素的宽度啊,如果它小于元素的宽度,元素就会被剪裁!
    bottom也是包含了元素的高度和第一个参数top,所以小于这个和就会被剪裁!
    left 距离左上角的距离

但是呢,因为延伸的剪裁区域(设置成负值导致的),没有任何内容,所以没什么差别
这里写图片描述

另一方面
clip 可以超越下边界和右边界,但是不能超越左边界和上边界! (虚线只是为了说明而不是真实存在)
rect(0,6em,9em,0);

这里写图片描述
这会扩展看到内容的区域。不过内容没有改变,改变就是元素下面可以看到更多的内容。


2.1 绝对定位

包含块和绝对定位元素
元素绝对定位时,会从文档流中完全删除。 然后相对于其包含块定位,其边界根据偏移属性top left放置。 定位元素不会流入其他元素的内容~
绝对定位元素可能覆盖其他元素,或被其他元素覆盖。。。

之前就说过了,绝对定位元素的包含块是最近的position 值不为static的祖先元素

一般做法将position定为relative 而且没有偏移.

p.contain{position:relative;}

这里写图片描述

第一段中的 b元素是相对于初始包含块定位的,因为它的所有祖先元素的position都是static。
而第二段的b元素是相对 设置了position:relative 的元素p来定位的。

第二段中定位元素覆盖了段落中的部分文本内容。 这是没办法的,因为无法将b元素定位到段落之外,因为它在包含块内! 你可以为段落指定padding,都是一般无法指定这么大的padding来容纳定位元素。
唯一的办法,就是为定位元素设置一个背景,或者将其从段落中完全去除。

元素绝对定位时,还会为其后代元素建立一个包含块。

这里写图片描述
也就是说它的子元素的 包含块就是这个绝对定位元素!

div {position:relative;width:100%;height:10em;border:1px solid;background:#EEE;}
div.a{position:absolute;top:0;right:0;width:15em;height:100%;}
diiv.b{position:absolue;bottom:0;left:0;width:10em;height:50%}

滚动性
记住如果文档可滚动,定位元素会随它滚动。 只要不是fixed就是。
原因是元素是相对正常流的某一部分定位的。!
即使你建立一个嵌套4层的绝对定位元素,“最外层”元素总是相对于初始包含块定位。
因此,它会随着初始包含块滚动,所有后代元素也会随之滚动。

绝对定位元素和放置的大小
一个元素使用4个偏移属性定位:

#masthead h1{position:absolute; top:1em;left:1em;right:25%;bottom:10px;margin:0;padding:0;background:silver;}

这里我们没有显式声明h1的高度和宽度, 它的高度和宽度会由外边距边界的放置决定
这里写图片描述

因为要满足top right bottom left的要求,宽度和高度都会自动调整成满足的样子
但是如果包含块更窄,h1也会跟着更窄。
如果向h1增加margin 或padding, 也会有影响

如果显式声明了高度和宽度呢?

#masthead h1{position:absolute; top:0;left:1em;right:10%;bottom:0;margin:0;padding:0;background:silver;height:1em;width:50%;}

这时,让这些值都正确是不可能的!
我们要遵循怎么样的规则去忽略哪几个值???

自动边偏移
绝对定位中 auto 是怎么应用的?
条件
元素绝对定位时,如果除了bottom外某个任意偏移属性设置为auto,会有一种特殊行为:

 <p>xxxxxxxxxxxxxxxxxxxxxxxx<span style="position: absolute;top:auto;left:0;">yyyyyyyyyy</span>xxxxxx</p>

对于left ,元素的左边界会相对于其包含块的左边界放置。 (这里可以假设是初始包含块。)
不过对于top,定位元素的顶端要相对于其未定位前本来的顶端位置对齐
换句话说,假设span的position值为static。它会放在哪里,这就是静态位置,也就是元素在正常流中的原本位置。
这里写图片描述

这个结果就是绝对定位一个元素,top位置与其静态位置一致。
准确表达:“顶端”top的静态位置是从包含块的上边界到假想框的上外边距margin-top边界之间的距离(假想框是假设元素为static时元素的第一个框)。

BTW:如果将left和right都设置为auto,效果就会更static一致了
这里写图片描述
但是由于它是已经定位的,其正常流空间关闭,这会导致定位元素与正常流内容重叠了~

问题2: 如果加入了right bottom width 的限制?

<p>xxxxxxxxxxxxxxxxxxxxxxxx<span style="position: absolute;top:auto;left:auto;right:0;bottom:0;width:5em;height:2em">yyyyyyyyyy</span>xxxxxxxx</p>

下一篇文章揭晓,而且我们会详解 过度受限(Overconstrained)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值