跳转至

CSS

1028 个字 84 行代码 预计阅读时间 4 分钟

Abstract

CSS 相关神奇妙妙用法记录。

参考:

Selectors

  • basic selectors
    • type: div { }选择全部 <div> 元素
    • class: .class { }选择全部 <... class="class"> 元素
    • id: #id { }选择全部 <... id="id"> 元素
    • universal: * { }选择全部元素
  • attribute selectors
    • div[title] { } 选择具有 title 属性的全部 <div> 元素
    • div[title="value"] { } 选择具有 title="value" 属性的全部 <div> 元素
    • div[title~="value"] { } 选择具有 title 属性值包含 value 的全部 <div> 元素
    • div[lang|="zh"] { } 选择 title="zh"title="zh-CN"<div> 元素
    • 根据 substring 匹配(不按空格分割)
      • [attr^=value] { } 开头,[attr$=value] { } 结尾,[attr*=value] { } 中间包含 value
  • selector lists
    • 逗号分隔,如 div, p { } 选择全部 <div><p> 元素
    • 其中有一个非法则整条规则忽略
  • combinators 组合用法
    • 空格分隔:div p { } 选择所有 <div> 元素下的 <p> 元素(descendant)
    • > 分隔:div > p { } 选择所有 <div> 元素下的直接子元素 <p>(child)
    • + 分隔:div + p { } 选择紧接在 <div> 元素后的 <p> 元素(next-sibling)
      • 反过来选择后面有紧接着的 <p> 元素的 <div> 元素:div:has(+ p) { }
    • ~ 分隔:div ~ p { } 选择所有在 <div> 元素之后的 <p> 元素(subsequent-sibling)
    • 不分隔:叠加选择所有条件,div.class#id[attr] { } -> <div class="class" id="id" attr="value">
  • pseudo-classes 伪类
    • li:first-child { } 选择每个作为第一个子元素的 <li> 元素
      • 推荐使用 div *:first-child { } 代替 div :first-child { } 防止混淆
    • :hover { } 悬停状态
  • pseudo-elements 伪元素
    • p::first-line { } 选择每个 <p> 元素的第一行
    • p::before { content: "Note: "; } 在每个 <p> 元素前插入内容
    • p::after { content: " (end)"; } 在每个 <p> 元素后插入内容
    • ::selection 选择被用户选中的内容
    • ::placeholder 选择输入框中的 placeholder 内容
    • ::marker 选择列表项的标记符号

嵌套选择器

.parent {
    <parent styles>
    .child {
        <child styles>
    }
}

等价于

.parent {
    <parent styles>
}
.parent .child {
    <child styles>
}

在子选择器中加入 & 表示父选择器插入的位置:

.parent {
    <parent styles>
    &:hover {
        <parent hover styles>
    }
    .child & & {
        <styles>
    }
}

等价于

.parent {
    <parent styles>
}
.parent:hover {
    <parent hover styles>
}
.child .parent .parent {
    <styles>
}

其他伪类

  • :active 激活状态(鼠标按下)
  • :visited 访问过的链接
  • :first-child 第一个子元素,:last-child 最后一个子元素
  • :nth-child(n) n 个子元素,:nth-last-child(n) 倒数第 n 个子元素
    • n 可以是数字odd(奇数even(偶数an+ba b 是整数,a>=0)
    • 例如 :nth-child(3n+1) 表示第 1、4、7、10... 个子元素
    • :nth-last-of-type(n):nth-of-type(n) 类似
  • :first-of-type 第一个指定类型的子元素,:last-of-type 最后一个指定类型的子元素
  • :has(...) 选择包含指定子元素的元素(... relative selector,即 + p / > p 等)
    • :has(a, b) 表示 or:has(a):has(b) 表示 and
  • :is(a, b) a b 任意一个,用于简写,可以生成一系列选择器
    • :is(a, b) :is(c, d) 等价于 a c, a d, b c, b d
  • :where(...) 类似 :is(...),但不会影响优先级
    :is(section.is-style, footer.is-style) a { ... }
    :where(section.where-style, footer.where-style) a { ... }
    footer a { ... } /* 会覆盖 where 的规则,但不覆盖 is 的规则 */
    
  • :not(...) 选择不匹配指定 rule 的元素
  • :root 选择文档的根元素,通常是 <html> 元素,常用于定义全局变量
    :root {
        --main-color: red; /* 其他地方可以使用 var(--main-color) 来引用 */
    }
    

其他神奇用法

响应式设计

即根据设备的屏幕大小来调整样式。可以使用 @media 查询规则来实现:

@media screen and (min-width: 960px) { /* 960px 宽及以上的屏幕应用下面的样式 */
  html {
    font-size: 137.5%;
  }
}
@media screen and (max-width: 600px) {
    ... /* 600px 宽及以下的屏幕应用下面的样式 */
}

counter

通过 css 计数器可以实现标题的自动编号:

  • counter-reset:创建并初始化一个计数器
  • counter-increment:增加计数器的值
  • counter():获取计数器的当前值
h1 {
  counter-reset: h2; /* 遇到 h1 时重置 h2 计数器 */
}
h2 {
  counter-reset: h3; /* 遇到 h2 时重置 h3 计数器 */
}
h2::before {
  counter-increment: h2; /* 遇到 h2 时增加 h2 计数器 */
  content: counter(h2);  /* 获取 h2 计数器的值并在标题前显示 */
  margin-right: 0.8rem;
}
h3::before {
  counter-increment: h3; /* 遇到 h3 时增加 h3 计数器 */
  content: counter(h2) "." counter(h3); /* 连接多个计数器 */
  margin-right: 0.8rem;
}

优先级与 important

.selector.class {
    color: red;
}
.selector {
    color: blue;
}

即使 .selector 在后面定义,.selector.class 也会生效,因为它的限制更多优先级更高。

在通过自定义 css 覆盖原有样式时,需要注意这种情况,一般需要把 selector 写得和原有样式一样或更具体才会覆盖。或者在属性后面加上 !important 强制覆盖:

关于字体

一般 font-family 写法:

font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";

自定义 font-family 时注意 fallback 机制,最好把常见的字体都列出来,最后加上通用字体族(如 sans-serif、serif、monospace

自定义字体:

@font-face {
    font-family: "Font Name";  /* 后续 font-family 中可以使用这个名字 */
    src: url("path/to/font.woff2") format("woff2"),
         url("path/to/font.woff") format("woff"); /* 可以提供多种格式以兼容不同浏览器 */
    font-weight: 400;    /* 支持的 weight */
    font-style: normal;  /* 支持的 style */
}

为了防止加载大型字体文件时卡住,可以将字体文件拆分为多个子集(subset,每个子集只包含部分字符,然后根据需要加载对应的子集:

@font-face {
    font-family: "Font Name";
    src: url("path/to/font-subset1.woff2") format("woff2");
    unicode-range: ...;
}
@font-face {
    font-family: "Font Name";
    src: url("path/to/font-subset2.woff2") format("woff2");
    unicode-range: ...;
}

可以利用 KonghaYao/cn-font-split 等工具来拆分字体文件。