CSS定位(position属性)

元素的定位类型:固定定位、相对定位以及绝对定位。

position属性的初始值是static,如果把它改成其他值,我们就说元素被定位了,如果使用了静态定位,那么就说它未被定位。

布局方法(flex等)是用各种操作来控制文档流的行为,定位则不同:它将元素彻底从文档流中移走,它允许你将元素放在屏幕的任意位置,还可以将一个元素放在另一个元素的前面或后面,彼此重叠。

固定定位

固定定位让元素相对视口定位,给一个元素设置position: fixed 就能将元素放在视口的任意位置,这需要搭配四种属性一起使用:toprightbottomleft。比如,top: 3em表示元素的上边缘距离视口顶部3em

设置这四个值还隐式地定义了元素的宽高。比如指定left: 2em; right: 2em 表示元素的左边缘距离视口左边2em,右边缘距离视口2em。因此元素的宽度等于视口总宽度减去4em

绝对定位

绝对定位(position: absolute)是相对最近的祖先定位元素,属性toprightbottomleft决定了元素的边缘在包含块里的位置。通常情况下,包含块是元素的父元素。如果父元素未被定位,那么浏览器会沿着DOM树往下找它的祖父、曾祖父,直到找到一个定位元素,用它作为包含块。

如果祖先元素都没有定位,那么绝对定位的元素会基于初始包含块来定位,初始包含块和视口一样大,固定在网页顶部。

相对定位

相对定位依赖文档流。当第一次给元素加上position: relative的时候,通常看不到页面上有任何视觉变化。如果加上toprightbottomleft属性,元素就会从原来的位置移走,但不会改变周围任何元素的位置,其他元素还是围绕着被移走元素的初始位置,跟随着正常的文档流。

relative该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。

跟固定或者绝对定位不同的是,不能用toprightbottomleft改变相对定位元素的大小,这些值只能让元素在上下左右方向移动,可以用top或者bottom,但不能一起用(bottom会忽略,同理,right会被忽略)。

有时可以用这些属性调整相对元素的位置,但这只是相对定位的一个冷门用法,更常用的是使用position: relative给它里面的绝对定位元素创建一个包含块,比如创建一个下拉菜单。

渲染过程和层叠顺序

通常情况下(使用定位前),元素在HTML里出现的顺序决定了绘制的顺序。

定位元素时,浏览器会先绘制所有非定位的元素,然后绘制定位元素。默认情况下,所有定位元素会出现在非定位元素里面。

用z-index控制层叠顺序

z表示的是笛卡尔x-y-z坐标系中的深度方向,拥有较高的z-index的元素出现在拥有较低z-index的元素前面,拥有负数z-index的元素出现在静态元素后面。

z-index只在定位元素上生效,不能用它控制静态元素,给一个定位元素加上z-index可以创建层叠上下文,层叠上下文负责决定哪些元素出现在另一些元素前面。

所有层叠上下文内的元素会按照以下顺序,从后往前叠放:

  • 层叠上下文的根
  • z-index为负的定位元素(及其子元素)
  • 非定位元素
  • z-indexauto的定位元素(及其子元素)
  • z-index为正的定位元素(及其子元素)

粘性定位

浏览器提供了一种新的定位类型: 粘性定位(sticky positioning),它是相对定位和固定定位的结合体:正常情况下,元素会随着页面滚动,当到达屏幕的特定位置时,如果用户继续滚动,他就会锁定在这个位置。常见用例是侧边栏导航。

CSS响应式布局

em和rem

em是最常见的相对长度单位,适合基于特定的字号进行排版。在CSS中,1em等于当前元素的字号,其准确值取决于作用的元素。

.padded {
    font-size: 16px;
    padding: 1em; //浏览器将其乘以字号,最终渲染为16px
}

浏览器会根据相对单位的值计算出绝对值,称作计算值。当设置paddingheightwidthborder-radius等属性时,使用em会很方便。这是当元素继承了不相同的字号,这些属性会跟着元素均匀的缩放。

使用em定义字号

前面说到,当前元素的字号决定了em,如果声明font-size: 1.2em,一个字号怎么等于自己的1.2倍?——实际上,font-size是根据继承的字号来计算的。

// html
<body>
    Body text
    <p class="text">paragraph text</p>
</body>
// css
body {
    font-size: 16px;
}
.text {
    font-size: 1.2em; // 计算结果为元素继承的字号的1.2倍
}

使用rem设置字号

在文档中,根节点是所有其他元素的祖先节点。根节点有一个伪类选择类(:root),可以用来选中自己。

remroot em的缩写,rem是相对于根元素的单位

vh、vw、vmin和vmax

em和rem都是相对于font-size定义的,但CSS中不只有这一种相对单位,还有相对于浏览器视口定义长度的视口的相对单位。
视口:浏览器中窗口里网页可见部分的边框区域,不包括地址栏、工具栏和状态栏。

  1. vh:视口高度的1/100
  2. vw:视口宽度的1/100
  3. vmin:视口宽、高中较小一方的1/100(IE9中叫vm,而不是vmin
  4. vmax:视口宽、高中较大一方的1/100

比如,50vw等于视口宽度的一半。

// 定义正方形
.square {
   width: 90vmin;
   height: 90vmin;
}

使用vw定义字号——如果给一个元素加上font-size: 2vw, 在一个1200px的显示器上,计算值为24px(1200*2%)。这么做的好处在于元素能够在两种大小之间平滑的过渡,不会在某个断点突然改变。当视口大小改变时,元素会逐渐过渡。

使用calc()

calc()函数内可以对两个及其以上的值进行基本运算(加减乘除),加号和减号两边必须有空白。

:root {
    font-size: calc(0.5em + 1vw);
}

0.5em保证了最小字号,1vw确保了字体随着视口缩放。

媒体查询 @media

我们可以根据屏幕尺寸,用媒体查询改变根元素的字号

:root {
    font-size: 0.75em; // 作用到所有屏幕上
}

@media (min-width: 800px) {
    :root {
        font-size: 0.875em; // 仅作用于宽度800px及以上的屏幕,覆盖以前的值
    }
}

@media (min-width: 1200px) {
    :root {
        font-size: 0.875em; // 仅作用于宽度1200px及以上的屏幕,覆盖前面两个的值
    }
}