定位 ( position )
所有网页元素在排版中都有默认的定位方式,透过定位相关的样式属性,就能更明确地进行元素的定位,这也是许多别具创意的排版常用的排版样式。这篇教学会完整介绍 position、top、bottom、right、left、z-index、inset、inset-block、inset-inline 等定位相关的样式属性。
快速导览:
教学影片
搭配教学影片一起阅读,效果会更好!欢迎大家订阅 STEAM 教育学习网的 Youtube 频道。
定位类型:position
position 样式属性可以定义元素的“定位方式”,没有继承特性,不论元素 position 的属性值为何,在排版时都会有一个“容器”作为定位的参考依据,下方会列出相关属性值,接着再分别介绍各个属性值的意义和使用方式。
| 属性值 | 说明 | 定位参考 | z-index 影响 |
|---|---|---|---|
| static | 默认定位 | 文件默认排版方向。 | X |
| relative | 相对定位 | 元素原始的位置。 | O |
| absolute | 绝对定位 | 非 static 的祖先元素或 body 元素。 |
O |
| fixed | 固定定位 | 视窗边界或套用特殊样式的祖先元素。 | O |
| sticky | 黏贴定位 | 卷动后元素和视窗边界的距离。 | O |
position:static 默认定位
position:static 是元素默认的定位样式,通常不需要额外设定这个样式属性,除非是在某些情况要不同排版状态才会进行设定 ( 不同分辨率画面、与用户互动...等 ),这表示所有的元素都有有下列默认的定位特性:
- 元素会按照自身的的显示类型,根据“默认的”排版方向 Normal Flow 定位。
- 不会被
top、bottom、left、right、z-index的数值影响。
下方范例展示 inline 元素和 block 元素默认的排版情况。
<!-- HTML 程式碼-->
inline 元素
<div class="a">
<span>apple</span>
<span>banana</span>
<span>coconut</span>
<span>oxxo</span>
</div>
block 元素
<div class="b">
<div>apple</div>
<div>banana</div>
<div>coconut</div>
<div>oxxo</div>
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
padding: 5px;
margin: 5px;
}
div div{background: #ccc;}
span {
background: #ccc;
border: 1px solid #000;
}
</style>
position:relative 相对定位
position:relative 表示元素会进行“相对定位”,设定这个属性值的元素会有下列特性:
- 根据元素“原本的大小和位置”进行相对位移。
- 相对定比特素位移之后,会保留原本的“容器空间”,不会因为元素发生相对定位造成版面位移。
- 相对定比特素会使用“margin 外边界”进行定位。
下方的例子可以清楚看出元素设定为相对定位后,相对位置的参考对象是元素“原本的位置”,蓝色虚线框表示元素原本的位置和所占的空间,不会因为元素位置进行相对移动之后,造成文字往上移动的状况。
<!-- HTML 程式碼-->
<div>
oxxo.studio
<div class="a">top: 30px;<br/>left: 80px</div>
hello world!!
</div>
<div>
oxxo.studio
<div class="b">bottom: 30px;<br/>right: 50px;</div>
hello world!!
</div>
<!-- CSS 程式碼 -->
<style>
div:not([class]) {
border: 1px solid #000;
width: 200px;
height: 150px;
margin: 10px 50px;
}
.a, .b {
border: 1px solid red;
background: pink;
position: relative; /* 設定相對定位 */
width: 100px;
height: 100px;
font-size:14px;
}
.a {
top: 30px;
left: 80px;
}
.b {
bottom: 30px;
right: 50px;
}
</style>
根据同样的规则,如果相对定位的元素出现在“行内元素”的内容里,元素原本的内容空间也会被保留,下方范例会将 strong 元素变成相对定位,原本的空间仍然会保留而呈现空白状态。
<!-- HTML 程式碼-->
<div>
STEAM 教育由五個單字組成,分別是 Science ( 科學 )、Technology ( 技術 )、Engineering ( 工程 )、Arts ( 藝術 ) 和 Mathematics ( 數學 ),因此 STEAM 教育也稱作「跨學科教育」。<strong>OXXO.STUDIO</strong> STEAM 教育延伸 STEM 的精神,除了強調「動手做」以及「解決問題」的能力,更將藝術 Art、技術、工程和數學整合,創造出能夠應用於真實生活的應用。
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
width: 280px;
height: 240px;
}
strong {
background: pink;
position: relative;
top: 60px;
left: 50px;
}
</style>
position:absolute 绝对定位
position:absolute 表示元素会进行“绝对定位”,设定这个属性值的元素会有下列特性:
- 绝对定比特素会参考元素“最靠近的非
static元素 ”位置进行定位 ( 特别注意,是“非static容器”,表示该容器的不能是position:static)。- 如果绝对定比特素“没有”参考的非
static容器,则会使用 body 作为定位容器。- 绝对定比特素会脱离原本的排版方式,元素容器和内容空间会完全独立于其他平面。
- 绝对定比特素默认位置会使用“元素原本的摆放位置”,可透过
top、left之类样式修改。- 绝对定比特素的定位位置是“margin 外边界”。
- 绝对定比特素的显示类型会转换成“block”类型,可设定宽高与上下边界。
下方范例展示绝对定比特素所参考的“非 static 容器”,蓝色 div 因为父元素设定 position:relative 就会参考父元素,红色 div 因为有一个祖先元素设定了 position:relative,就会参考这个元素,而绿色 div 因为其父元素都没有设定,就会参考页面进行绝对定位。
<!-- HTML 程式碼-->
<div class="a">
<div>
<div>apple</div>
</div>
</div>
<div class="b">
<div>
<div>banana</div>
</div>
</div>
<div class="c">
<div>
<div>oxxo</div>
</div>
</div>
<!-- CSS 程式碼 -->
<style>
body {padding-top:60px;}
div {
border: 1px solid #000;
padding: 20px;
background: #aaa;
margin: 10px;
}
div div {
background: #ccc;
margin: 0;
}
div div div {
position: absolute;
top: 0;
left: 0;
}
.a > div {position: relative;} /* 第二層 div 為「非 static 容器」 */
.a div div {background: #f005;}
.b {position: relative;} /* 第一層 div 為「非 static 容器」 */
.b div div {background: #06f5;}
.c div div {background: #0a05;}
</style>
因为绝对定比特素会使用“margin 外边界”进行定位,所以如果绝对定比特素本身有设定外边界,则定位时“需要加上或减去外边界的数值”,下方范例的元素设定了 margin:20px,定位时就会发现位置往右往下各移动了 20px。
<!-- HTML 程式碼-->
<div class="a">
<div>
<div>apple</div>
</div>
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
padding: 20px;
background: #aaa;
margin: 10px;
}
div div {
position: relative;
background: #ccc;
margin: 0;
}
div div div {
position: absolute;
top: 0;
left: 0;
margin: 20px; /* 設定外邊界 */
background: #f005;
}
</style>
转换成绝对定比特素会脱离原本的排版方式,仿佛从原本的排版消失,独立到另外的图层,原本所占的容器或内容空间,就会由其他的元素根据排版方式填补,下方的范例将文字里的 strong 元素转换成绝对定位,除了离开原本的位置且由其他元素递补位置,也可以看出 strong 元素具有 block 特性,可以调整宽高与上下边界。
<!-- HTML 程式碼-->
<div>
STEAM 教育學習網秉持著 STEAM/STEM 的精神<strong>OXXO.STUDIO</strong>,透過一系列免費且高品質的教學與範例,讓所有人都能輕鬆跨入 STEAM 的學習領域。
</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
margin: 10px;
padding: 20px;
position: absolute; /* 父元素設定為 absolute 變成非 static 元素 */
}
strong {
position: absolute;
left: 0;
top: 0;
border: 1px solid red;
padding: 10px 30px;
background: #f005;
}
</style>
position:fixed 固定定位
position:fixed 表示元素会进行“固定定位”,设定这个属性值的元素会有下列特性:
- 固定定比特素会参考所在的“页面视窗”进行定位,不会随卷轴滚动而移动。
- 固定定比特素会脱离原本的排版方式,元素容器和内容空间会完全独立于其他平面。
- 固定定比特素的定为位置是“margin 外边界”。
- 固定定比特素默认位置会使用“元素原本的摆放位置”,可透过
top、left之类样式修改。- 固定定比特素的显示类型会转换成“block”类型,可设定宽高与上下边界。
- 如果固定元素的“祖先元素”的
transform、perspective、filter或backdrop-filter的属性值非 none,固定元素就会参考这个元素进行定位。
下方范例会将四个固定定比特素分别定位在页面的四个角落,不论这些元素原本位在何处,定位后就会使用页面视窗进行定位。
<!-- HTML 程式碼-->
<div>
STEAM 教育學習網秉持著 STEAM/STEM 的精神<div class="a">apple</div>,透過一系列免費且高品質的教學與範例,讓所有人都能輕鬆跨入 STEAM 的學習領域。
</div>
<div>我是 div
<div class="b">banana</div>
</div>
<div>我是第一層 div
<div>我是第二層 div
<div class="c">coconut</div>
</div>
</div>
<div class="d">oxxo</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
padding: 10px;
}
div[class] {
position: fixed; /* 具有 class 屬性的 div 都設定為 fixed */
width: 100px;
height: 100px;
padding: 0;
}
.a {
top: 0;
left: 0;
background: #f00d;
}
.b {
top: 0;
right: 0;
background: #0a0d;
}
.c {
bottom: 0;
right: 0;
background: #00fd;
}
.d {
bottom: 0;
left: 0;
background: #f90d;
}
</style>
如果固定元素的“祖先元素”的 transform、perspective、filter 或 backdrop-filter 的属性值非 none,固定元素就会参考这个元素进行定位,下方范例将设定了某个 div 为 filter: blur(2px),位于该 div 里的固定元素,就会参考这个 div 进行定位,也因为是参考元素不是参考视窗,卷轴移动时就会跟着移动。
<!-- HTML 程式碼-->
<div>
STEAM 教育學習網秉持著 STEAM/STEM 的精神<div class="a">apple</div>,透過一系列免費且高品質的教學與範例,讓所有人都能輕鬆跨入 STEAM 的學習領域。
</div>
<div>我是 div
<div class="b">banana</div>
</div>
<div>我是第一層 div
<div class="test">我是第二層 div
<div class="c">coconut</div>
</div>
</div>
<div class="d">oxxo</div>
<!-- CSS 程式碼 -->
<style>
div {
border: 1px solid #000;
padding: 10px;
}
.a, .b, .c, .d {
position: fixed;
width: 100px;
height: 100px;
padding: 0;
}
.a {
top: 0;
left: 0;
background: #f00d;
}
.b {
top: 0;
right: 0;
background: #0a0d;
}
.c {
bottom: 0;
right: 0;
background: #00fd;
}
.d {
bottom: 0;
left: 0;
background: #f90d;
}
.test {
filter: blur(2px); /* 設定有模糊的 filter */
}
</style>
position:sticky 黏贴定位
position:sticky 表示元素会进行“黏贴定位”,设定这个属性值的元素会有下列特性:
- 黏贴定比特素会参考元素“最靠近的祖先元素的卷动高度”进行定位。
- 根据“指定视窗”的触发条件,呈现
fixed或relative的表现行为 ( 指定视窗表示可卷动黏贴元素的显示区域 )。- 如果黏贴定位的祖先元素设定了
overflow的样式属性,可能会影响黏贴定比特素的显示。
| 表现行为 | 触发条件 |
|---|---|
fixed |
黏贴定比特素和“指定视窗边缘的距离”“小于”黏贴元素设定的数值 |
relative |
黏贴定比特素和“指定视窗边缘的距离”“大于”黏贴元素设定的数值,或接触到任意祖先元素的边缘 |
下方范例将黄色 div 设定为黏贴定位并设定 top: 50px,表示如果卷动卷轴让元素向上移动到距离视窗上缘 50px 时,就会触发变成类似 fixed 固定不动的表现行为,但是如果卷轴继续卷动,直到元素碰到父元素边缘,或向下卷动到元素原本的位置,又会恢复成类似 relative 相对移动的方式。
<!-- HTML 程式碼-->
<div class="test">紅色區塊高度 50px;</div>
<h1>Hello!!</h1>
<div>
<div class="a">oxxo</div>
</div>
<div></div>
<!-- CSS 程式碼 -->
<style>
div {
width: 200px;
height: 300px;
border: 1px solid #000;
}
.a {
width: 100px;
height: 100px;
position: sticky; /* 設定為黏貼定位 */
top: 50px;
left: 0;
background: yellow;
}
.test {
position: fixed; /* 使用一個固定定位元素凸顯位置 */
top: 0;
left: 110px;
background: #f009;
height: 50px;
top: 0;
left: 110px;
}
</style>
下方范例会将所有的 h2 设定为黏贴定比特素,可以看出当卷动卷轴抵达顶端时,h2 就会固定不动,呈现出特别的阅读效果。
<!-- HTML 程式碼-->
<main>
<h1>Hello World!!</h1>
<h2 class="a">apple</h2>
<p>我是內容<br/>我是內容<br/>我是內容<br/>我是內容<br/></p>
<h2>banana</h2>
<p>我是內容<br/>我是內容<br/>我是內容<br/>我是內容<br/></p>
<h2>oxxo</h2>
<p>我是內容<br/>我是內容<br/>我是內容<br/>我是內容<br/></p>
<p>我是內容<br/>我是內容<br/>我是內容<br/>我是內容<br/></p>
<p>我是內容<br/>我是內容<br/>我是內容<br/>我是內容<br/></p>
</main>
<!-- CSS 程式碼 -->
<style>
main {
border: 1px solid #000;
}
h2 {
background: orange;
position: sticky;
top: 0;
}
</style>
位置距离:top、bottom、left、right
除了使用默认值进行定位,也会透过 top、bottom、left、right 这四个样式属性指定位置,这四个样式属性代表“被定位的元素与其参考容器的四个方向的距离”,通常也会称为“offset 属性”,这四个样式属性仅适用于“定位样式非 static”的元素,且都没有继承特性。
| 样式属性 | 说明 |
|---|---|
top |
与参考容器上缘之间的距离。 |
bottom |
与参考容器下缘之间的距离。 |
left |
与参考容器左侧之间的距离。 |
right |
与参考容器右侧之间的距离。 |
这四个样式的属性值默认都是 auto,使用“绝对长度或相对长度”的数值作为单位 ( 参考“长度与角度单位”),由于“top、bottom”和“left、right”代表完全不同方向的距离数值,通常不会同时使用 ( 因为没必要,就如同定义座标也只需要两个数值 ),但如果真的同时使用 ( 制作不同方向语系的网页 ),则会遵循下列规则:
top与bottom同时使用时,以top数值为主。left与right同时使用时,参考容器的文字左到右书写语系以left为主,右到左书写语系以right为主。
下方的范例使用呈现同时使用四个样式属性的状况,由于元素排版方向一率由上到下,所以都会使用 top 数值为主,如果文字书写方向是右到左,就会以 right 为主。
<!-- HTML 程式碼-->
<div class="a">
<div>文字左到右</div>
</div>
<div class="b">
<div>文字右到左</div>
</div>
<!-- CSS 程式碼 -->
<style>
div[class]{
border: 1px solid #000;
width: 200px;
height: 100px;
position: relative; /* 因為子元素使用 absolute,所以需要設定 relative 產生參考容器 */
margin: 10px;
}
.b {direction: rtl;}
div div {
border: 1px solid red;
width: 100px;
height: 50px;
position: absolute;
top: 5px;
bottom: 30px;
left: 5px;
right: 30px;
}
</style>
内嵌宽度:inset、inset-block、inset-inline
有时候面对不同方向语系的网页,或没有设定宽度的定位时,可能会有左右颠倒或不容易控制位置的状况,这时可透过 inset、inset-block 和 inset-inline 样式属性,针对不同的方向嵌入特定的宽度,进而控制元素的位置,这几个样式属性都没有继承特性,并仅适用于“定位样式非 static”元素,相关说明如下:
| 样式属性 | 说明 |
|---|---|
inset |
内嵌“上右下左”宽度造成偏移。 |
inset-block |
逻辑属性,根据元素流向,内嵌“上下”宽度造成偏移。 |
inset-inline |
逻辑属性,根据元素流向,内嵌“右左”宽度造成偏移。 |
这三个样式的属性值默认都是 auto,使用“绝对长度或相对长度”的数值作为单位 ( 参考“长度与角度单位”),三个属性里只有 inset 不会受到元素流向影响,inset 支援 1~4 个数值,一个数值表示“上右下左”,两个数值表示“上下、左右”,三个数值表示“上、左右、下”,四个数值表示“上、右、下、左”,在大部分的情况下,类似于 top、right、bottom 和 left 四个属性值的缩写格式。
特别注意,由于是“内嵌宽度”,当没有设定元素尺寸且尺寸小于父元素时,会造成子元素范围缩减的情况!
下方范例使用四种不同流向的元素,可以看出 inset 所呈现的结果完全相同。
<!-- HTML 程式碼-->
<div><div class="a">oxxo</div></div>
<div><div class="b">oxxo</div></div>
<div><div class="c">oxxo</div></div>
<div><div class="d">oxxo</div></div>
<!-- CSS 程式碼 -->
<style>
div:not([class]) {
position: relative;
width: 200px;
height: 100px;
border: 2px solid #000;
margin: 10px;
}
div div{
position: absolute;
margin: 0;
padding: 0;
background: orange;
}
.a {
direction: ltr;
inset: 5px 20px 40px 60px;
}
.b {
direction: rtl;
inset: 5px 20px 40px 60px;
}
.c {
writing-mode: vertical-rl;
inset: 5px 20px 40px 60px;
}
.d {
writing-mode: vertical-lr;
inset: 5px 20px 40px 60px;
}
</style>
使用 inset 会先以“上、左”的数值为主,除非将上或左的数值设定为 auto,才会套用“下、右”数值,下方范例的第一个 div 虽然使用了四个数值,但会以“上、左”为主,第二个 div 将上左的数值设为 auto,就会以“下、右”为主,第三个 div 则表现支援“负值”的数值。
<!-- HTML 程式碼-->
<div><div class="a">以上、左為主</div></div>
<div><div class="b">上、左設為 auto,使用下、右數值</div></div>
<div><div class="c">支援負值</div></div>
<!-- CSS 程式碼 -->
<style>
div:not([class]) {
position: relative;
width: 300px;
height: 100px;
border: 2px solid #000;
margin: 20px;
}
div div{
position: absolute;
margin: 0;
padding: 0;
background: orange;
width: 300px;
height: 100px;
}
.a {inset: 5px 20px 40px 60px;}
.b {inset: auto 20px 5px auto;}
.c {inset: auto -10px -10px auto;}
</style>
inset-block 和 inset-inline 属于逻辑属性的样式,会受到元素流向的影响,在不同的流向中,内嵌宽度的位置也会跟着颠倒,下方范例呈现不同流向的呈现差异。
<!-- HTML 程式碼-->
<div><div class="a ib">oxxo123</div></div>
<div><div class="b ib">oxxo123</div></div>
<div><div class="c ib">oxxo123</div></div>
<div><div class="d ib">oxxo123</div></div>
<div><div class="a il">oxxo123</div></div>
<div><div class="b il">oxxo123</div></div>
<div><div class="c il">oxxo123</div></div>
<div><div class="d il">oxxo123</div></div>
<!-- CSS 程式碼 -->
<style>
div:not([class]) {
position: relative;
width: 200px;
height: 100px;
border: 2px solid #000;
margin: 10px;
}
div div{
position: absolute;
margin: 0;
padding: 0;
}
.a {direction: ltr;}
.b {direction: rtl;}
.c {writing-mode: vertical-rl;}
.d {writing-mode: vertical-lr;}
.ib {
background: #0c0;
inset-block: 5px 20px;
}
.il {
background: #f50;
inset-inline: 5px 20px;
}
</style>
图层关系:z-index
z-index 样式属性可以设定元素的“Z 轴”位置,也就是常见专有名词“图层”,表示每个元素在显示时的“前后关系”,通常在默认状态下,程序码里下方元素的“容器空间”会覆盖上方元素,但内容不会覆盖,z-index 样式属性没有继承特性,但具有下列特性:
- 只适用于“非
static定比特素”。- 属性值使用“正整数或负整数”,值越大越靠近用户,数值越小越靠远离用户,数值大的元素覆盖数值小的元素。
- 如果数值相同,则按照程序码中的顺序,下方元素覆盖上方元素。
- 默认值 auto,
等同 z-index:0。
下方范例有两组 div,都有修改 div 的 margin 使其互相覆盖,上方的 div 使用默认值,可以看出下方元素虽然会覆盖上方元素,而下方的 div 都修改成 position:relative,下方元素的“容器和内容”就都会覆盖掉上方的元素。
<!-- HTML 程式碼-->
<main>
<div class="a">apple</div>
<div class="b">banana</div>
<div class="c">oxxo</div>
</main>
<main class="z">
<div class="a">apple</div>
<div class="b">banana</div>
<div class="c">oxxo</div>
</main>
<!-- CSS 程式碼 -->
<style>
main {padding: 30px;}
.z div {position: relative;} /* 下方的 div 都是 relative */
div {
padding: 16px;
margin-top: -30px;
border: 1px solid #000;
font-size: 24px;
}
.a {background: #f90;}
.b {
margin-left: 10px;
background: #0c0;
}
.c {
margin-left: 20px;
background: #0cf;
}
</style>
下方范例会修改 z-index 数值,让 div 图层前后排列顺序改变,就会产生不同的效果。
<!-- HTML 程式碼-->
<main>
<div class="a">apple</div>
<div class="b">banana</div>
<div class="c">oxxo</div>
</main>
<main class="z">
<div class="a">apple</div>
<div class="b">banana</div>
<div class="c">oxxo</div>
</main>
<!-- CSS 程式碼 -->
<style>
main {padding: 30px;}
.z div {position: relative;}
div {
padding: 16px;
margin-top: -30px;
border: 1px solid #000;
font-size: 24px;
}
.a {
background: #f90;
z-index: 10; /* z-index 數值最大,擺在最前面 ( 原本在後方 ) */
}
.b {
margin-left: 10px;
background: #0c0;
z-index: -99; /* z-index 數值最小,擺在最後面 ( 原本在中間 ) */
}
.c {
margin-top: -60px;
margin-left: 80px;
background: #0cf;
z-index: 5; /* z-index 數值第二大,擺在中間 ( 原本在最後方 ) */
}
</style>
小结
元素的定位是网页排版中最常出现的技巧,几乎随处可见透过定位方式来指定元素位置,透过这篇教学可以清楚认识元素的定位,相信对于网页排版一定相当有帮助。
微信扫码关注
抖音扫码关注