CSS复习笔记

122 阅读38分钟

实现效果

怎么让Chrome支持小于12px 的文字?

使用缩放比例

使用 CSS 的 transform 属性,可能会导致文本外观变得模糊或失真。

.small-text {
  transform: scale(0.8);
}

使用 zoom

将容器或文本元素的 zoom 属性设置为小于 1 的值,会缩小文本元素及其容器,使得文本看起来更小。请注意,zoom 是非标准的 CSS 属性,不一定在所有浏览器中都有效。

.small-text {
  zoom: 0.8;
}

使用 -webkit-text-size-adjust

将容器或文本元素的 -webkit-text-size-adjust 属性设置为 "none" 或 "auto" 可以控制 Chrome 浏览器对文本大小的调整行为。通过将其设置为 "none",可以禁用 Chrome 浏览器的最小字体大小限制。请注意,-webkit-text-size-adjust 是针对 WebKit 内核(包括 Chrome 和 Safari)的私有属性。

.small-text {
  -webkit-text-size-adjust: none;
}

使用图片替代

如果需要应用较小的文字大小,并且无法使用缩放,可以将文本转换为图像,并将其作为背景图像或内联图像插入到元素中。这样可以绕过浏览器的最小字体大小限制。但要注意,这将增加页面加载时间并且不利于可访问性和响应式设计。

<div class="small-text">
  <img src="path/to/small_text_image.png" alt="Small Text">
</div>

有哪些方式可以隐藏页面的元素

  • 使用CSS
    • display: none;
    • visibility: hidden;
    • opacity: 0;
    • position: absolute; left: -9999px;
    • clip-path
  • 使用JS
    • 直接设置元素的style属性

怎么实现一段文字颜色渐变的效果?

  1. 设置文字的 background 为渐变色。
  2. 使用 -webkit-background-clip: text; 将背景裁剪为文字形状。
  3. 使用 color: transparent; 隐藏文字的原始颜色,确保只显示渐变背景。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        .gradient-text {
            font-size: 48px;
            font-weight: bold;
            background: linear-gradient(90deg, #ff7f50, #1e90ff); /* background: linear-gradient(...): 定义从左到右的渐变色。 */
            -webkit-background-clip: text; /* 让背景裁剪成文字的形状。 */
            color: transparent; /* 隐藏原始文本颜色 使文本颜色透明,从而显示背景的渐变效果。 */
        }
    </style>
    <title>Gradient Text</title>
</head>
<body>

    <h1 class="gradient-text">渐变文字效果</h1>

</body>
</html>

使用css实现一个无限循环动画

.anima {
  animation-name: likes; // 动画名称
  animation-direction: alternate; // 动画在奇数次(135...)正向播放,在偶数次(246...)反向播放。
  animation-timing-function: linear; // 动画执行方式,linear:匀速;ease:先慢再快后慢;ease-in:由慢速开始;ease-out:由慢速结束;ease-in-out:由慢速开始和结束;
  animation-delay: 0s; // 动画延迟时间
  animation-iteration-count: infinite; //  动画播放次数,infinite:一直播放
  animation-duration: 1s; // 动画完成时间
}

@keyframes likes {
  0%{
  	transform: scale(1);
  }
  25%{
  	transform: scale(0.9);
  }
  50%{
  	transform: scale(0.85);
  }
  75%{
  	transform: scale(0.9);
  }
  100%{
  	transform: scale(1);
  }
}
<image class="anima" mode="widthFix" @click="nav" src="@/static/1_btn.png"></image>

如何实现单行/多行文本溢出的省略样式?

单行文本溢出省略

overflow设为hidden,普通情况用在块级元素的外层隐藏内部溢出元素,或者配合下面两个属性实现文本溢出省略

white-space:nowrap,作用是设置文本不换行,是overflow:hidden和text-overflow:ellipsis生效的基础

text-overflow属性值有如下:

  • clip:当对象内文本溢出部分裁切掉
  • ellipsis:当对象内文本溢出时显示省略标记(...) text-overflow只有在设置了overflow:hidden和white-space:nowrap才能够生效的

多行文本溢出省略

基于高度截断

伪元素 + 定位 核心的css代码结构如下: position: relative:为伪元素绝对定位 overflow: hidden:文本溢出限定的宽度就隐藏内容) position: absolute:给省略号绝对定位 line-height: 20px:结合元素高度,高度固定的情况下,设定行高, 控制显示行数 height: 40px:设定当前元素高度 ::after {} :设置省略号样式

基于行数截断

核心的css代码如下: -webkit-line-clamp: 2:用来限制在一个块元素显示的文本的行数,为了实现该效果,它需要组合其他的WebKit属性) display: -webkit-box:和1结合使用,将对象作为弹性伸缩盒子模型显示 -webkit-box-orient: vertical:和1结合使用 ,设置或检索伸缩盒对象的子元素的排列方式 overflow: hidden:文本溢出限定的宽度就隐藏内容 text-overflow: ellipsis:多行文本的情况下,用省略号“…”隐藏溢出范围的文本

现在要开发一个响应式的网站,怎么实现根据设备的尺寸和分辨率,加载不同尺寸的 banner?要求不使用 JavaScript

使用 元素

使用多个 元素,根据屏幕的最小宽度来选择不同的图片。

<picture>
    <source media="(min-width: 1200px)" srcset="banner-large.jpg">
    <source media="(min-width: 600px)" srcset="banner-medium.jpg">
    <img src="banner-small.jpg" alt="Banner Image">
</picture>

使用 srcset 属性

<img> 标签中使用 srcset 定义多个图片及其宽度,结合 sizes 属性指定如何选择图片。

<img src="banner-small.jpg"
     srcset="banner-medium.jpg 600w,
             banner-large.jpg 1200w"
     sizes="(min-width: 1200px) 100vw,
            (min-width: 600px) 50vw,
            100vw"
     alt="Banner Image">

媒体查询

.banner {
    background-image: url('banner-small.jpg');
}

@media (min-width: 600px) {
    .banner {
        background-image: url('banner-medium.jpg');
    }
}

@media (min-width: 1200px) {
    .banner {
        background-image: url('banner-large.jpg');
    }
}

image-set()

可以利用 image-set() 来根据设备像素比加载不同的图片

.banner {
    background-image: image-set(
        url('banner-small.jpg') 1x,
        url('banner-medium.jpg') 2x,
        url('banner-large.jpg') 3x
    );
}

站点一键换肤的实现方式有哪些?

切换 CSS 样式表

方式:通过 JavaScript 动态切换不同的 CSS 样式表文件。 实现步骤:

  1. <head> 标签中引入多个样式表,使用不同的 id 来标识。
<link id="theme-style" rel="stylesheet" href="default-theme.css">
  1. 使用 JavaScript 动态更改 href 属性来切换样式表。
function changeTheme(theme) {
  const linkElement = document.getElementById('theme-style');
  linkElement.href = theme + '-theme.css';
}

使用 CSS 变量

方式:定义 CSS 变量来控制主题样式,通过 JavaScript 动态修改这些变量的值。

  • 在 CSS 文件中定义主题变量。
:root {
  --primary-color: #3498db;
  --background-color: #ecf0f1;
}

.dark-theme {
  --primary-color: #2c3e50;
  --background-color: #34495e;
}
  • 使用 JavaScript 动态切换主题类。
function changeTheme(theme) {
  document.documentElement.className = theme;
}

动态加载样式

方式:利用 JavaScript 动态加载不同的样式文件或 CSS 规则。 实现步骤:

  1. 创建多个样式文件,并使用 JavaScript 动态加载。
function loadTheme(theme) {
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = theme + '-theme.css';
  document.head.appendChild(link);
}
  1. 移除当前样式以避免重复加载。
function changeTheme(theme) {
  const existingLink = document.querySelector('link[href*="-theme.css"]');
  if (existingLink) {
    existingLink.remove();
  }
  loadTheme(theme);
}

使用 JavaScript 插件

实现步骤:

  1. 使用插件,例如 ThemeSwitcher 或类似的工具,根据插件文档进行配置。
  2. 插件通常提供了简单的 API 来更换主题。
$('#theme-switcher').on('change', function() {
  const selectedTheme = $(this).val();
  themeSwitcher.change(selectedTheme);
});

存储用户设置

方式:保存用户选择的主题,并在用户重新访问时应用相同的主题。 实现步骤:

  1. 在用户选择主题时,将其存储到 localStorage 或 sessionStorage。
function setTheme(theme) {
  localStorage.setItem('theme', theme);
  changeTheme(theme);
}
  1. 在页面加载时,读取存储的主题并应用。
document.addEventListener('DOMContentLoaded', function() {
  const savedTheme = localStorage.getItem('theme') || 'default';
  changeTheme(savedTheme);
});

布局定位

CSS 中的文档流

CSS 中的文档流(Document Flow),也称为标准流,是指浏览器如何按照 HTML 元素的结构和 CSS 样式规则来布局和呈现网页内容的过程。文档流决定了元素在页面上的位置和排列方式。文档流的主要特点和组成部分包括:

  1. 主要布局模式
  • 正常流(Normal Flow):元素按照在 HTML 中的顺序逐个显示。块级元素(如 <div>, <p>)在页面上垂直堆叠,行内元素(如 <span>, <a>)在页面上水平排列。
  • 浮动(Float):当元素应用 float 属性后,它会从正常流中脱离,允许其他文本和行内元素围绕它排列。
  • 定位(Positioning):使用 position 属性(如 absolute, relative, fixed, sticky)时,元素会脱离正常流,根据其定位规则进行放置。
  • 弹性盒布局(Flexbox):通过 display: flex,元素成为弹性容器及其子元素成为弹性项,允许灵活地布局和对齐。
  • 网格布局(Grid):通过 display: grid,元素成为网格容器及其子元素成为网格项,提供了二维布局的能力。
  1. 文档流中的元素类型
  • 块级元素(Block-level Elements):通常会从新行开始,占据父元素的整个宽度,如 <div>, <h1>, <p>
  • 行内元素(Inline Elements):在同一行内显示,仅占据其内容的宽度,如 <span>, <a>, <img>
  • 块级行内元素(Block-level Inline Elements):既有块级元素的特性又能在行内显示,如 <button>, <input>
  1. 影响文档流的 CSS 属性
  • display:决定元素的显示类型(如 block, inline, flex, grid)。
  • position:决定元素的定位方式(如 static, relative, absolute, fixed, sticky)。
  • float:使元素脱离正常流并允许文本环绕。
  • clear:用于控制浮动元素的清除,以避免元素重叠。
  1. 文档流的影响
  • 布局:文档流决定了元素的默认布局方式。块级元素会垂直堆叠,行内元素会水平排列。
  • 重叠和排列:使用浮动和定位可以改变元素的排列顺序和位置,但这些元素不会占据正常文档流的位置。
  • 响应式设计:通过调整文档流中的元素(如使用 Flexbox 或 Grid),可以实现响应式布局,适应不同的屏幕尺寸。

css 中的 BFC、IFC、GFC 和 FFC 分别指什么?

BFC:用于块级元素的布局和清除浮动。

  • 定义:BFC 是一个独立的渲染区域,所有的块级盒子都在这个上下文中进行布局。它定义了块级元素的布局和定位规则。
  • 特性:
    • 清除浮动:BFC 可以用于清除浮动元素带来的影响,因为 BFC 形成的区域不会被浮动元素影响。
    • 自适应高度:BFC 会计算自身的高度以包裹包含的内容,确保包含块的高度能根据内容变化而调整。
    • 边距折叠:垂直方向上,BFC 中相邻的块级元素的边距不会折叠到 BFC 的外部。
  • 触发 BFC 的情况:
    • 根元素
    • display: flow-root(用于创建新的 BFC)
    • position: absolute 或 position: fixed
    • float(左或右)
    • overflow 的值为 hidden, auto, 或 scroll
    • display: table(table, inline-table)

IFC:用于内联元素的水平排列。

  • 定义:IFC 是处理内联元素(如 <span>、<a>)的上下文。它定义了这些元素如何在一行中进行布局。
  • 特性:
    • 水平排列:在 IFC 中,内联元素按水平顺序排列,直到当前行的宽度被填满。
    • 高度自适应:内联元素的高度由内容决定,不会影响周围元素的高度。
    • 不影响其他行:内联元素不会影响其他行的布局,行内元素会在行中水平排列。

GFC:用于 CSS Grid 布局中的网格项布局。

  • 定义:GFC 是在使用 CSS Grid 布局时创建的上下文。它定义了如何在网格容器内布局网格项。
  • 特性:
    • 网格布局:在 GFC 中,元素会按照定义的网格行和列进行布局。
    • 完全控制:通过 CSS Grid,开发者可以完全控制网格项的位置和大小。
    • 网格线:GFC 允许开发者定义网格线,从而精确控制布局。

FFC:用于 CSS Flexbox 布局中的弹性项布局。

  • 定义:FFC 是在使用 CSS Flexbox 布局时创建的上下文。它定义了如何在弹性容器内布局弹性项。
  • 特性:
    • 弹性布局:在 FFC 中,元素会根据 Flexbox 属性(如 flex-direction, justify-content, align-items)进行弹性布局。
    • 方向控制:开发者可以控制主轴和交叉轴上的对齐方式。
    • 自适应布局:FPC 允许弹性项根据容器大小自动调整自身的大小和排列方式。

z-index属性在什么情况下会失效?

z-index 属性用于控制元素的堆叠顺序,z-index值越大就越是在上层。z-index元素的position属性需要是relative,absolute或是fixed。但有时会出现失效的情况。

常见的导致 z-index 失效的原因:

  1. 没有设置 position 属性: z-index 仅对设置了 position 属性(absolute、relative、fixed 或 sticky)的元素有效。
  2. z-index 值不在范围内: z-index 可以取负值,但必须在 position 属性设置后才能生效。
  3. 元素被隐藏: 如果元素的 visibility 属性设置为 hidden,或者 display 属性设置为 none,则 z-index 不会生效。
  4. z-index 值相同: 如果多个元素的 z-index 值相同,它们的堆叠顺序将按照它们在文档流中的顺序决定。
  5. z-index 值被覆盖: 如果父元素的 z-index 值较高,可能会覆盖子元素的 z-index。
  6. 元素是 position: static: 静态定位的元素(position: static)不会创建新的层级,因此 z-index 不会生效。
  7. 元素在不同的堆叠上下文: 堆叠上下文(Stacking Context)可以被创建,例如通过 opacity、transform 等属性,这会影响 z-index 的效果。
  8. 在手机端 iOS 13 系统中,-webkit-overflow-scrolling:touch 也会使 z-index 失效,将 touch 换成 unset

未知高度和宽度元素的水平垂直居中的方案有哪些, 简单手写一下?

Flexbox

container {
  display: flex;
  justify-content: center; /* 水平居中 */
  align-items: center;     /* 垂直居中 */
  height: 100vh;           /* 使容器填满视口 */
}

.centered-element {
  /* 元素的样式 */
}
<div class="container">
  <div class="centered-element">Centered</div>
</div>

Grid

.container {
  display: grid;
  place-items: center;     /* 同时水平和垂直居中 */
  height: 100vh;           /* 使容器填满视口 */
}

.centered-element {
  /* 元素的样式 */
}
<div class="container">
  <div class="centered-element">Centered</div>
</div>

Absolute + Transform

.container {
  position: relative;
  height: 100vh;           /* 使容器填满视口 */
}

.centered-element {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%); /* 使元素居中 */
}
<div class="container">
  <div class="centered-element">Centered</div>
</div>

Line-Height (适用于单行文本)

.container {
  height: 100vh;           /* 使容器填满视口 */
  line-height: 100vh;      /* 设置行高为容器高度 */
  text-align: center;      /* 水平居中 */
}

.centered-element {
  display: inline-block;
  vertical-align: middle; /* 垂直居中 */
  line-height: normal;    /* 恢复正常行高 */
}
<div class="container">
  <div class="centered-element">Centered</div>
</div>

三栏布局

Flexbox 布局

<div class="container">
  <div class="sidebar-left">左侧</div>
  <div class="main">中间</div>
  <div class="sidebar-right">右侧</div>
</div>

<style>
  .container {
    display: flex;
    justify-content: space-between;
  }
  .sidebar-left, .sidebar-right {
    flex: 0 0 200px; /* 固定宽度 */
  }
  .main {
    flex: 1; /* 自动填充剩余空间 */
  }
</style>

Grid 布局

<div class="grid-container">
  <div class="sidebar-left">左侧</div>
  <div class="main">中间</div>
  <div class="sidebar-right">右侧</div>
</div>

<style>
  .grid-container {
    display: grid;
    grid-template-columns: 200px 1fr 200px; /* 定义三列的宽度 */
    gap: 10px; /* 列间距 */
  }
  .sidebar-left, .sidebar-right {
    background-color: #f0f0f0;
  }
  .main {
    background-color: #e0e0e0;
  }
</style>

浮动布局

需要清除浮动,代码维护较为繁琐。

<div class="container">
  <div class="sidebar-left">左侧</div>
  <div class="main">中间</div>
  <div class="sidebar-right">右侧</div>
</div>

<style>
  .container {
    overflow: hidden; /* 清除浮动 */
  }
  .sidebar-left, .sidebar-right {
    float: left;
    width: 200px; /* 固定宽度 */
  }
  .main {
    margin: 0 200px; /* 设置左右边距 */
  }
</style>

绝对定位布局

需要手动计算和调整,可能不如其他方法灵活和易用。

<div class="container">
  <div class="sidebar-left">左侧</div>
  <div class="main">中间</div>
  <div class="sidebar-right">右侧</div>
</div>

<style>
  .container {
    position: relative;
    height: 100vh; /* 高度为视口高度 */
  }
  .sidebar-left, .sidebar-right {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 200px; /* 固定宽度 */
  }
  .sidebar-left {
    left: 0;
  }
  .sidebar-right {
    right: 0;
  }
  .main {
    position: absolute;
    left: 200px;
    right: 200px;
    top: 0;
    bottom: 0;
  }
</style>

flex:1的意思

flex: 1是flex - grow、flex - shrink和flex - basis这三个属性的缩写形式。它用于在弹性盒子布局(flex布局)中控制子元素的尺寸和伸缩性。

flex - grow属性

定义:它决定了容器内剩余空间在子元素之间的分配比例。当容器的宽度(或高度,取决于flex - direction)大于所有子元素的flex - basis之和时,flex - grow属性指定了每个子元素应该分配多少剩余空间。

flex - shrink属性

定义:它指定了在容器空间不足时,子元素的收缩比例。当容器的宽度(或高度)小于所有子元素的flex - basis之和时,flex - shrink属性决定了每个子元素应该收缩多少。

flex - basis属性

定义:它定义了在分配剩余空间之前元素的初始大小。可以是一个长度值(如200px),也可以是一个关键字(如auto)。如果是auto,则元素的初始大小由其内容决定。

flex:1的综合效果

当写flex:1时,实际上是flex - grow:1; flex - shrink:1; flex - basis:0%(在大多数浏览器中的默认解析)。这意味着这个子元素会在flex容器中有弹性,它会根据容器内其他元素的情况,按照 1:1 的收缩和增长比例来分配空间,并且初始大小为 0(但会根据内容撑开)。例如,在一个水平flex布局的容器中有三个子元素,都设置为flex:1,那么它们会平分容器的宽度,并且当容器宽度改变时,它们会等比例地伸缩。

gap 属性是用来设置什么的?

gap 属性用于设置在网格布局(grid)或弹性布局(flex)中,子元素(项目)之间的间距。它可以同时设置行间距和列间距,或者分别通过 row-gap 和 column-gap 单独设置。

.container {
  display: grid;
  gap: 10px;
}

position 的 sticky 有什么应用场景?

position: sticky 是一种结合了 relative 和 fixed 特性的定位方式,在一定的滚动范围内表现为相对定位,但当达到设定的阈值时会变成固定定位。它在前端开发中常用于创建随滚动动态固定的内容,提升用户体验。以下是一些常见的应用场景:

导航栏固定

场景:页面有一个较长的内容,当用户滚动页面时,导航栏可以保持在视口顶部,方便用户随时访问导航选项。 这种场景中使用 sticky 使导航栏在滚动时停留在顶部。

.navbar {
    position: sticky;
    top: 0;
    background-color: white;
    z-index: 1000;
}

内容目录(TOC)

场景:在文章页面中,常有一个内容目录(Table of Contents)来帮助用户快速跳转到对应章节。使用 sticky 可以让目录随着用户的滚动停留在侧边,便于用户随时查看。

.toc {
    position: sticky;
    top: 20px; /* 距离顶部 20px */
}

表头固定

场景:在一个有滚动条的表格中,让表头保持固定,以便用户在查看数据时,始终能看到列的名称。 在表头元素上使用 position: sticky; top: 0;,可以让表头在滚动时停留在表格的顶部。

th {
    position: sticky;
    top: 0;
    background-color: #f1f1f1;
}

浮动的侧边栏

场景:在一个带有侧边栏的布局中,可以使侧边栏随滚动保持在视口的一个固定位置,避免用户需要返回顶部才能看到侧边内容。 设置 top 值,让侧边栏在到达该位置时停留。

.sidebar {
    position: sticky;
    top: 10px; /* 在距离视口顶部 10px 时固定 */
}

分段内容的标题固定

场景:长文档或博客文章中,常分成多个章节,每一章节的标题可以使用 sticky 实现“吸附效果”。当用户滚动到每一章节时,标题会停留在顶部,清晰指示当前章节内容。 设置 top 值,让标题随章节滚动到顶部时停留。

.section-title {
    position: sticky;
    top: 0;
    background-color: #fff;
    z-index: 1;
}

购物车或价格信息的固定

场景:在电商产品页面中,当用户浏览详细信息时,可以将购物车按钮或价格信息固定在侧边或底部,便于用户快速访问结算功能。

.price-info {
    position: sticky;
    top: 10px;
}

position: fixed 一定是相对于浏览器窗口进行定位吗?

不一定。

position:fixed;的元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置,元素的位置在屏幕滚动时不会改变。fixed 属性会创建新的层叠上下文。

当元素祖先的 transform, perspective 或 filter 属性非 none 时,容器由视口改为该祖先。

CSS 尺寸单位

绝对单位:px, cm, mm, in, pt, pc

相对单位:%, em, rem, vh, vw, vmin, vmax, ch, ex

%(百分比):相对于包含块的尺寸,如父元素的宽度或高度。

em:相对于当前元素的字体大小,1em等于当前字体的大小。

rem:相对于根元素()的字体大小,1rem等于根元素的字体大小。

vh(视口高度):相对于视口的高度,1vh等于视口高度的1%。

vw(视口宽度):相对于视口的宽度,1vw等于视口宽度的1%。

vmin:相对于视口的较小的宽度或高度,1vmin是 vw 和 vh 中较小的那个。

vmax:相对于视口的较大的宽度或高度,1vmax是 vw 和 vh 中较大的那个。

ch:相对于 0 字符的宽度(当前字体的数字 0 的宽度)。

ex:相对于当前字体的 x 高度。

动态单位:auto, min-content, max-content, fit-content

CSS中的1像素问题是什么?有哪些解决方案?

  • 1 像素问题 是由于高分辨率屏幕上的像素密度不同,导致 1 像素边框或线条的渲染问题。
  • 解决方案 包括使用 border、box-shadow、transform、background、CSS 变量、媒体查询,以及 SVG 或 Canvas 绘制。

使用 transform 解决:通过设置元素的 box-sizing 为 border-box,然后构建伪元素,再使用 CSS3 的 transform 缩放,这是目前市面上最受推崇的解决方法。 缺陷:对于已使用伪元素的元素要多嵌套一个无用元素

.one-pixel-border {
  position: relative;
  box-sizing: border-box;
}

.one-pixel-border::before {
  display: block;
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200%;
  height: 200%;
  border: 1px solid red;
  transform: translate(-50%, -50%) scale(0.5, 0.5);
}

伪类和伪元素

CSS伪类:选择元素的状态或结构特征。主要用于根据用户交互或元素在文档中的位置来改变样式。

:hover - 选择当鼠标悬停在元素上时的状态。

:focus - 选择当元素获得焦点时的状态,通常用于输入框。

:nth-child(n) - 选择父元素中第 n 个子元素。

:first-child - 选择父元素中的第一个子元素。

:last-child - 选择父元素中的最后一个子元素。

:first-of-type 选择属于其父元素的首个元素

:last-of-type 选择属于其父元素的最后元素

:only-of-type 选择属于其父元素唯一的元素

:only-child 选择属于其父元素的唯一子元素

:not(selector) - 选择不匹配指定选择器的元素。

:checked - 选择已选中的输入框(如复选框、单选框)。

:enabled :disabled 表单控件的禁用状态。

CSS伪元素:选择元素的特定部分或添加新的内容。伪元素主要用于插入额外的样式或内容到元素的特定位置。

::before - 在元素的内容之前插入内容。

::after - 在元素的内容之后插入内容。

::first-line - 选择元素的第一行文本。

::first-letter - 选择元素的第一个字母。

选择器

浏览器如何解析css选择器?

浏览器会『从右往左』解析CSS选择器。

html 元素节点上, 有多个 class 名称,这几个class 名称对应的样式渲染优先级是如何的?

在 HTML 元素上,多个 class 名称的样式渲染优先级(或称为特指度)是由 CSS 的特指度计算规则决定的。

特指度计算规则

  1. ID 选择器(如 #header):特指度最高。
  2. 类选择器(如 .menu)、属性选择器(如 [type="text"])和伪类选择器(如 :hover):特指度次之。
  3. 元素选择器(如 div)和伪元素选择器(如 ::before):特指度最低。
  4. 通配符选择器(如 *)、组合器(如 >、+)和伪类(如 :not())的特指度通常较低。

计算多个 class 的优先级

当一个元素上有多个 class 名称时,每个 class 名称的样式规则都会应用到该元素。若多个 class 选择器定义了相同的 CSS 属性,浏览器会按照以下规则决定哪个样式优先应用:

  1. 特指度:在多个 class 选择器的情况下,优先应用特指度更高的规则。例如,.class1 和 .class2 的特指度相同,那么后定义的样式会覆盖先定义的样式。

  2. 样式表的顺序:如果多个样式规则的特指度相同,那么后定义的规则会覆盖先定义的规则。例如,如果 CSS 文件中 .menu { color: red; } 在 .header { color: blue; } 之后,那么 .menu 的样式会被应用。

  3. 内联样式:内联样式(即 style 属性中的样式)具有比外部样式表更高的特指度。如果元素上有内联样式,它们会覆盖 class 中定义的样式。

  4. !important 声明:如果 CSS 属性使用了 !important,它将具有最高的优先级,覆盖所有其他没有 !important 的规则。

选择器的效率问题

  1. CSS 选择器效率的重要性 在网页加载和渲染过程中,CSS 选择器的效率会影响页面的性能。如果选择器效率低下,浏览器在解析和应用样式时需要花费更多的时间和资源,可能导致页面加载速度变慢,特别是在处理复杂的大型网页时。

  2. 不同类型选择器的效率对比

  • ID 选择器:效率最高。在文档中,ID 是唯一的,浏览器可以通过内部的哈希表快速定位到具有特定 ID 的元素。例如,#myElement这样的选择器,当浏览器解析到这个选择器时,它能够迅速找到 ID 为myElement的元素并应用样式。因为 ID 选择器具有很高的特异性,它的优先级也很高。
  • 类选择器:效率次之。类选择器是通过元素的类名来选择元素,如.myClass。浏览器会遍历文档中的元素,检查每个元素的类列表中是否包含指定的类名。虽然比 ID 选择器慢,但如果合理使用,性能影响通常是可以接受的。而且一个类可以被多个元素共享,这使得类选择器在样式复用方面非常有用。
  • 标签选择器:效率相对较低。例如p、div等标签选择器,浏览器需要遍历文档中的所有标签,找出符合选择器的元素。当文档结构很复杂,元素数量众多时,使用大量的标签选择器可能会导致性能下降。不过在某些简单的布局场景下,如对所有段落元素应用相同的基本样式,标签选择器还是很方便的。
  • 后代选择器(包含选择器):效率较低。例如div p这样的选择器,表示选择所有div元素内部的p元素。浏览器需要先找到所有的div元素,然后在每个div元素内部查找p元素。这种选择器的效率随着文档结构的深度和复杂度增加而降低。如果文档结构很深,使用过多的后代选择器可能会使浏览器花费大量时间来匹配元素。
  • 通配符选择器:效率最低。如*选择器,它会匹配文档中的所有元素。这意味着浏览器需要遍历整个文档来查找所有元素,并且对于每个元素都要考虑是否应用相应的样式。在实际开发中,应该尽量避免使用通配符选择器,除非确实需要对所有元素应用某种基本样式,比如设置所有元素的box - sizing: border - box;来统一盒模型计算方式。
  1. 提高 CSS 选择器效率的策略
  • 减少选择器的复杂性:尽量避免使用过长的选择器链,例如body div#main.content p span这样复杂的选择器。选择器越复杂,浏览器解析和匹配的时间就越长。
  • 避免过度嵌套:在编写 CSS 预处理器(如 Sass 或 Less)代码时,容易出现过度嵌套的情况。
  • 利用特异性(Specificity)合理安排选择器顺序:了解选择器的特异性有助于提高效率。例如,先定义通用的样式,再通过更具体的选择器来覆盖特定元素的样式。如果有一个通用的段落样式p { color: black; },然后针对某个特殊的段落有#special - section p { color: blue; },浏览器可以先应用通用样式,然后在需要的地方通过更具体的选择器来修改样式,这样可以使样式应用过程更加高效。

CSS变量

CSS 变量(也叫自定义属性)是 CSS 中的一项重要特性,允许开发者在样式表中定义可以重复使用的值,并可以在不同的地方引用这些值。CSS 变量使得样式的管理和维护更加灵活,尤其在处理复杂的设计系统和动态主题时非常有用。

定义 CSS 变量

CSS 变量使用 -- 前缀来定义,并且可以在任意选择器中定义。它们可以在任何作用域中声明,作用域决定了变量的可访问范围。

:root {
    --primary-color: #3498db; /* 定义全局变量 */
}

:root 选择器表示文档的根元素(通常是 <html>),定义在 :root 中的变量是全局变量,可以在整个文档中使用。 可以在其他元素或类中定义局部变量,但这些变量的作用域仅限于其定义的上下文。

使用 CSS 变量

使用 CSS 变量时,通过 var() 函数来引用变量的值。例如:

body {
    background-color: var(--primary-color); /* 使用 CSS 变量 */
}

作用域

  • 全局作用域:如果在 :root 中定义变量,它可以在整个文档中访问。
  • 局部作用域:如果在某个元素或类中定义变量,它仅在该元素及其子元素中有效。
:root {
    --global-color: red; /* 全局变量 */
}

.container {
    --container-color: green; /* 局部变量,仅在.container及其子元素有效 */
}

.header {
    color: var(--global-color); /* 使用全局变量 */
}

.footer {
    color: var(--container-color); /* 使用局部变量 */
}

默认值

CSS 变量可以为 var() 函数提供一个默认值,当变量未定义或值为空时,使用默认值。默认值在 var() 的第二个参数中指定。

.content {
    color: var(--text-color, black); /* 如果 --text-color 未定义,则使用 black */
}

动态修改 CSS 变量

CSS 变量具有动态性,可以通过 JavaScript 来修改它们的值。修改变量时,浏览器会立即重新渲染受影响的元素,使得它们能够响应变化。

document.documentElement.style.setProperty('--primary-color', '#e74c3c');

继承和覆盖

CSS 变量支持继承,这意味着子元素可以继承父元素定义的变量的值。变量可以被覆盖,并且具有局部作用域。

:root {
    --main-color: blue;
}

.child {
    --main-color: red; /* 重写父元素的 --main-color 变量 */
    color: var(--main-color); /* 子元素的文字颜色为 red */
}

支持的浏览器

CSS 变量被大多数现代浏览器支持,包括 Chrome、Firefox、Safari 和 Edge。但在老版本的浏览器(如 IE)中并不支持,因此在使用时需要考虑兼容性问题。

全局样式

CSS Modules

CSS Modules 是一种用于组织和管理 CSS 的技术。它通过在编译时为每个 CSS 类名生成唯一的标识符,并将它们作为 JavaScript 对象的属性导出。这样,可以确保每个类名在整个应用程序中的唯一性,避免样式冲突。

使用 CSS Modules,可以将 CSS 文件与组件文件绑定在一起,这样每个组件都有自己的 CSS 作用域,样式只会应用于特定的组件,不会影响其他组件。这种隔离性和局部作用域有助于降低样式冲突和维护 CSS 的复杂性。

CSS Modules 还提供了一些其他功能,例如:

  1. 局部作用域: CSS Modules 允许在组件中定义局部样式,这些样式仅适用于该组件。这样,可以避免全局样式造成的副作用,并使组件更加可重用。

  2. 类名和样式的映射: 使用 CSS Modules,可以通过导入生成的样式对象,将类名映射到组件中的类名,并将其应用于相应的元素。这样可以方便地将样式与组件关联起来,并跟踪样式的变化。

  3. 继承和组合: CSS Modules 支持继承和组合样式。可以通过使用类名组合和继承规则,将多个样式应用于同一个元素或组件。

总结来说,CSS Modules 提供了一种更可靠和可维护的方式来管理 CSS,通过实现局部作用域和唯一类名标识符,帮助开发者避免样式冲突和提高样式的可重用性。

// Button.module.css
.button {
  background-color: blue;
  color: white;
}

// Button.js
import React from 'react';
import styles from './Button.module.css';

const Button = () => (
  <button className={styles.button}>Click me</button>
);

export default Button;

全局样式命名冲突和样式覆盖问题怎么解决?

在前端开发过程中,有几种常见的方法可以解决全局样式命名冲突和样式覆盖问题:

  1. 使用命名空间(Namespacing):给样式类名添加前缀或命名空间,以确保每个组件的样式类名不会冲突。例如,在一个项目中,可以为每个组件的样式类名都添加一个唯一的前缀,例如.componentA-button和.componentB-button,这样可以避免命名冲突。

  2. 使用BEM命名规范:BEM(块、元素、修饰符)是一种常用的命名规范,可以将样式类名分成块(block)、元素(element)和修饰符(modifier)三个部分,以确保样式的唯一性和可读性。例如,.button表示一个块,.button__icon表示一个元素,.button--disabled表示一个修饰符。

  3. 使用CSS预处理器:CSS预处理器(如Sass、Less)可以提供变量、嵌套规则和模块化等功能,可以更方便地管理样式并避免命名冲突。例如,可以使用变量来定义颜色和尺寸,使用嵌套规则来组织样式,并将样式拆分成多个模块。

  4. 使用CSS模块:CSS模块提供了在组件级别上限定样式作用域的能力,从而避免了全局样式的冲突和覆盖。每个组件的样式定义在组件内部,使用唯一的类名,确保样式的隔离性和唯一性。

  5. 使用CSS-in-JS解决方案:CSS-in-JS是一种将CSS样式直接写入JavaScript代码中的方法,通过将样式与组件绑定,可以避免全局样式的冲突问题。一些常见的CSS-in-JS解决方案包括Styled Components、Emotion和CSS Modules with React等。

如何避免全局样式污染?

  1. 使用 CSS 模块 CSS Modules:每个 CSS 文件只对其作用的组件生效,样式局部化,避免全局污染。例如,在使用 CSS Modules 的项目中,样式只会影响导入了该模块的组件。
  2. 使用命名空间 命名空间:为类名添加前缀,或使用更具描述性的命名空间,避免类名冲突。例如,使用 Button__primary 而不是 .primary。
  3. CSS-in-JS CSS-in-JS:使用如 styled-components 或 emotion 这样的库将 CSS 和 JavaScript 结合,样式与组件绑定,不会全局污染。
  4. Scoped CSS Scoped Styles:在 Vue.js 等框架中,使用 <style scoped> 将样式限制在组件内部,只影响当前组件的 DOM 元素。
  5. BEM 方法论 BEM(Block Element Modifier):遵循 BEM 方法论编写 CSS 类名,使类名具有更高的特异性,避免样式冲突。例如,.block__element--modifier
  6. CSS 预处理器 CSS 预处理器:使用 Sass、Less 等预处理器来组织样式,通过嵌套、变量和混合宏提高样式管理能力,减少全局样式污染。
  7. 避免通配符选择器 限制通配符选择器使用:避免使用 * 选择器,这会影响所有元素,增加样式污染的风险。
  8. 使用 CSS 变量 CSS Variables:通过定义 CSS 变量(自定义属性),确保样式在组件中可控,并减少全局样式的影响。
  9. 合理使用继承 继承:尽量避免深层次的样式继承。使用明确的选择器来减少继承的副作用。
  10. 分离结构与样式 分离结构与样式:尽量将结构和样式分离,保持 CSS 文件的简洁和模块化。

html和css中的图片加载与渲染规则是什么样的?

Web浏览器先会把获取到的HTML代码解析成一个DOM树,HTML中的每个标签都是DOM树中的一个节点,包括display: none隐藏的标签,还有JavaScript动态添加的元素等。

浏览器会获取到所有样式,并会把所有样式解析成样式规则,在解析的过程中会去掉浏览器不能识别的样式。

浏览器将会把DOM树和样式规则组合在一起(DOM元素和样式规则匹配)后将会合建一个渲染树(Render Tree),渲染树类似于DOM树,但两者别还是很大的:

渲染树能识别样式,渲染树中每个节点(NODE)都有自己的样式,而且渲染树不包含隐藏的节点(比如display:none的节点,还有</head>内的一些节点),因为这些节点不会用于渲染,也不会影响节点的渲染,因此不会包含到渲染树中。一旦渲染树构建完毕后,浏览器就可以根据渲染树来绘制页面了。

简单的归纳就是浏览器渲染Web页面大约会经过六个过程:

  • 解析HTML,构成DOM树
  • 解析加载的样式,构建样式规则树
  • 加载JavaScript,执行JavaScript代码
  • DOM树和样式规则树进行匹配,构成渲染树
  • 计算元素位置进行页面布局
  • 绘制页面,最终在浏览器中呈现

是不是会感觉这个和我们图像加载渲染没啥关系一样,事实并非如此,因为img、picture或者background-image都是DOM树或样式规则中的一部分,那么咱们套用进来,图片加载和渲染的时机有可能是下面这样:

  • 解析HTML时,如果遇到img或picture标签,将会加载图片
  • 解析加载的样式,遇到background-image时,并不会加载图片,而会构建样式规则树
  • 加载JavaScript,执行JavaScript代码,如果代码中有创建img元素之类,会添加到DOM树中;如查有添加background-image规则,将会添加到样式规则树中
  • DOM树和样式规则匹配时构建渲染树,如果DOM树节点匹配到样式规则中的backgorund-image,则会加载背景图片
  • 计算元素(图片)位置进行布局
  • 开始渲染图片,浏览器将呈现渲染出来的图片

Web页面中不是所有的图片都会加载和渲染!

可以归纳为:

  • <img><picture>和设置background-image的元素遇到display:none时,图片会加载,但不会渲染。
  • <img><picture>和设置background-image的元素祖先元素设置display:none时,background-image不会渲染也不会加载,而img和picture引入的图片不会渲染但会加载
  • <img><picture>和background-image引入相同路径相同图片文件名时,图片只会加载一次
  • 样式文件中background-image引入的图片,如果匹配不到DOM元素,图片不会加载
  • 伪类引入的background-image,比如:hover,只有当伪类被触发时,图片才会加载

原子化CSS

原子化 CSS 是一种将样式分解为最小化、独立的单一功能类名的 CSS 设计方法。每个类名通常只定义一个特定样式(例如设置颜色、边距、字体大小等),然后在 HTML 中通过组合这些类来构建界面。Tailwind CSS 是这种方法的代表框架之一。

原子化 CSS 的核心理念

原子化 CSS 旨在通过拆分样式最小化样式单元来避免传统样式表中的复杂性问题,并通过小而精确的类名提供了更高的灵活性和复用性。

传统的样式表可能会写出:

/* 传统 CSS */
.button {
    background-color: blue;
    padding: 10px;
    border-radius: 5px;
}

而原子化 CSS 则会分解为单一功能类:

/* 原子化 CSS */
.bg-blue { background-color: blue; }
.p-10 { padding: 10px; }
.rounded-5 { border-radius: 5px; }

HTML 中组合使用这些类:

<button class="bg-blue p-10 rounded-5">按钮</button>

原子化 CSS 的优势

  1. 更高的复用性:每个类都只包含一个样式,可以在多个组件或页面中复用,减少重复代码。
  2. 更高的灵活性:由于每个类代表一个特定样式,开发者可以自由组合这些类来实现各种效果,无需频繁编写新样式。
  3. 降低样式冲突:原子化 CSS 避免了命名空间冲突的问题,不需要担心不同组件之间的样式覆盖,因为每个类只包含一个特定的功能,不依赖上下文。
  4. 更快速的构建和样式更新:在构建时无需重新定义类名,开发者可以直接在 HTML 中组合样式类,使得开发更高效。

原子化 CSS 的不足

  1. 可读性差:大量短小的类名堆积在一起,可能会降低 HTML 的可读性,尤其是对于不熟悉代码的团队成员。
  2. 依赖 HTML 类名:大量的样式依赖于 HTML 的类名,导致 HTML 和 CSS 之间的分离不再明显,这对代码的结构化有一定影响。
  3. 学习曲线:原子化 CSS 需要开发者熟悉大量的短小类名和命名规则,例如 Tailwind CSS 的命名规则,可能对新手来说有一定的学习难度。

常见的原子化 CSS 框架

Tailwind CSS:最流行的原子化 CSS 框架,提供了大量的原子类,可以直接用于构建复杂的布局和样式。 Tachyons:类似于 Tailwind,提供了小而独立的样式类,支持快速原型和构建。

原子化 CSS 的应用场景

快速原型设计:可以快速迭代页面,不需要定义大量的样式。 小型项目:项目简单、页面少的情况下,原子化 CSS 可以大大提升开发速度。 组件库:在构建组件库时,可以使用原子类创建灵活、可组合的组件。

PostCSS

PostCSS 是一个基于 Node.js 的工具,用于处理 CSS 文件。它本质上是一个 CSS 解析器和转换器,通过插件机制,可以在构建过程中对 CSS 进行各种优化和扩展。

主要作用和功能

  1. CSS 预处理: PostCSS 可以用作 CSS 预处理器,支持嵌套规则、变量、混合等功能,类似于 Sass 或 LESS。通过插件,如 postcss-nested(支持嵌套)和 postcss-simple-vars(支持变量),可以在 CSS 中使用这些高级功能。

  2. 自动添加浏览器前缀: PostCSS 可以自动为 CSS 属性添加浏览器前缀,以确保兼容性。插件 Autoprefixer 是最常用的插件之一,它基于 Can I Use 数据库来判断需要添加哪些前缀,从而减少手动添加前缀的繁琐操作。

  3. 优化和压缩: PostCSS 还可以用于优化和压缩 CSS 代码,减少文件大小。通过插件,如 cssnano,可以自动去除不必要的空格、注释,并合并相同的选择器规则,生成更小的 CSS 文件。

  4. 未来 CSS 功能的支持: PostCSS 通过插件可以提前使用一些未来 CSS 规范中的功能,即使这些功能还未被广泛支持。例如,postcss-preset-env 插件允许开发者使用未来的 CSS 语法,然后根据目标浏览器的支持情况自动进行相应的转换。

  5. CSS Linting: PostCSS 可以用于代码风格的检查和格式化。通过插件,如 stylelint,可以按照团队的编码规范自动检测和修正 CSS 中的不合规写法。

  6. 自定义插件: PostCSS 的强大之处在于其灵活的插件机制,开发者可以编写自己的插件来实现特定的 CSS 转换需求。例如,处理特定的公司风格指南、动态生成样式等。

PostCSS 的工作流程

  1. 解析:首先,PostCSS 将 CSS 源代码解析为抽象语法树(AST)。
  2. 转换:然后,PostCSS 会通过插件对 AST 进行各种转换。
  3. 生成:最后,PostCSS 将转换后的 AST 重新生成 CSS 代码。

使用 PostCSS 自动添加浏览器前缀的示例:

// 安装 PostCSS 和 Autoprefixer
// npm install postcss autoprefixer

const postcss = require('postcss');
const autoprefixer = require('autoprefixer');

const css = `
  .example {
    display: flex;
    transition: transform 1s;
  }
`;

postcss([autoprefixer])
  .process(css, { from: undefined })
  .then(result => {
    console.log(result.css);
  });