本文内容来自 sbcoco B站视频分享

字体相关

1. 衬线字体和非线字体的区别

衬线字体与非衬线字体区别
  • 通过 font-family:serif 设置衬线字体

  • 通过 font-family: sans-serif 设置非衬线字体

  • 测试:

    • <div style="font-family: serif">N</div>
      <div style="font-family: sans-serif">N</div>
      
    • 效果:image-20230108012125094

为什么同样的 font-family 值的设置,在不同设备上的显示字体不同呢 ?

答:首先在不同设备上有不同的字体集,以上面的 serif 和 sans-serif 为例。其实这两个值并不是设置的某个指定的字体,而是代指的是电脑的本地字体中 所有衬线字体中优先级最高的那个字体所有非衬线字体中优先级最高的那个字体。其次,web页面的 lang、charset 和 浏览器设置都会对默认值字体产生影响。所以,这样就是同样的字体设置为什么在不同设备上显示不同。通常是通过网络字体来解决这个问题。

2. 为什么设置 font-weight 值为一些数值时没有加粗效果?

首先我们直到常见的 字重 大致有 9 种,对应如下描述

  • value name
    100 Thin
    200 Extra Light (Ultra Light)
    300 Light
    400 Regular (Normal、Book、Roman)
    500 Medium
    600 Semi Bold (Demi Bold)
    700 Bold
    800 Extra Bold (Ultra Bold)
    900 Black (Heavy)
  • 但是,文字加粗取决与当前字体的 字重 的数量,不同字体 有不同的 字重数量。很少有字体实现了上面九种 字重, 通常来说,每种字体必备两种 字重 —— 400(normal)、700(bold) 。所以,如果设置的值并没有与之相等的 字重, 则不生效。

选则器相关

1. 如何让下面代码中的 background: red 生效 ?

<style>
    body > .foo {
        background: #000;
    }
    .foo {
        background: red;
    }
</style>

<div class="foo"></div>
  • 我们知道 css 选择器有不同的优先级,大致通过数字表示有如下几种表示:

    • 选择器 数值
      !important 10000
      内联样式 1000
      ID 选择器 100
      类选择器、伪类选择器、属性选择器 10
      元素选择器、伪元素选择题 1
    • 关于优先级权威介绍:MDN优先级

  • computerValue(body > .foo) = 11; computerValue(.foo) = 1; 所以,想要让 background: red 样式生效,我们需要将其 选择器优先级提升,大致有如下方法。

    • 第一种:直接为 div 在设置一个类名

      • <style>
            .foo.bar {
                background: red;
            }
        </style>
        <div class="foo bar"></div>
        
      • 这种方法会导致我们新添加一个类名,不太优雅。

    • 第二种: 通过自我叠加,提升选择器权重

      • <style>
            .foo.foo {
                background: red;
            }
        </style>
        <div class="foo"></div>
        
      • 此时 computerValue(.foo.foo) = 20 20 > 11,所以,.foo.foo 选择器样式生效。这样的方式优雅,且不用添加多余的类名。

    • 第三种: 叠加属性,提升权重

      • <style>
            .foo[class] {
                background: red;
            }
        </style>
        <div class="foo"></div>
        
      • 此时 computerValue(.foo[class]) = 20 20 > 11,所以,.foo[class] 选择器样式生效。有点同上。

颜色相关

1. 理解 currentColor 与 color

对于 color,通常我们都用它设置字体颜色。但是,设置字体颜色其实只是 它的功能之一。它同时设置了如下属性的颜色值:

  • <style>
        .g-color {
            color: #f00;
            border: 1px solid;
            box-shadow: 2px 2px 10px 2px;
            text-shadow: 2px 2px 5px;
        }
    </style>
    <div class="g-color"></div>
    
    • 效果如图:image-20230108020737444
    • 可以看到,上面代码并没有设置 border、box-shadow 和 text-shadow 的颜色,它们的颜色取自 color 的值。
    • mdn 上描述color属性:”color 属性设置前景色以及文本装饰,并设置 currentColor 值。“

通过mdn的描述我们可以知道 currentColor = color, 所以, border: 1px solid === border: 1px solid currentColor box-shadow: 30px 0 === box-shadow: 30px 0 currentColor

color的这个特新和 box-shadow 结合,设计出一朵云

  • <style>
    
        html,
        body {
            width: 100%;
            height: 100%;
            display: flex;
            background: #bbb;
        }
    
        div {
            margin: auto;
            width: 60px;
            height: 60px;
            border-radius: 50%;
            color: #fff;
            background: currentColor;
        }
    
        div {
            box-shadow: 30px 0, 60px 0, 85px 0, 20px -25px, 60px -25px;
        }
    </style>
    <div></div>
    
  • 效果图:image-20230108022435135

计算值相关

1. inherit 与 unset

1.1 position相关的面试题

每个 CSS 属性的定义的概述都指出这个属性是:

  • 默认继承的( inherited: yes)
  • 还是默认不继承(inherited: no)

以position属性为例,mdn 上属性概述为:image-20230108022941310

其实,每个属性都有可以设置 inherit、initial 和 unset 这三个值。

同样的以position为例,它总共的值可以有八个:

  • value 作用
    inherit 继承父元素的值
    initial 设置为浏览器默认值
    unset 如果有继承自父元素的值,则设置成继承值。如果没有继承值,就设置成浏览器默认值
    static 这个值是默认值,不会脱离标准流,并且top、bottom、right、left和z-index 对其没有效果
    relative 并不会移除标准流,相对于标准流位置,进行布局移动, 当 z-index 值不为 auto 是创建一个堆叠上下文。relative这个值对 table-*-group、table-row、table-column、table-cell、table-caption 元素无效
    absolute 脱离标准流。它相对于任何设置 position 属性的最近祖先元素,进行定位。如果没有,它会放在最初的 Content Block种。最终布局由 top、bottom、left、right 决定。 当 z-index 不为 auto 时,创建一个堆叠上下文。并且 绝对定位的margin不会与其他边距折叠。正常情况下是相对于 设置了position属性的祖先元素。但是,如果在 设置了position属性的祖先元素之前的元素,如下属性不为none 则相对于该元素定位——transform、perspective、filter 或 will-change: transform 或 设置了background-filter 或 contain: paint | layout | content | strict 或 transform-style: preserve-3d。
    fixed 脱离标准流,正常情况下是相对于当前视口定位布局。但是,如果它的祖先元素种如下属性中存在不为 none 的属性,则会相对于该祖先进行布局——transform、perspective、filter 或 will-change: transform 或 设置了background-filter 或 contain: paint | layout | content | strict 或 transform-style: preserve-3d。这个值会创建一个新的堆叠上下文。
    sticky 根据文档的正常流定位,让后根据 最近的滚动组件 和 最近的块级祖先。并不会影响其他元素的位置。它粘连到最近的有滚动机制的祖先元素即overflow值为 hidden、scroll、auto、overlay。注意:并不是相对于最近能滚动的祖先,而是相对于设置了 overflow 指定四个属性之一的祖先元素。 这个值会创建一个 堆叠上下文。
  • MDN权威讲解

1.2 inherit 属性

我们知道inherit 属性可以强制某些属性,继承父元素的值。通过这个特性我们实现以下,图片倒影的效果。

  • <style>
      .g-reflect {
        position: relative;
        width: 200px;
        height: 200px;
        background-image: url("https://encrypted-tbn0.gstatic.com/images?
    q=tbn:ANd9GcQ8M9ItO3afMFUfXu2qcdmFgZL6Cb25n16FS_pPbU8z&s");
        background-repeat: no-repeat;
        background-size: contain;
      }
      .g-reflect::before {
        content: "";
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        bottom: -100%;
        transform: rotateX(180deg);
        background-image: inherit; /* 强制继承父元素的属性值 */
        background-repeat: inherit;
        background-size: inherit;
      }
    </style>
    <div class="g-reflect"></div>
    
    • 效果图:image-20230108032628759
1.3 unset 属性

当某个属性值设置为 unset 时

  • 先判断这个属性本来有从父级继承的值(这个属性默认可以继承,并且父级有定义),则将该属性设置为继承的值。
  • 如果没有继承父级样式,则将该属性重新设置为初始值。

应用场景1:

  • * {
        box-sizing: border-box;
    }
    
  • 当我们不想上面的规则应用在某个元素上,我们可以通过 unset 将其设置为默认值

    box-sizing: unset; === box-sizing: content-box

应用场景2:

  • 当我们有个banner,并且它有左右切换的按钮。我们知道,两个切换按钮的样式基本是相同的,所以通常会用并集选则器。

    • <style>
          body,
          html {
              width: 100%;
              height: 100%;
              display: flex;
              font-family: "Space Mono", monospace;
          }
          div {
              position: relative;
              margin: auto;
              width: 300px;
              height: 300px;
              border: 2px solid #000;
          }
          div::before,
          div::after {
              content: "<";
              position: absolute;
              top: 130px;
              left: 20px;
              width: 40px;
              height: 40px;
              line-height: 40px;
              border-radius: 50%;
              border: 1px solid #999;
              text-align: center;
              cursor: pointer;
          }
      
          div::after {
              content: ">";
              right: 20px;
              left: unset;  /* unset 将其设置为默认值 0, 因为left 属性不是默认继承, 这里用initial也行 */
          }
      </style>
      <div></div>
      
    • 效果图:image-20230108034219871

各种失效

1. fixed 和 absolute 失效

fixed 和 absolute 当遇到最近祖先元素设置如下属性时——transform、perspective、filter不为none 或 will-change: transform 或 设置了background-filter 或 contain: paint | layout | content | strict 或 transform-style: preserve-3d,会直接相对于这个祖先元素定位。

根本原因:堆叠上下文(Stacking Context) 堆叠上下文时 HTML 元素的三维概念,这些 HTML 在同一条假象的相对于面向视图或者网页的用户的 z 轴上延伸,HTML 元素依据其自身属性按照优先级顺序占用层叠上下文的空间。生成了堆叠上下文(Stacking Context)的元素会影响该元素的层叠关系与定位关系。

2. 3D 坍缩

指定是原本3D的图像被显示成 2D 了。能够导致3D坍塌的属性:

  • 父容器加:filter: contrast(1);
  • 3d元素加:mix-blend-mode: color;

根本原因:当我们使用了CSS混合模式(滤镜)的时候,层叠上下文会重新堆这个使用了混合模式的元素的根结点处创建一个独立的渲染平面,但是这个渲染平面是不支持 perserve-3d 的, 所以,我们看到是一个2D的平面效果。

Chrome调出层级线:Layers => Rendering => Layer borders

  • Chrome中 黄色代表 复合层(GraphicsLayer),当复合层里面的内容有更新的时候,Chrome 内核只会渲染该复合层内部元素,达到性能优化的目的。
  • 蓝色网格表示瓦片(tile), 可以把它当作层的单元,Chrome 内核可以将他们作为一个大层的部分上传给 GPU 进行渲染加速。
  • image-20230108041225866

知识拓展:mix-blend-mode not interacting with all elements behind as expected. 探究 CSS 混合模式\滤镜导致 CSS 3D 失效问题

3. 100vh 失效问题

我们知道的是

  • 1vw = 1/100 * viewport width
  • 1vh = 1/100 * viewport height

但是移动端 Chrome 浏览器中,100vh 会出现滚动条。

  • 根本原因:很多浏览器会把地址栏的高度计算在内。这回导致一系列预料之外的BUG,在移动端慎用。

  • 解决方法

    • 使用 100% 来解决,给body设置 width: 100%; height: 100%;
    • 新的查询单位 1cqw = 容器宽度的1%; 1cqh = 容器高度的1%;

开发中的注意事项

1. 所有元素都有 ::before::after 伪元素吗 ?

答:并不是所有元素都有。无法将这两个伪元素添加到 文本输入框和图片,因为这些元素都是 替换元素。”Rendering section“ 这些标签不能设置这两个伪元素 audio、canvas、embed、iframe、img、input、object、video根本原因,替换元素会将替换元素的所有内容,包括::before ::after属性。值得注意的是,img 元素并不总是替换元素,当 src 指定的图片无法加载时,Chrome 和 Firefox 中可以将 ::before ::after 添加到 img 上。

利用img src失效时不是替换元素的特性,我们通常用来实现,将 alt 属性值 和 兜底图片 用 ::before ::after 设置。

  • <style>
        img.error {
            position: relative;
        }
        img.error::before {
            content: "";
            /** 定位代码 **/
            background: url(error-default.png);
        }
        img.error::after {
            content: attr(alt);
            /** 定位代码 **/
        }
    </style>
    <img src="image.png" onerror="this.classList.add('error');" alt="Alt Info">
    
  • 效果图:image-20230108043542766

2. 父容器设置了 overflow: hidden, 任何超出父元素的子元素都不可见吗?

答:是否定的,当遇到 position: fixed | absolute; 且其相对于其他祖先元素定位,则不会消失。如果想要 position: absolute 的父容器的 overflow: hidden 生效,要么 加 position: relative, 要么让父容器生成也给 Stacking Contextposition: fixed; 要让父容器的 overflow: hidden; 生效,让父容器生成一个 Stacking Context.

3. 除了 overflow: hidden, CSS 还能如何让移除容器的元素隐藏呢 ?

答:

  • 通过 clip-path 进行裁剪,范围外的元素自动隐藏。
  • contain: paint 进行裁剪,其目的是加快页面渲染,在非必要区域,不渲染元素。因此,如果元素不在屏幕上或以其他方式设定为不可以见,则其后代不可见不被渲染。也就是说,此元素的子元素不会再此元素的边界之外被展示。
  • 扩展阅读:如何不使用 overflow: hidden 实现 overflow: hidden?

4. 文字超出省略

4.1 单行省略
.single-line {
    width: 200px;
    white-space: nowrap; /* 设置不换行 */
    overflow: hidden; /* 隐藏超出部分 */
    text-overflow: ellipsis; /* 显示省略号 */
}
4.2 多行省略
.multiple-line {
    width: 200px;
    white-space: normal;
    overflow : hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;	/* 设置为两行 */
    -webkit-box-orient: vertical;
}
4.3 如果省略的是前面的内容,保留后面的内容怎么办呢 ?
{
    width: 200px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    direction: rtl;

}

direction: 设置文本排列的方向。rtl 表示从右到左,ltr 表示从左到右。

另外两个与排列顺序相关的属性:

  • writing-mode: 定义文本水平或垂直排布以及再块级元素中文本的行进方向。
  • unicode-bidi: 它与direction 非常类似,连个会经常一起出现。在现代计算机应用中,最长用来处理文字的算法是 Unicode 双向算法。而 unicode-bidi 这属性是用来重写这个算法的。

扩展阅读:CSS 世界中的方位与顺序

如何学习CSS