@codady/normalize
Version:
@codady/normalize, A modern alternative to normalize.css, focused on typography, form usability, and cross-browser consistency.
487 lines (481 loc) • 14.9 kB
CSS
/**
* @codady/normalize
* Last modified: 2026-05-09 16:26:48
*
* Philosophy 设计理念:
* 1. Fix browser inconsistencies 修正浏览器默认差异
* 2. Provide a clean typography baseline 提供干净的排版基线
* 3. Improve form & media usability 优化表单与媒体元素体验
* 4. Stay layout-neutral 尽量不干涉具体布局
*/
/* ==================================================
Design Tokens — Typography
设计令牌:字体系统
================================================== */
/**
* Public Override Tokens(对外变量,可由用户覆盖)
* --------------------------------------------------
* These variables act as "entry points" for customization.
* They are intentionally left undefined or loosely defined,
* so users can override them without touching internal tokens.
*
* 这些变量是对外暴露的“覆盖入口”,
* 用户可以通过它们定制全局行为,而无需修改内部实现。
*
* --default-font-family
* → Base font family for the document
* → 页面默认字体族
*
* --default-mono-font-family
* → Base monospace font family for code elements
* → 代码元素默认等宽字体
*
* --default-tab-size
* → Tab character width in spaces
* → Tab 缩进宽度(空格数)
*
* --default-accent-color
* → Accent color for form controls (checkbox, radio, etc.)
* → 表单控件主题色(checkbox、radio 等)
*
* --default-border-color
* → Default border color used in elements like table
* → 默认边框颜色(如表格)
*
* --default-font-feature-settings
* → OpenType feature control (ligatures, numeric styles, etc.)
* → 控制 OpenType 排版特性(连字、数字样式等)
*
* --default-font-variation-settings
* → Variable font axis control
* → 控制可变字体轴参数
*/
/**
* Internal Tokens(内部变量,不建议直接修改)
* --------------------------------------------------
* These variables define the internal design system of @codady/normalize.
* They provide consistent fallback values and are used throughout the stylesheet.
*
* 这些变量属于内部实现,用于保证一致性和回退逻辑。
* 虽然可以覆盖,但通常不建议用户直接修改。
*
* --font-sans
* → Default sans-serif font stack
*
* --font-zh-sc / --font-zh-tc / --font-ja / --font-ar
* → Language-specific font stacks
*
* --font-emoji
* → Emoji fallback fonts
*
* --font-fallback
* → Final fallback (usually generic family)
*
* --font-mono
* → Monospace font stack
*
* --leading-tight / snug / compact / normal / relaxed / loose
* → Line-height scale for typography hierarchy
*/
@layer base {
:root,
:host {
/* ---------- Font Stacks 字体栈 ---------- */
/* UI & Latin interfaces 通用界面与拉丁字符 */
--font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
/* Simplified Chinese 简体中文 */
--font-zh-sc: "PingFang SC", "Microsoft YaHei", "Noto Sans SC", "Source Han Sans SC";
/* Traditional Chinese 繁体中文 */
--font-zh-tc: "PingFang TC", "Microsoft JhengHei", "Noto Sans TC", "Source Han Sans TC";
/* Japanese 日文 */
--font-ja: "Hiragino Sans", "Yu Gothic UI", Meiryo, "Noto Sans JP";
/* Arabic 阿拉伯语 */
--font-ar: Tahoma, "Geeza Pro", "Noto Naskh Arabic", "Noto Sans Arabic";
/* Emoji 表情符号 */
--font-emoji: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";
/* Fallback 兜底字体 */
--font-fallback: sans-serif;
/* Monospace 等宽字体 */
--font-mono: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
/* ---------- Line Heights 行高 ---------- */
/* Large headings use tighter line-height 大标题使用小值行高 */
--leading-tight: 1.2;
--leading-snug: 1.3;
--leading-compact: 1.4;
/* Default for Latin scripts 拉丁字符默认行高 (16px*1.5=24px) */
--leading-normal: 1.5;
/* 韩文阿拉伯语文紧凑阅读 */
--leading-relaxed: 1.65;
/* More breathing room for CJK 中日韩更舒展的行高 (16px*1.75=28px)*/
--leading-loose: 1.75;
}
/* ==================================================
Root Typography
根级排版基线
================================================== */
html,
:host {
font-family: var(--default-font-family), var(--font-sans), var(--font-zh-sc), var(--font-zh-tc), var(--font-ja), var(--font-ar), var(--font-emoji), var(--font-fallback);
/* Base line height 基础行高 */
line-height: var(--leading-normal);
/* Prevent iOS font auto-scaling 防止 iOS 横屏自动放大字体 */
-webkit-text-size-adjust: 100%;
/* Consistent tab rendering 统一 Tab 显示宽度 */
tab-size: var(--default-tab-size, 4);
/* Remove mobile tap highlight 移除移动端点击高亮 */
-webkit-tap-highlight-color: transparent;
/* Control OpenType advanced typographic features 控制 OpenType 高级排版特性 */
font-feature-settings: var(--default-font-feature-settings, normal);
/* Enable support for variable fonts 支持可变字体(Variable Fonts) */
font-variation-settings: var(--default-font-variation-settings, normal);
/* Improve long-text wrapping 优化长文本换行 */
text-wrap: pretty;
}
/* Language-specific font optimization 语言特定字体优化 */
/* Simplified Chinese 简体中文 */
:where([lang]:lang(zh)),
:where([lang]:lang(zh-CN)),
:where([lang]:lang(zh-Hans)) {
font-family: var(--font-zh-sc), var(--font-sans), var(--font-emoji), var(--font-fallback);
}
/* Traditional Chinese 繁体中文 */
:where([lang]:lang(zh-TW)),
:where([lang]:lang(zh-HK)),
:where([lang]:lang(zh-Hant)) {
font-family: var(--font-zh-tc), var(--font-sans), var(--font-emoji), var(--font-fallback);
}
/* Japanese 日文 */
:where([lang]:lang(ja)) {
font-family: var(--font-ja), var(--font-sans), var(--font-emoji), var(--font-fallback);
}
/* Arabic 阿拉伯语 */
:where([lang]:lang(ar)) {
font-family: var(--font-ar), var(--font-sans), var(--font-emoji), var(--font-fallback);
}
/* CJK & Arabic line-height optimization 中日韩与阿拉伯语行高优化 */
:where([lang]:lang(zh)),
:where([lang]:lang(ja)) {
line-height: var(--leading-loose);
}
:where([lang]:lang(ar)),
:where([lang]:lang(ko)) {
line-height: var(--leading-relaxed);
}
/* ==================================================
Document Structure
文档结构
================================================== */
html {
/* Improve text rendering quality 优化文本渲染质量 */
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
scroll-behavior: auto;
}
html:focus-within {
scroll-behavior: smooth;
}
body {
/* Remove default margin 移除浏览器默认外边距 */
margin: 0;
}
/* Use border-box for predictable sizing 使用更直观的盒模型,宽高包含 padding 和 border */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* 选择文本背景色跟随系统高亮色 */
::selection {
background-color: Highlight;
color: HighlightText;
}
/* ==================================================
Text-level Semantics
文本语义元素
================================================== */
/* Smaller headings use tighter spacing 标题越大,行高越紧凑 */
h1 {
line-height: var(--leading-tight);
}
h2,
h3 {
line-height: var(--leading-snug);
}
h4,
h5 {
line-height: var(--leading-compact);
}
h6 {
line-height: var(--leading-normal);
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin-block: 0;
}
/* Fine-tune line-height for CJK text cjk微调 */
:where([lang]:lang(zh)) h1,
:where([lang]:lang(ja)) h1,
:where([lang]:lang(ko)) h1 {
line-height: calc(var(--leading-tight) + 0.05);
}
:where([lang]:lang(zh)) h2,
:where([lang]:lang(ja)) h2,
:where([lang]:lang(ko)) h2,
:where([lang]:lang(zh)) h3,
:where([lang]:lang(ja)) h3,
:where([lang]:lang(ko)) h3 {
line-height: calc(var(--leading-snug) + 0.05);
}
/* Stronger bold weight in WebKit 修正加粗权重 */
b,
strong {
font-weight: bolder;
}
/* Monospace consistency 等宽字体统一 */
code,
kbd,
samp,
pre {
font-family: var(--default-mono-font-family, var(--font-mono));
/* Keep same size as body 保持与正文一致 */
font-size: 1em;
}
/* Small text size 小号文本 */
small {
font-size: 80%;
}
/* Sub/Sup line-height fix 上下标不影响行高 */
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* ==================================================
Forms
表单元素
================================================== */
/* Form typography normalization 表单排版统一 */
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
line-height: var(--leading-normal);
margin: 0;
}
/* Datalist arrow vertical alignment 修正 datalist 图标垂直对齐 */
input[list]::-webkit-calendar-picker-indicator {
line-height: 1em;
}
/* Fieldset legend padding reset 移除 legend 内边距 */
legend {
padding: 0;
}
/* Progress baseline alignment 修正进度条对齐 */
progress {
vertical-align: baseline;
}
/* Safari number input button fix 修正 Safari 数字输入按钮 */
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/* Search input normalization 搜索框外观统一 */
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
/* Remove macOS search decoration 移除 macOS 搜索装饰 */
::-webkit-search-decoration {
-webkit-appearance: none;
}
/* File upload button styling fix 文件上传按钮样式修正 */
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
/* Restore button appearance in iOS 恢复 iOS 按钮外观 */
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
cursor: pointer;
}
/* Disabled state cursor 禁用态鼠标样式 */
:disabled,
[aria-disabled="true"] {
cursor: not-allowed;
}
/* Textarea usability 文本域体验优化 */
textarea {
overflow: auto;
/* Scroll when needed 内容溢出时滚动 */
resize: vertical;
/* Only vertical resize 仅允许纵向拖拽 */
vertical-align: top;
/* Better inline alignment 更自然的行内对齐 */
}
/* Inline control alignment 行内控件对齐 */
input,
select,
meter,
progress,
button {
vertical-align: middle;
}
/* Accent color for native controls 原生控件主题色(checkbox / radio / progress / meter) */
input[type="checkbox"],
input[type="radio"],
progress,
meter {
accent-color: var(--default-accent-color);
}
/* ==================================================
Interactive Elements
交互元素
================================================== */
/* Ensure correct display for details/summary 修正折叠面板显示 */
summary {
display: list-item;
}
/* Label usability 标签可用性优化 */
label {
/* Indicate clickable 表示可点击 */
display: inline-flex;
/* Better alignment 更好的内部对齐 */
align-items: center;
/* Show pointer cursor when label contains a checkbox or radio 如果包裹了radio或checkbox则显示手型 */
}
label:where(:has(input)) {
cursor: pointer;
}
/* Form container positioning 表单容器定位基准 */
form {
position: relative;
/* For loading overlays 等绝对定位子元素 */
}
/* ==================================================
Media Elements
媒体元素
================================================== */
/* Inline media alignment 行内媒体对齐 */
img,
svg {
vertical-align: middle;
}
/* Responsive media safety 响应式媒体安全网 */
img,
video,
audio,
picture {
max-width: 100%;
height: auto;
}
/* Block media elements 块级媒体元素 */
picture,
iframe,
canvas,
embed,
object {
display: block;
}
/* Keep images at equal width with inherited border-radius. 确保两个标签等宽,并使用相同的圆角 */
picture img {
border-radius: inherit;
width: 100%;
height: auto;
object-fit: cover;
}
/* Full-width iframe 全宽 iframe */
iframe {
width: 100%;
border: 0;
}
/* Improve readability of the abbr element 增强abbr标签的可读性 */
abbr:where([title]) {
text-decoration: underline dotted;
cursor: help;
}
/* ==================================================
Content Elements
内容元素
================================================== */
/* Horizontal rule styling 分割线样式 */
hr {
border: 0;
height: 1px;
background-color: currentColor;
}
/* Preformatted text wrapping 预格式文本自动换行 */
pre {
white-space: pre-wrap;
overflow-wrap: break-word;
}
/* Code highlighting is typically structured as pre + code 代码高亮布局通常是pre+code */
pre > code {
display: block;
}
/* Keyboard input styling 键盘输入样式 */
kbd {
display: inline-flex;
vertical-align: middle;
user-select: none;
}
/* Article long-text wrapping 长文本断行优化 */
article {
overflow-wrap: break-word;
/* Prevent overflow 防止溢出 */
hyphens: auto;
/* Natural hyphenation 自动连字符 */
}
/* ==================================================
Tables
表格
================================================== */
table {
border-color: var(--default-border-color, currentColor);
min-width: 100%;
/* Fill container at minimum 至少铺满容器 */
border-collapse: collapse;
table-layout: fixed;
/* Faster & stable column width 更稳定高效 */
}
table th {
text-align: inherit;
}
/* Reduce motion 减少动画
* 有两个途径开启motion reduce功能
* 1.在电脑操作系统中设置取消动画
* 2.在浏览器设置中使用motion reduce设置
* 只要设置其中一个便将取消动画
*/
@media (prefers-reduced-motion: reduce) {
html {
/* 页面锚记之间跳转将没有平滑滚动动画 */
scroll-behavior: auto;
}
/* 所有animation动画失效 */
*,
*::before,
*::after {
animation-duration: 0.01ms ;
animation-iteration-count: 1 ;
transition-duration: 0.01ms ;
scroll-behavior: auto ;
}
}
}