普通视图

发现新文章,点击刷新页面。
今天 — 2025年11月23日掘金 前端

CSS 属性值 initial、unset 和 revert 的解析

2025年11月22日 22:17

大家好,我是前端架构师,关注微信公众号【程序员大卫】,免费领取前端最新面试资料。

背景

在 CSS 中,管理属性值和继承行为是创建健壮、可维护样式的基础。除了常见的具体数值(如 16px#333)或通用值(如 inherit)之外,CSS 还提供了一些特殊的关键字,它们能重置或恢复属性值到其“默认”或前一个状态。

其中,initialunsetrevert 是三个功能强大且容易混淆的关键字。理解它们的区别,能帮助您更好地控制样式,尤其是在处理第三方组件或大型应用中的样式冲突时。

核心区别一览

关键字 作用 行为细节 适用场景
initial 重置为初始值 将属性重置为其在 CSS 规范中定义的初始值(就像该属性从未被设置过一样)。 确保属性值是浏览器默认的“出厂设置”,不考虑继承。
unset 重置为未设置值 如果该属性是可继承的,则表现为 inherit(继承父元素的值)。
如果该属性是不可继承的,则表现为 initial
恢复属性到其自然的(默认的)继承行为。
revert 重置为上一个级联值 将属性重置为用户代理样式表(浏览器默认样式)、用户样式表作者样式表中应用过的上一个值。它会撤销当前样式块的更改,恢复到级联链中更早的值。 撤销对属性的特定覆盖,恢复到浏览器或用户定义的样式,常用于恢复浏览器默认样式。

关键字详解与示例

为了更好地理解,我们主要关注 color(可继承)和 border(不可继承)这两个属性。

1. initial:回到起点

initial 总是将属性值设置为 CSS 规范中定义的初始值。这个值是固定的,并且与该元素是否继承了父元素的值无关

示例:

/* 初始设置 */
div {
  color: blue;
  border: 1px solid black;
}

/* 应用 initial */
.initial-demo {
  /* color 是可继承属性,但 initial 强制设为初始值 (通常是 black) */
  color: initial;
  /* border 是不可继承属性,initial 强制设为初始值 (none) */
  border: initial;
}
元素 父元素 div 的样式 .initial-demo 的样式 最终值
color blue initial black (初始值)
border 1px solid black initial none (初始值)

2. unset:恢复自然状态

unset 是一个“智能”的重置。它根据属性的可继承性来决定行为:

  • 可继承属性: 表现为 inherit
  • 不可继承属性: 表现为 initial

示例:

/* 初始设置 */
div {
  color: blue;
  border: 1px solid black;
}

/* 应用 unset */
.unset-demo {
  /* color 是可继承属性,表现为 inherit */
  color: unset;
  /* border 是不可继承属性,表现为 initial */
  border: unset;
}
元素 父元素 div 的样式 .unset-demo 的样式 最终值
color blue unset \rightarrow inherit blue (继承自父元素)
border 1px solid black unset \rightarrow initial none (初始值)

3. revert:撤销作者样式

revert 是最独特的。它沿着 CSS 级联(Cascading)链向上查找,恢复到上一个被应用的值。它本质上是撤销了当前样式表中的属性定义,恢复到:

  1. 用户样式(如果用户设置了)。
  2. 浏览器默认样式(用户代理样式表)。
  3. 如果以上都没有,则恢复到 unset 的行为。

它主要用于恢复浏览器默认样式,例如,您不想让某个 <h1> 标签应用您的全局字体样式,希望它用回浏览器默认的粗体大字。

示例:

假设浏览器默认样式是:h1 { font-weight: bold; }

/* 作者样式表 (您的代码) */
h1 {
  /* 覆盖了浏览器默认样式 */
  font-weight: normal; 
}

.revert-demo {
  /* 撤销了上方的 font-weight: normal; */
  font-weight: revert;
}

在这个例子中,.revert-demo 元素会将 font-weight 恢复到 浏览器默认值 (bold),因为它撤销了作者样式表中的 normal 声明。

✅ 总结与应用建议

关键字 记忆点 应用场景
initial “绝对初始” 确保属性值是其 CSS 规范定义的原始默认值,不考虑上下文。
unset “智能重置” 恢复属性的自然继承行为(可继承则 inherit,不可继承则 initial)。
revert “撤销” 撤销作者样式,恢复到浏览器默认或用户样式。常用于希望保持浏览器默认外观的元素。

什么时候用哪个?

  • 如果您想确保一个属性值是固定的、明确的 CSS 初始值,使用 initial
  • 如果您想让一个属性遵循其固有的继承规则(即,可继承的就继承,不可继承的就使用初始值),使用 unset
  • 如果您想撤销您的样式对某个元素默认外观的覆盖,恢复到浏览器提供的默认样式,使用 revert
昨天 — 2025年11月22日掘金 前端

把原型链画成地铁图:坐 3 站路就能看懂 JS 的“继承”怎么跑

2025年11月22日 11:43
前言 在 JavaScript 里,“原型”这个词听起来高大上,其实就是一个“默认备胎”:当对象自己找不到属性时,就沿着原型这条暗道去“亲戚家”借。没有类、没有蓝图,仅靠这条备胎链,就能把公共方法层层

多语言的爱意告白

2025年11月21日 22:35

这张图片以黑色为背景,中央突出显示白色的 “小鱼” 字样,周围环绕着多语言的 “我喜欢你”“我爱你”“和我交往吧”“在一起” 等表达爱慕与交往意愿的文字,文字颜色多样,营造出一种充满爱意的视觉氛围。

image.png

import pygame
import random
import sys
import math
import os

# 初始化pygame
pygame.init()
# 窗口设置
width, height = 1000, 800
screen = pygame.display.set_mode((width, height))

# 改进的字体设置函数
def get_font(size):
    font_paths = [
        "C:/Windows/Fonts/simhei.ttf", "C:/Windows/Fonts/msyh.ttc", "C:/Windows/Fonts/simsun.ttc",
        "/System/Library/Fonts/PingFang.ttc", "/System/Library/Fonts/Arial.ttf",
        "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf", "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
    ]
    for font_path in font_paths:
        if os.path.exists(font_path):
            try:
                return pygame.font.Font(font_path, size)
            except:
                continue
    try:
        return pygame.font.SysFont("Arial", size)
    except:
        return pygame.font.Font(None, size)

# 创建字体对象(弹幕字体稍大,保证清晰)
font = get_font(20)
title_font = get_font(36)
danmu_font = get_font(20)  # 弹幕字体大小适中
# 新增名字专用字体(更大更醒目)
name_font = get_font(60)  # 字体大小60,突出显示

# 多语言“我爱你”文本库(原内容完全保留)
love_texts = [
    "Mola le offi la tee", "mihai amestiah sind", "milvini un ne seibesc", "Le sakam", "Mlohuujam",
    "Te sakam", "chami dài e n ki n M", "Te dua", "Té okabescu", "Tá grá agam duit", "Kocham Ci",
    "Saya cintakan kamu", "我爱你", "Te ambesc", "Mahal kita", "Jeg elsker deg", "Mihaji té", "Meng sona",
    "Szerethékda", "Jag Tjukin", "Teja amerhi", "L kertesi skarji", "joga nem lesen", "nyolyomni",
    "I love you", "Je t'aime", "Ich liebe dich", "Ti amo", "Te amo", "あいしてる",
    "我爱你", "我中意你", "我爱侬", "我欢喜你", "我爱你", "我愛你", "勾买蒙", "额爱你","我待见你"
    "恩欢喜你", "我爱列", "Ik hou van je", "Saya cintakan mu", "Ti amo", "Jeg elsker dig",
    "Aku cinta padamu", "Saya cinta kamu", "Ljubim te", "俺喜欢", "我稀罕你", "俺稀罕你","阿秋拉嘎"
]

# 爱心坐标生成(原逻辑完全保留,未做任何修改)
love_points = []
for t in range(1000):
    theta = t / 1000 * 2 * math.pi
    x = 15 * (pow(math.sin(theta), 3))
    y = 10 * math.cos(theta) - 5 * math.cos(2 * theta) - 2 * math.cos(3 * theta) - math.cos(4 * theta)
    x = x * 18 + width // 2
    y = -y * 18 + height // 2
    love_points.append((int(x), int(y)))

# 文字对象列表(原逻辑完全保留,未做任何修改)
text_objects = []
colors = [(255, 182, 193), (255, 105, 180), (255, 20, 147),(218,112,214)]
for i, text in enumerate(love_texts):
    color = colors[i % len(colors)]
    try:
        if not isinstance(text, str):
            text = str(text)
        text_surface = font.render(text, True, color)
    except Exception as e:
        print(f"渲染失败 '{text}': {e}")
        text_surface = font.render("Love", True, color)
    idx = random.randint(0, len(love_points) - 1)
    x, y = love_points[idx]
    speed_x = random.uniform(-0.15, 0.15)
    speed_y = random.uniform(-0.15, 0.15)
    text_objects.append({
        "surface": text_surface, "text": text, "x": x, "y": y,
        "speed_x": speed_x, "speed_y": speed_y, "target_idx": idx, "color": color
    })

# ===================== 弹幕功能(按要求优化)=====================
# 弹幕仅保留3条中文文案
danmu_texts = ["我爱你", "在一起", "我喜欢你","和我交往吧","阿秋拉嘎"]
# 弹幕仅一种粉色(鲜艳且协调)
danmu_color = (255,239,213)  # 热粉色

# 弹幕对象类(速度加快,淡入淡出节奏紧凑)
class Danmu:
    def __init__(self):
        self.text = random.choice(danmu_texts)
        self.font_size = random.randint(18, 24)  # 字体大小随机
        self.font = get_font(self.font_size)
        self.color = danmu_color
        # 随机位置(全屏分布,支持左右/上下双向运动)
        if random.random() > 0.5:
            # 从左向右运动
            self.x = random.randint(-100, -20)
            self.y = random.randint(50, height - 50)
            self.speed_x = random.uniform(3, 4)  # 加快水平速度
            self.speed_y = random.uniform(-0.5, 0.5)  # 轻微垂直偏移
        else:
            # 从右向左运动
            self.x = random.randint(width + 20, width + 100)
            self.y = random.randint(50, height - 50)
            self.speed_x = random.uniform(-5, -3)  # 加快水平速度
            self.speed_y = random.uniform(-0.5, 0.5)  # 轻微垂直偏移
        self.alpha = 0  # 初始透明度为0
        self.life = random.randint(80, 150)  # 生命周期缩短(速度快对应短生命周期)
        self.life_count = 0
        self.surface = self._render_text()

    def _render_text(self):
        surf = self.font.render(self.text, True, self.color)
        surf.set_alpha(self.alpha)
        return surf

    def update(self):
        self.life_count += 1
        # 快速淡入(前20%生命周期完成淡入)
        if self.life_count < self.life * 0.2:
            self.alpha = min(255, self.alpha + 15)  # 加快淡入速度
        # 快速淡出(后30%生命周期完成淡出)
        elif self.life_count > self.life * 0.7:
            self.alpha = max(0, self.alpha - 10)  # 加快淡出速度
        # 更新透明度和位置(速度加快)
        self.surface.set_alpha(self.alpha)
        self.x += self.speed_x
        self.y += self.speed_y
        # 生命周期结束或超出屏幕则重置
        if self.life_count >= self.life or self.x < -200 or self.x > width + 200:
            self.__init__()

    def draw(self, screen):
        rect = self.surface.get_rect(center=(self.x, self.y))
        screen.blit(self.surface, rect)

# 初始化弹幕(初始30条,数量适中不遮挡爱心)
danmu_list = [Danmu() for _ in range(30)]
# 弹幕生成计时器(生成频率加快)
danmu_spawn_timer = 0
danmu_spawn_interval = 20  # 每20帧(约0.3秒)新增1条弹幕

# 原标题与说明文字(保留)
try:
    title_text = title_font.render("", True, (255, 255, 255))
except:
    title_text = title_font.render("I Love You + Pink Danmu", True, (255, 255, 255))
instruction_font = get_font(16)
instruction_text = instruction_font.render("按ESC键退出", True, (150, 150, 150))

# 生成居中显示的名字(白色,屏幕正中间)
name_text = name_font.render("小鱼", True, (255, 255, 255))  # 白色文字
# 计算名字居中坐标(屏幕正中心)
name_x = width // 2 - name_text.get_width() // 2
name_y = height // 2 - name_text.get_height() // 2

# 主循环(仅添加名字绘制,不改动原有内容)
clock = pygame.time.Clock()
running = True
while running:
    # 事件处理(原逻辑保留)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False

    # 黑色背景(原逻辑保留)
    screen.fill((0, 0, 0))

    # 绘制标题、说明文字(原逻辑保留)
    screen.blit(title_text, (width // 2 - title_text.get_width() // 2, 20))
    screen.blit(instruction_text, (width - instruction_text.get_width() - 10, height - 30))

    # 绘制爱心轨迹文字(原逻辑完全保留,未做任何修改)
    for obj in text_objects:
        text_rect = obj["surface"].get_rect(center=(obj["x"], obj["y"]))
        screen.blit(obj["surface"], text_rect)
        target_x, target_y = love_points[obj["target_idx"]]
        obj["x"] += (target_x - obj["x"]) * 0.02 + obj["speed_x"]
        obj["y"] += (target_y - obj["y"]) * 0.02 + obj["speed_y"]
        obj["target_idx"] = (obj["target_idx"] + 1) % len(love_points)
        if obj["x"] < 0 or obj["x"] > width:
            obj["speed_x"] *= -1
        if obj["y"] < 50 or obj["y"] > height - 50:
            obj["speed_y"] *= -1

    # ===================== 绘制居中名字(新增代码)=====================
    screen.blit(name_text, (name_x, name_y))  # 在屏幕正中间绘制白色名字

    # ===================== 弹幕更新与绘制(按要求优化)=====================
    # 加快弹幕生成频率
    danmu_spawn_timer += 1
    if danmu_spawn_timer >= danmu_spawn_interval:
        danmu_list.append(Danmu())
        danmu_spawn_timer = 0
        # 限制弹幕总数(最多50条,避免过度拥挤)
        if len(danmu_list) > 50:
            danmu_list.pop(0)

    # 更新并绘制所有弹幕(速度加快,粉色系,仅中文文案)
    for danmu in danmu_list:
        danmu.update()
        danmu.draw(screen)

    # 显示帧率(原逻辑保留)
    fps_text = font.render(f"FPS: {int(clock.get_fps())}", True, (100, 100, 100))
    screen.blit(fps_text, (10, height - 30))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()
❌
❌