MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

CSS基础概念:理解层叠样式表的核心作用

2023-11-266.6k 阅读

什么是 CSS

CSS,即层叠样式表(Cascading Style Sheets),是一种用于描述网页表现(外观)的标记语言。它允许开发者将网页的内容(HTML)与展示样式分离,从而使网页的设计更加灵活和易于维护。

在没有 CSS 之前,网页的样式直接写在 HTML 标签内,这使得代码冗长且难以管理。例如:

<body>
  <h1 style="color: red; font-size: 24px;">标题</h1>
  <p style="color: blue; font-size: 16px;">段落内容</p>
</body>

使用 CSS 后,可以将样式统一放在一个单独的文件中,HTML 只需引用该 CSS 文件即可。这样不仅代码结构清晰,而且修改样式也变得非常方便。

CSS 的引入方式

内联样式

内联样式是将 CSS 样式直接写在 HTML 标签的 style 属性中。如上面的例子:

<h1 style="color: red; font-size: 24px;">标题</h1>

优点是作用范围明确,只对当前标签生效。缺点是代码冗余,不便于维护和复用,当需要修改样式时,需要逐个修改每个标签的 style 属性。

内部样式表

内部样式表是将 CSS 代码写在 HTML 文件的 <style> 标签内,通常放在 <head> 标签中。

<head>
  <style>
    h1 {
      color: red;
      font-size: 24px;
    }
    p {
      color: blue;
      font-size: 16px;
    }
  </style>
</head>
<body>
  <h1>标题</h1>
  <p>段落内容</p>
</body>

优点是对当前页面有效,样式相对集中,便于管理。缺点是如果多个页面需要相同的样式,无法复用,会导致代码重复。

外部样式表

外部样式表是将 CSS 代码写在一个独立的 .css 文件中,然后在 HTML 文件中通过 <link> 标签引入。 假设创建一个 styles.css 文件:

h1 {
  color: red;
  font-size: 24px;
}
p {
  color: blue;
  font-size: 16px;
}

在 HTML 文件中引入:

<head>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h1>标题</h1>
  <p>段落内容</p>
</body>

优点是可以复用,多个页面可以引用同一个 CSS 文件,便于团队协作开发和维护。缺点是如果 CSS 文件过多,可能会增加 HTTP 请求次数,影响页面加载速度。

CSS 选择器

选择器是 CSS 中用于选中 HTML 元素的工具,通过选择器可以精确地指定要应用样式的元素。

标签选择器

标签选择器通过 HTML 标签名来选中元素。例如,要选中所有的 <p> 标签:

p {
  color: green;
}

这样页面中所有的 <p> 标签内的文本颜色都会变为绿色。

类选择器

类选择器通过元素的 class 属性来选中元素。可以为多个元素添加相同的 class 属性,然后使用类选择器来应用样式。 HTML:

<p class="highlight">段落 1</p>
<div class="highlight">Div 内容</div>

CSS:

.highlight {
  background-color: yellow;
}

这样所有 classhighlight 的元素都会有黄色的背景。

ID 选择器

ID 选择器通过元素的 id 属性来选中元素。每个 HTML 页面中 id 的值必须是唯一的。 HTML:

<p id="unique-paragraph">唯一段落</p>

CSS:

#unique-paragraph {
  color: purple;
}

注意,ID 选择器的优先级比类选择器高。

后代选择器

后代选择器用于选中某个元素的后代元素。例如,要选中 <div> 内的所有 <p> 元素: HTML:

<div>
  <p>段落 1</p>
  <p>段落 2</p>
</div>

CSS:

div p {
  font-weight: bold;
}

这样 <div> 内的 <p> 元素文本都会加粗。

子选择器

子选择器只选中某个元素的直接子元素。例如,要选中 <ul> 的直接子元素 <li>: HTML:

<ul>
  <li>列表项 1</li>
  <li>列表项 2</li>
  <ul>
    <li>子列表项 1</li>
  </ul>
</ul>

CSS:

ul > li {
  color: orange;
}

此时只有 <ul> 的直接子 <li> 元素文本会变为橙色,而嵌套的 <li> 元素不受影响。

相邻兄弟选择器

相邻兄弟选择器选中紧挨着某个元素的下一个兄弟元素。例如,要选中 <h1> 后面紧挨着的 <p> 元素: HTML:

<h1>标题</h1>
<p>段落 1</p>
<p>段落 2</p>

CSS:

h1 + p {
  text-decoration: underline;
}

只有紧挨着 <h1><p> 元素文本会有下划线。

通用选择器

通用选择器 * 选中页面中的所有元素。例如:

* {
  margin: 0;
  padding: 0;
}

这通常用于初始化页面样式,去除浏览器默认的边距。

CSS 盒模型

CSS 盒模型是理解网页布局的基础,每个 HTML 元素都可以看作是一个矩形的盒子,这个盒子由内容(content)、内边距(padding)、边框(border)和外边距(margin)组成。

内容(content)

内容是盒子的核心部分,显示元素的文本、图像等实际内容。例如:

div {
  width: 200px;
  height: 100px;
}

这里设置了 <div> 元素内容区域的宽度为 200 像素,高度为 100 像素。

内边距(padding)

内边距是内容与边框之间的距离。可以分别设置上、右、下、左四个方向的内边距。

div {
  padding-top: 10px;
  padding-right: 20px;
  padding-bottom: 10px;
  padding-left: 20px;
}

也可以使用简写方式:

div {
  padding: 10px 20px; /* 上下 10px,左右 20px */
}

内边距会影响盒子的总尺寸,例如一个内容宽度为 200 像素,左右内边距各为 20 像素的盒子,其实际占据的水平空间为 240 像素(200 + 20 + 20)。

边框(border)

边框围绕在内边距的外面,可以设置边框的宽度、样式和颜色。

div {
  border-width: 1px;
  border-style: solid;
  border-color: black;
}

同样有简写方式:

div {
  border: 1px solid black;
}

边框的样式有 solid(实线)、dashed(虚线)、dotted(点线)等多种。

外边距(margin)

外边距是盒子与其他元素之间的距离,也分为上、右、下、左四个方向。

div {
  margin-top: 10px;
  margin-right: 20px;
  margin-bottom: 10px;
  margin-left: 20px;
}

简写方式:

div {
  margin: 10px 20px; /* 上下 10px,左右 20px */
}

外边距不会影响盒子自身的尺寸,但会影响盒子与周围元素的间距。

盒模型的计算

在标准盒模型(content-box)中,元素的总宽度 = 内容宽度 + 左右内边距 + 左右边框 + 左右外边距。总高度同理。 例如:

div {
  width: 200px;
  padding: 20px;
  border: 1px solid black;
  margin: 10px;
}

<div> 元素实际占据的水平空间为:200(内容宽度) + 20 + 20(左右内边距) + 1 + 1(左右边框) + 10 + 10(左右外边距) = 262 像素。

在 IE 盒模型(border-box)中,设置的 widthheight 包括了内容、内边距和边框。例如:

div {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 1px solid black;
  margin: 10px;
}

此时该 <div> 元素的内容宽度 = 200 - 20 - 20 - 1 - 1 = 158 像素,实际占据的水平空间为 200 + 10 + 10 = 220 像素。

CSS 布局

常规流布局

常规流布局是 HTML 元素默认的布局方式,块级元素在垂直方向依次排列,行内元素在水平方向依次排列。 块级元素(如 <div><p><h1> 等)会独占一行,其宽度默认为父元素的宽度。

<div>块级元素 1</div>
<div>块级元素 2</div>

行内元素(如 <span><a> 等)不会独占一行,其宽度由内容决定,并且可以与其他行内元素在同一行显示。

<span>行内元素 1</span>
<span>行内元素 2</span>

浮动布局

浮动布局通过 float 属性实现,元素可以向左或向右浮动,使其他元素环绕在其周围。

img {
  float: left;
  margin-right: 10px;
}

在 HTML 中,一个 <img> 元素设置了向左浮动后,后面的文本会环绕在图片的右侧。

<img src="image.jpg" alt="图片">
<p>这是一段环绕图片的文本……</p>

浮动布局常用于实现多列布局。例如,实现一个两列布局:

<div class="left-column">左列内容</div>
<div class="right-column">右列内容</div>
.left-column {
  float: left;
  width: 30%;
}
.right-column {
  float: right;
  width: 70%;
}

但是浮动布局会带来一些问题,比如父元素高度塌陷。当父元素内部的子元素都设置了浮动,父元素会无法感知子元素的高度,从而导致高度塌陷。解决方法有很多,比如给父元素添加 overflow: hidden 样式,或者使用清除浮动的方法。

定位布局

定位布局通过 position 属性实现,有以下几种定位方式:

  1. 静态定位(static):这是元素的默认定位方式,元素按照常规流布局。
  2. 相对定位(relative):元素相对于自身在常规流中的位置进行定位。例如:
div {
  position: relative;
  left: 50px;
  top: 30px;
}

此时 <div> 元素会在常规流位置的基础上,向右移动 50 像素,向下移动 30 像素。相对定位不会脱离常规流,其原来占据的空间仍然保留。 3. 绝对定位(absolute):元素相对于最近的已定位(非静态定位)祖先元素进行定位。如果没有已定位的祖先元素,则相对于 <html> 元素。例如:

<div class="parent">
  <div class="child">绝对定位元素</div>
</div>
.parent {
  position: relative;
}
.child {
  position: absolute;
  right: 0;
  bottom: 0;
}

此时 .child 元素会相对于 .parent 元素的右下角进行定位。绝对定位会脱离常规流,其原来占据的空间会被其他元素占据。 4. 固定定位(fixed):元素相对于浏览器窗口进行定位,无论页面如何滚动,元素始终保持在固定位置。常用于创建导航栏等。例如:

nav {
  position: fixed;
  top: 0;
  width: 100%;
  background-color: #333;
  color: white;
}

这样导航栏会固定在页面顶部。

Flex 布局

Flex 布局(Flexible Box Layout)是一种用于一维布局的 CSS 布局模型,它可以轻松地实现元素的排列、对齐和分布。 首先,将父元素设置为 Flex 容器:

.container {
  display: flex;
}

Flex 容器有以下几个重要属性:

  1. flex - direction:定义主轴方向,即子元素的排列方向,可选值有 row(默认,水平从左到右)、row - reverse(水平从右到左)、column(垂直从上到下)、column - reverse(垂直从下到上)。
.container {
  flex - direction: column;
}
  1. justify - content:定义子元素在主轴上的对齐方式,可选值有 flex - start(默认,左对齐或上对齐)、flex - end(右对齐或下对齐)、center(居中对齐)、space - between(两端对齐,子元素之间间隔相等)、space - around(子元素两侧间隔相等,子元素之间间隔是两侧间隔的两倍)。
.container {
  justify - content: center;
}
  1. align - items:定义子元素在交叉轴上的对齐方式,可选值有 stretch(默认,拉伸以填满交叉轴)、flex - start(交叉轴起点对齐)、flex - end(交叉轴终点对齐)、center(交叉轴居中对齐)。
.container {
  align - items: center;
}

子元素也有一些相关属性:

  1. flex - grow:定义子元素的放大比例,默认为 0,即不放大。如果所有子元素的 flex - grow 都为 1,则它们将平均分配剩余空间。
.item {
  flex - grow: 1;
}
  1. flex - shrink:定义子元素的缩小比例,默认为 1,即当空间不足时会缩小。如果设置为 0,则该子元素不会缩小。
  2. flex - basis:定义子元素在分配多余空间之前的初始主尺寸,可以设置为具体的长度值(如 100px)或 auto(根据内容自动调整)。

Grid 布局

Grid 布局(CSS Grid Layout)是一种用于二维布局的 CSS 布局模型,它可以将页面划分为一个个网格,更加灵活地控制元素的位置和大小。 首先,将父元素设置为 Grid 容器:

.container {
  display: grid;
}

Grid 容器有以下几个重要属性:

  1. grid - template - columns:定义网格的列模板,可以设置列的宽度。例如:
.container {
  grid - template - columns: 1fr 2fr 1fr;
}

这里 fr 是一个灵活的长度单位,表示剩余空间的比例,上述代码表示将容器分为三列,第一列和第三列占一份,第二列占两份。 2. grid - template - rows:定义网格的行模板,类似 grid - template - columns。 3. grid - gap:定义网格之间的间距,包括行间距和列间距。可以分别设置 grid - row - gapgrid - column - gap

.container {
  grid - gap: 10px;
}

子元素可以通过 grid - column - startgrid - column - endgrid - row - startgrid - row - end 属性来指定在网格中的位置。例如:

<div class="container">
  <div class="item1">项目 1</div>
  <div class="item2">项目 2</div>
</div>
.container {
  display: grid;
  grid - template - columns: repeat(3, 1fr);
  grid - template - rows: repeat(3, 100px);
  grid - gap: 10px;
}
.item1 {
  grid - column - start: 1;
  grid - column - end: 3;
  grid - row - start: 1;
  grid - row - end: 2;
}
.item2 {
  grid - column - start: 3;
  grid - column - end: 4;
  grid - row - start: 1;
  grid - row - end: 3;
}

这样可以精确控制每个子元素在网格中的位置和占据的空间。

CSS 样式的层叠与优先级

层叠

CSS 的层叠性指的是当多个样式规则应用到同一个元素时,浏览器如何决定最终应用哪个样式。样式规则的来源有以下几种:

  1. 浏览器默认样式:浏览器会为 HTML 元素设置一些默认样式,比如 <p> 元素有一定的边距。
  2. 用户自定义样式:用户可以在浏览器中设置自己的样式,一般优先级高于浏览器默认样式。
  3. 开发者定义样式:即我们编写的 CSS 样式,优先级高于用户自定义样式。

当多个样式规则应用到同一个元素时,按照以下顺序进行层叠:

  1. 样式声明的顺序:后声明的样式会覆盖先声明的样式(前提是它们的优先级相同)。例如:
p {
  color: red;
}
p {
  color: blue;
}

此时 <p> 元素的文本颜色为蓝色,因为 color: blue; 声明在后面。

优先级

样式的优先级决定了哪个样式规则最终会应用到元素上。优先级由以下因素决定:

  1. 选择器的特异性(Specificity):选择器越具体,优先级越高。
    • 内联样式:特异性最高,记为 1,0,0,0
    • ID 选择器:记为 0,1,0,0
    • 类选择器、属性选择器和伪类:记为 0,0,1,0
    • 标签选择器和伪元素:记为 0,0,0,1
    • 通配选择器(*:特异性最低,记为 0,0,0,0。 例如:
/* ID 选择器,优先级 0,1,0,0 */
#my - id {
  color: red;
}
/* 类选择器,优先级 0,0,1,0 */
.my - class {
  color: blue;
}
/* 标签选择器,优先级 0,0,0,1 */
p {
  color: green;
}

如果一个元素同时有 id="my - id"class="my - class" 并且是 <p> 元素,最终文本颜色会是红色,因为 ID 选择器优先级最高。 2. !important 声明:如果一个样式声明后面加上 !important,则该声明具有最高优先级,会覆盖其他所有样式,除非其他样式也有 !important 声明。但应尽量避免使用 !important,因为它会使样式难以维护和调试。例如:

p {
  color: red!important;
}

即使有更具体的选择器,该 <p> 元素的文本颜色也会是红色。

CSS 动画与过渡

过渡(Transition)

过渡可以让元素的样式在一定时间内平滑地从一种状态过渡到另一种状态。 例如,当鼠标悬停在一个按钮上时,让按钮的背景颜色渐变。

<button class="my - button">按钮</button>
.my - button {
  background - color: blue;
  color: white;
  padding: 10px 20px;
  border: none;
  transition: background - color 0.3s ease - in - out;
}
.my - button:hover {
  background - color: red;
}

在上述代码中,transition 属性指定了要过渡的属性(background - color)、过渡时间(0.3s)和过渡的时间函数(ease - in - out,表示缓入缓出)。当鼠标悬停在按钮上时,背景颜色会在 0.3 秒内从蓝色平滑过渡到红色。

transition 属性可以有多个值,例如同时过渡背景颜色和透明度:

.my - button {
  transition: background - color 0.3s ease - in - out, opacity 0.2s linear;
}
.my - button:hover {
  background - color: red;
  opacity: 0.8;
}

动画(Animation)

动画比过渡更加灵活,可以定义多个关键帧,实现更复杂的动态效果。 首先,定义一个动画关键帧:

@keyframes my - animation {
  0% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(100px);
  }
  100% {
    transform: translateX(0);
  }
}

上述代码定义了一个名为 my - animation 的动画,从初始状态(0%)到 50% 时,元素水平移动 100 像素,再回到初始位置(100%)。 然后,将动画应用到元素上:

<div class="animated - div"></div>
.animated - div {
  width: 100px;
  height: 100px;
  background - color: green;
  animation: my - animation 2s infinite;
}

这里 animation 属性指定了动画名称(my - animation)、动画时长(2s)和动画播放次数(infinite 表示无限循环)。这样绿色方块会在水平方向上来回移动。

动画还有很多其他属性,比如 animation - delay 用于设置动画延迟开始时间,animation - direction 可以控制动画的播放方向(如 normalreversealternate 等)。

通过理解和熟练运用 CSS 的这些基础概念,开发者能够创建出美观、交互性强且布局合理的网页,为用户带来良好的浏览体验。无论是简单的静态页面还是复杂的单页应用,CSS 都是前端开发中不可或缺的重要组成部分。