CSS Basic Notes
CSS Working Group
- CSS working group: CSS WG.
- W3C standard types:
- ED:
Editor's Draft. - FPWD:
First Public Working Draft. - WD:
Working Draft. - CR:
Candidate Recommendation. - PR:
Proposed Recommendation. - REC: a W3C
Recommendationis a W3C Technical Report.
- ED:
CSS Cascading and Inheritance
Cascading Order
- Inherit styles.
- User agent normal styles.
- User normal styles.
- Author
@layernormal styles. - Author normal styles.
- Animation styles.
- Author
!importantstyles. - Author
@layer!importantstyles. - User
!importantstyles. - User agent
!importantstyles. - Transition styles.
Transition > Animation > Normal >
@layer> User > User Agent > Inherit
- 级联水平高的 styles 应用 !important 后, 其优先级变低.
- 级联水平低的 styles 应用 !important 后, 其优先级变高.
Layer
Layer Formal Syntax
@layer formal syntax:
@layer [<layer-name># | <layer-name>? {
<stylesheet>
}];
@layer base;
@layer theme, layout, components, utilities;
@layer base {
html {
font-size: 1rem;
}
}
@layer {
html {
font-size: 1rem;
}
}
@layer reset, externals, base, components, utilities;
@import url('reset.css') layer(reset);
@import url('carousel.css') layer(externals);
@import url('map.css') layer(externals);
<link
rel="stylesheet"
href="reset.css"
layer="reset"
media="supports(at-rule(@layer))"
/>
Layer Specificity
/* utilities > components > layout > theme */
@layer theme, layout, components, utilities;
/* c > c.d > a > a.b */
@layer a {
p {
color: red;
}
@layer b {
p {
color: green;
}
}
}
@layer c {
p {
color: orange;
}
@layer d {
p {
color: blue;
}
}
}

Specificity
Specificity
(Selector Priority) has 4 bits,
thousands, hundreds, tens, ones 0000:
- Thousands: inline-style.
- Hundreds: ID selector (实际开发中一般用
[id="Id"]代替优先级过高的 ID selector). - Tens: class selector, attribute selector, pseudo class(
:). - Ones: type selector, pseudo element(
::).
- Universal selector (
*), combinators (+,>,~,a b) and:where()have no effect on specificity. :not()/:is()/:has()have no effect on specificity, but selectors in it have effect on specificity.
<!-- specificity: 1000 -->
<h1 style="color: black">Hello</h1>
/* specificity: 0001 */
h1 {
color: red;
}
/* specificity: 0100 */
#id {
color: green;
}
/* specificity: 0003 */
h1 + p::first-letter {
color: blue;
}
/* specificity: 0022 */
li > a[href*='link-url'] > .inline-warning {
color: yellow;
}
/* specificity: 0023 */
div li:nth-child(2) a:hover,
div li:nth-child(2) a:focus {
border: 10px dashed black;
}
/* specificity: 0024 */
div div li:nth-child(2) a:hover,
div div li:nth-child(2) a:focus {
border: 10px solid black;
}
/* specificity: 0033 */
div div .nav:nth-child(2) a:hover,
div div .nav:nth-child(2) a:focus {
border: 10px double black;
}
/* specificity: 0101 */
#outer a {
background-color: red;
}
/* specificity: 0104 */
#outer div ul li a {
color: yellow;
}
/* specificity: 0113 */
#outer div ul .nav a {
color: white;
}
/* specificity: 0201 */
#outer #inner a {
background-color: blue;
}
Styles for a directly targeted element will always take precedence over inherited styles, regardless of the specificity of the inherited rule:
#parent {
color: green;
}
/* <h1> element will be purple */
h1 {
color: purple;
}
Increasing specificity by duplicating selector:
.my-class.my-class.my-class span {
/* 0-3-1 */
color: white;
}
:is(.my-class.my-class.my-class, span) {
/* 0-3-0 */
color: white;
}
Inheritance
- Most CSS properties that affect the text node are inherited properties: color, font-size, font-family, etc.
- Most CSS properties that affect the element node are non-inherited properties.
- When the
unsetvalue is set on an inherited property, it resets the property value to its inherited value. unsetvalue resets a non-inherited property to itsinitialvalue.revertreverses the CSS default values to the browser user-agent styles.
Inheritable CSS Property
- visibility
- cursor
- color
- direction
- font-family
- font-size
- font-style
- font-variant
- font-weight
- font
- line-height
- letter-spacing
- word-spacing
- white-space
- text-align
- text-indent
- text-transform
- border-collapse
- border-spacing
- caption-side
- empty-cells
- list-style-image
- list-style-position
- list-style-type
- list-style
- orphans
- quotes
- widows
CSS Selectors
Universal Selector
*:
- 不影响选择器优先级.
- 匹配自定义元素,
<script>,<style>,<title>. - 不匹配伪元素.
Type Selector
p {
margin-bottom: 1em;
line-height: 1.5em;
}
Attribute Selector
E[attr]:
/* 定位页面里所有具有必填属性 "required" 的 input */
input[required] {
border: 1px solid #f00;
}
E[attr=value] match value:
/* 定位页面里的密码输入框 */
input[type='password'] {
border: 1px solid #aaa;
}
E[attr|=value] match value/value-:
/**
* 定位页面里所有的 pre 里具有 class 属性且属性值为 language 或是 language- 开头的
* 比如 class="language", class="language-tsx"
*/
pre[class|='language'] {
color: #333;
}
E[attr~=value] match value/* value *:
/**
* 定位页面里所有具有属性 title 且属性值里拥有完整单词 english 的 div 容器
* 比如 title="english", title="a english"
*/
div[title~='english'] {
color: #f88;
}
E[attr^=value] match ^value:
/**
* 定位页面里具有属性 class 且属性值以 a 开头的 div 容器
* 比如 class="a", class="ab"
*/
div[class^='a'] {
color: #666;
}
E[attr$=value] match value$:
/**
* 定位页面里具有属性 class 且属性值以 a 结尾的 div 容器
* 比如 class="nba", class="cba"
*/
div[class$='a'] {
color: #f00;
}
E[attr*=value] match *value*:
/* 定位所有 title 里具有 link 字符串的 a 链接 */
a[title*='link'] {
text-decoration: underline;
}
Descendant Combinator
E F 后代选择器:
ul li {
margin-bottom: 0.5em;
}
Using the descendant selector without more specificity can be really expensive. The browser is going to check every descendant element for a match because the relationship isn't restricted to parent and child.
For .container ul li a selector:
- match every
<a>on the page - find every
<a>contained in a<li> - use the previous matches and narrow down to
the ones contained in a
<ul> - finally, filter down the above selection to
the ones contained in an element with the class
.container
Child Combinator
E > F 子代选择器:
ul > li {
list-style: none;
} /* 仅限ul的直接子元素li, 忽略嵌套子元素 */
General Sibling Combinator
E ~ F 一般兄弟选择器:
/* p before h1 */
p {
color: #fff;
}
/* 定位具有相同父元素的, h1标签之后的所有p标签 */
h1 ~ p {
color: #f00;
}
Checkbox input as hidden click event listener:
input.checkbox {
visibility: hidden;
opacity: 0;
}
nav {
transform: scale(0);
}
input.checkbox:checked ~ nav {
transform: scale(1);
}
Adjacent Sibling Combinator
E + F 相邻兄弟选择器:
* + * {
margin-top: 1.5em;
}
li + li {
border-top: 1px solid #ddd;
}
Location Pseudo Class
Link Pseudo Class
:link:
- 只匹配未访问的
<a href>. - 可用
a/[href]选择器代替.
Visited Pseudo Class
:visited:
- 只匹配访问过的
<a href>. - 只支持设置颜色:
color/background-color/outline-color/border-color/column-rule-color/text-decoration-color. - 不支持颜色透明度 (
alpha). - 只支持重置已有颜色, 不能新增设置样式.
window.getComputedStyle无法获取到:visited设置颜色.
Any Link Pseudo Class
:any-link:
- 同时匹配
:link与:visited元素. - 匹配所有设置了
[href]的链接元素:<a href>/<link href>/<area href>.
Target Pseudo Class
:target:
- 该选择器定位当前活动页面内定位点的目标元素 (#anchor-name)
#info:target {font-size:24px;}. - 可用于实现 tab/modal/carousel/gallery/slide:
- 利用
display:none隐藏#id元素, 不会触发页面滚动 (防止页面抖动), 可以触发:target伪类匹配. :target ~ .content控制实际内容切换.
- 利用
<a href="#p1">p1</a>
<div id="p1">p1</div>
<style>
div:target {
background-color: purple;
}
</style>
.anchor {
display: none;
}
.content {
max-height: 0;
}
.anchor:target ~ .content {
max-height: 100%;
}
:target-within:
- Selected when any children targeted.
User Action Pseudo Class
Hover Pseudo Class
- 鼠标移动到容器时的状态.
- 不仅限于链接, 可用于页面中的任何元素.
Active Pseudo Class
:active:
- 点击 (mouse click/screen touch) 时的状态.
- 键盘访问无法激活
:active. - 不仅限于链接, 可用于任何具有
tabindex属性的元素.
:link —> :visited —> :hover —> :active links:
/* Unvisited links */
a:link {
color: blue;
}
/* Visited links */
a:visited {
color: purple;
}
/* Hovered links */
a:hover {
background: yellow;
}
/* Active links */
a:active {
color: red;
}
[href]:active,
button:active,
[type='button']:active,
[type='reset']:active,
[type='submit']:active {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
background: linear-gradient(rgb(0 0 0 / 5%), rgb(0 0 0 / 5%));
outline: 999px solid rgb(0 0 0 / 5%);
outline-offset: -999px;
box-shadow: inset 0 0 0 999px rgb(0 0 0 / 5%);
}
Focus Pseudo Class
:focus:
- 获得焦点时的状态 (包括键盘访问).
- 不仅限于
<a href>/<button>/<input>/<select>/<area>/<summary>, 可用于任何具有tabindex/contenteditable属性的元素.
:focus-visible:
- Selected when
Tab(keyboard) focused. - 可用于区分鼠标与键盘激活样式.
Separate focus styles:
/* Tab Focus Style */
.button:focus-visible {
outline: 2px solid #416dea;
outline-offset: 2px;
box-shadow: 0 1px 1px #416dea;
}
/* Mouse Focus Style */
.button:focus:not(:focus-visible) {
outline: none;
}
:focus-within:
- Selected when any children focused.
- 可用于实现
dropdown.
.dropdown-list {
display: none;
}
.dropdown:focus-within .dropdown-list {
display: block;
}
Input Pseudo Class
:autofill.:enabled: 匹配启用的界面元素, e.ginput.:disabled: 匹配禁用的界面元素 ([disabled]), e.ginput.:read-only: 匹配其内容无法供用户修改的元素 (<div>/[readonly]).:read-write: 匹配其内容可供用户修改的元素 (<div contenteditable>/<input>).:default: 匹配处于默认状态的表单元素, 可用于默认选项/推荐选项样式.:checked: 匹配处于选中状态的表单元素, 可用于开关选框/多选框样式, e.g tab, dropdown, modal, carousel, tree, checkbox grid.:indeterminate:- 匹配处于未选状态的单选框元素
<input type="radio">. - 匹配处于半选状态的复选框元素
<input type="checkbox">. - 匹配处于未设置
value的进度条元素<progress>.
- 匹配处于未选状态的单选框元素
:valid: 匹配输入验证有效的表单元素 (<input type>/<input pattern>).:invalid: 匹配输入验证无效的表单元素.:user-invalid: 匹配用户交互后仍然验证无效的表单元素.:in-range: 匹配具有范围限制的元素, 其中该值位于限制范围内, e.g 具有min和max属性的number和range输入框.:out-of-range: 与:in-range选择相反, 其中该值位于限制范围外.:required: 匹配具有必填属性[required]的表单元素.:optional: 匹配没有必填属性[required]的表单元素.:placeholder-shown: selectinputwith placeholder, 可用于控制输入样式.
@media only screen and (prefers-reduced-motion: reduce) {
.msg {
transition: none;
}
}
.msg {
opacity: 0;
transition: opacity 0.2s ease-in-out;
}
.input:not(:placeholder-shown) ~ .label,
.input:focus ~ .label {
opacity: 1;
}
Structural Pseudo Class
:root:- 根元素, 始终指 html 元素.
:root选择器优先级高于html选择器.- 为了代码可读性,
:root用于设置全局变量,html用于设置全局样式.
:empty: 没有任何子元素的元素, 不能有注释节点与文本节点.E F:nth-child(n):该选择器定位元素 E 的第 n 个子元素的元素 F,可省略 E.E F:nth-last-child(n): 该选择器定位元素 E 的倒数第 n 个子元素的元素 F,可省略 E.E F:first-child: 第一个孩子.E F:last-child: 最后一个孩子.E F:only-child: 单一后代.E F:nth-of-type(n): 该选择器定位元素 E 的第 n 个 相同类型 子元素,可省略 E.E F:nth-lash-of-type(n): 该选择器定位元素 E 的导数第 n 个 相同类型 子元素,可省略 E.E F:first-of-type: 相同类型 的第一个元素.E F:last-of-type: 相同类型 的最后一个元素.E F:only-of-type: 孩子中只有一种该元素.
n start from 0,
calculation result limit to > 0:
:nth-child(5n):0, 5, 10, 15, ...->5, 10, 15, ....:nth-child(3n + 4):4, 7, 10, 13, ...->4, 7, 10, 13, ....:nth-child(-n + 3):3, 2, 1, 0, -1, ...->3, 2, 1.:nth-child(n + 4):nth-child(-n + 10): 两个n分开计算,4, 5, 6, ...+10, 9, 8, ...->4, 5, 6, 7, 8, 9, 10.
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
/* 当列表正好包含 4 项时, 命中所有列表项 */
color: darkblue;
}
/* stylelint-disable-next-line no-descending-specificity */
li:first-child:nth-last-child(n + 4),
li:first-child:nth-last-child(n + 4) ~ li {
/* 当列表至少包含 4 项时, 命中所有列表项 */
color: darkblue;
}
li:first-child:nth-last-child(n + 2):nth-last-child(-n + 6),
li:first-child:nth-last-child(n + 2):nth-last-child(-n + 6) ~ li {
/* 当列表包含 2 ~ 6 项时, 命中所有列表项 */
color: darkblue;
}
Logical Pseudo Class
:not(<selector>):- Selector priority.
- 选择与括号内的选择器不匹配的元素.
:is(<selector>):- Selector priority.
- Legacy name:
:any()/:matches().
:where(<selector>):0priority.
<target>:has(<selector>):- Selector priority.
- A target element has child elements:
:has(> selector). - A target element has sibling elements:
:has(+ selector).
:is(ol, ul) :is(ol, ul) li {
margin-left: 2rem;
}
Linguistic Pseudo Class
:dir(ltr)/:dir(rtl).:lang(en): 具有使用双字母缩写 (en) 表示的语言的元素.
:lang(en) > q {
quotes: '\201C' '\201D' '\2018' '\2019';
}
:lang(fr) > q {
quotes: '<< ' ' >>';
}
:lang(de) > q {
quotes: '>>' '<<' '\2039' '\203A';
}
Misc Pseudo Class
:fullscreen.
First Letter and Line Pseudo Element
::first-letter/::first-line:
::first-letter: 匹配文本首字母.::first-line: 匹配文本首行.- IE9 及以上版本浏览器支持双冒号, IE8 浏览器只支持单冒号写法.
- 只作用于块级元素:
displayblock/inline-block/list-item/table-cell/table-caption. - 只支持部分 CSS 属性:
color.fontproperties:font-size,font-weight.textproperties:text-decoration,word-spacing.backgroundproperties:background-color,background-image.borderproperties:border-color.float.
Selection Pseudo Element
::selection 匹配突出显示的文本:
color.background-color.cursor.caret-color.outline.text-decoration.text-emphasis-color.text-shadow.stroke-color.fill-color.stroke-width.
/* 定义选中的文本颜色与背景色 */
::selection {
color: #fff;
background: #444;
}
Target Text Pseudo Element
::target-text {
color: white;
background-color: rebeccapurple;
}
Before and After Pseudo Element
使用 content 属性生成额外的内容并插入在标记中:
a::after {
content: '↗';
}
attr(), 调用当前元素的属性:
a::after {
content: '(' attr(href) ')';
}
b::after {
content: '(' attr(data-language) ')';
}
url()/uri(), 用于引用媒体文件:
h1::before {
content: url('logo.png');
}
counter(), 调用计数器, 可以不使用列表元素实现序号功能,
配合 CSS3 中counter-increment和counter-reset属性:
<div>
<h2>HTML</h2>
<h2>CSS</h2>
<h2>JS</h2>
</div>
<style>
div {
counter-reset: tidbit-counter 58;
}
h2::before {
content: counter(tidbit-counter, list-style-type) ': ';
counter-increment: tidbit-counter 1;
}
</style>
<!-- output
59: HTML
60: CSS
61: JS
output -->
伪元素可用于扩大可点击区域:
.btn-text::before {
position: absolute;
inset: -6px -8px;
content: '';
}
Backdrop Pseudo Element
/* Backdrop is only displayed when dialog is opened with dialog.showModal() */
dialog::backdrop {
background: rgb(255 0 0 / 25%);
}
video::backdrop {
background-color: #448;
}
Marker Pseudo Element
animation-*.transition-*.color.direction.font-*.content.unicode-bidi.white-space.
li::marker {
font-variant-numeric: tabular-nums;
text-align: start;
text-align-last: start;
text-indent: 0;
text-transform: none;
unicode-bidi: isolate;
}
Shadow DOM Pseudo Class and Element
:host: shadow DOM root element.:host-context: shadow DOM root parent element.::part().::slotted().
Focusable Selector
const FOCUSABLE_SELECTOR = [
'[contenteditable]',
'[tabindex="0"]:not([disabled])',
'a[href]',
'audio[controls]',
'button:not([disabled])',
'iframe',
'input:not([disabled]):not([type="hidden"])',
'select:not([disabled])',
'summary',
'textarea:not([disabled])',
'video[controls]',
].join(',');
CSS Data Types
CSS data types define typical values (including keywords and units) accepted by CSS properties and functions:
- Textual data types.
- Numeric data types.
- Quantities.
- Combinations of types.
- Color data types.
- Image data types.
- 2D
<position>.
CSS data types list:
- CSS formal syntax.
- CSS values.
- CSS units.
- CSS functions.
CSS Property Values
Inherit Value
Inherit from parent.
Initial Value
The initial value of a CSS property is its default value, as listed in its standard definition table.
Revert Value
Revert to user agent built in styles.
@supports (-webkit-overflow-scrolling: touch) {
progress {
all: revert;
}
}
Unset Value
Reset to inherit or initial value.
dialog {
all: unset; /* Exclude `unicode-bidi`, `direction`, custom variables */
}
Specified Value
The specified value of a CSS property is the value it receives from the document's style sheet
Computed Value
The computed value of a CSS property is the value that is transferred from parent to child during inheritance. It is calculated from the specified value by:
- Handling the special values
inherit,initial,unset, andrevert - Doing the computation needed to reach the value described in the "Computed value" line in the property's definition table
span {
/* display computed to `block` */
position: absolute;
}
Used Value
The used value of a CSS property is its value after all calculations have been performed on the computed value:
- The used values of dimensions (e.g., width, line-height) are in pixels
- The used values of shorthand properties (e.g., background) are consistent with those of their component properties (e.g., background-color or background-size) and with position and float
Actual Value
The actual value of a CSS property is the used value of that property after any necessary approximations have been applied
The user agent performs four steps to calculate a property's actual (final) value:
- the specified value is determined based on the result of cascading, inheritance, or using the initial value.
- the computed value is calculated according to the specification (for example, a span with position: absolute will have its computed display changed to block)
- layout is calculated, resulting in the used value
- the used value is transformed according to the limitations of the local environment, resulting in the actual value
- initial.
- specified.
- computed.
- used.
- actual value.
CSS Logical Properties and Values
CSS Logical Basis
In position/size/margin/padding/border/text alignment:
block-startfortop.block-endforbottom.blockfor vertical.inline-startforleft.inline-endforright.inlinefor horizontal.
.logical {
inline-size: fit-content;
block-size: fit-content;
min-inline-size: min-content;
min-block-size: min-content;
max-inline-size: max-content;
max-block-size: max-content;
padding-block-start: 1rem;
padding-block-end: 1rem;
padding-inline-start: 1rem;
padding-inline-end: 1rem;
margin-block-start: 1rem;
margin-block-end: 1rem;
margin-inline-start: 1rem;
margin-inline-end: 1rem;
border-block-start: 1px solid blue;
border-block-end: 1px solid blue;
border-inline-start: 1px solid blue;
border-inline-end: 1px solid blue;
inset-block-start: 0;
inset-block-end: 0;
inset-inline-start: 0;
inset-inline-end: 0;
}
CSS Logical Reference
CSS Variables
Scope Variables
Inherited Variables
CSS Variables 本质上具有继承特性, HTML 文档树中, 后代元素可以继承祖先元素的 CSS Variables:
<div class="alert alert-info">
<div class="alert-content">
<h2 class="alert-title">Info</h2>
<div class="alert-body">
<p>Info Message.</p>
</div>
</div>
</div>
Contextual Styling Variables
[data-theme='dark'] {
--fg: hsl(0deg 10% 70%);
--border: hsl(0deg 10% 10%);
--bg: hsl(0deg 0% 20%);
--button-bg: hsl(0deg 0% 25%);
--input-bg: hsl(0deg 0% 15%);
}
[data-theme='hero'] {
--fg: hsl(240deg 50% 90%);
--border: hsl(240deg 50% 10%);
--bg: hsl(240deg 33% 30%);
--button-bg: hsl(240deg 33% 40%);
--input-bg: hsl(240deg 33% 20%);
}
Contextual styling buttons:
:root {
--primary: hsl(260deg 95% 70%);
--secondary: hsl(320deg 95% 60%);
}
.button {
background-color: var(--button-background, transparent);
}
.button-primary {
--button-background: var(--primary);
}
.button-secondary {
--button-background: var(--secondary);
}
Contextual styling alerts:
.alert {
--primary: #777;
--secondary: #ccc;
background-color: var(--secondary);
border: 1px solid var(--primary);
}
.alert::before {
background-color: var(--primary);
}
.alert-title {
color: var(--primary);
}
.alert-success {
--primary: #40c057;
--secondary: #d3f9d8;
}
.alert-info {
--primary: #228be6;
--secondary: #d0ebff;
}
.alert-warning {
--primary: #fab005;
--secondary: #fff3bf;
}
.alert-error {
--primary: #fa5252;
--secondary: #ffe3e3;
}
Invalid and Empty Variables
--invalid-value: initial;isinvalidvalue leading tovar(--invalid-value)called failed,var(--invalid-value, backup-value)getbackup-value.--empty-value: ;is validemptyvalue leading tovar(--empty-value)called succeeded,var(--empty-value, backup-value)getunsetvalue (inheritorinitialvalue).- Use
invalidandemptyvalue to implementif (true)statement, you can see real world case ontailwind.css.
:root {
--on: initial;
--off: ;
}
button {
--is-raised: var(--off);
border: 1px solid var(--is-raised, rgb(0 0 0 / 10%));
}
button:hover,
button:focus {
--is-raised: var(--on);
}
/**
* css-media-vars
* BSD 2-Clause License
* Copyright (c) James0x57, PropJockey, 2020
*/
html {
--media-print: initial;
--media-screen: initial;
--media-speech: initial;
--media-xs: initial;
--media-sm: initial;
--media-md: initial;
--media-lg: initial;
--media-xl: initial;
/* ... */
--media-pointer-fine: initial;
--media-pointer-none: initial;
}
/* 把当前变量变为空值 */
@media print {
html {
--media-print: ;
}
}
@media screen {
html {
--media-screen: ;
}
}
@media speech {
html {
--media-speech: ;
}
}
/* 把当前变量变为空值 */
@media (width <= 37.499em) {
html {
--media-xs: ;
--media-lte-sm: ;
--media-lte-md: ;
--media-lte-lg: ;
}
}
/** 移动优先的样式规则 */
.breakpoints-demo > * {
/** 小于 37.5em, 宽度 100% */
--xs-width: var(--media-xs) 100%;
/** 小于 56.249em, 宽度 49% */
--sm-width: var(--media-sm) 49%;
--md-width: var(--media-md) 32%;
--lg-width: var(--media-gte-lg) 24%;
width: var(--xs-width, var(--sm-width, var(--md-width, var(--lg-width))));
--sm-and-down-bg: var(--media-lte-sm) red;
--md-and-up-bg: var(--media-gte-md) green;
background: var(--sm-and-down-bg, var(--md-and-up-bg));
}
Space toggle for progressive enhancement
:root {
--in-oklab: ;
}
@supports (background: linear-gradient(in oklab, red, tan)) {
:root {
--in-oklab: in oklab;
}
}
/* Usage: */
.card {
background: linear-gradient(var(--in-oklab) #f00, #0f0);
}
Limit Variables
For some CSS values and units have limits (e.g <color>),
use variables to implement if else statement.
:root {
--red: 44;
--green: 135;
--blue: 255;
/**
* 亮度算法:
* lightness = (red * 0.2126 + green * 0.7152 + blue * 0.0722) / 255
*/
--lightness: calc(
(var(--red) * 0.2126 + var(--green) * 0.7152 + var(--blue) * 0.0722) / 255
);
}
.button {
/* 文字颜色, 只可能是黑色或白色 */
color: hsl(0% 0% calc((var(--lightness) - 0.5) * -999999%));
/* 文字阴影, 黑色文字才会出现 */
text-shadow: 1px 1px rgb(calc(var(--red) + 50) calc(var(--green) + 50) calc(
var(--blue) + 50
) / calc((var(--lightness) - 0.5) * 9999));
/* 背景颜色 */
background: rgb(var(--red) var(--green) var(--blue));
/* 固定样式 */
border: 0.2em solid;
/* 边框样式, 亮度大于 0.8 才出现 */
border-color: rgb(
calc(var(--red) - 50) calc(var(--green) - 50) calc(var(--blue) - 50) / calc((
var(--lightness) - 0.8
) * 100)
);
}
Dark Mode Variables
:root {
/* Themes */
--bg-light: #fff;
--text-light: #000;
--bg-dark: #000;
--text-dark: #fff;
/* Defaults */
--bg: var(--bg-light);
--text: var(--text-light);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: var(--bg-dark);
--text: var(--text-dark);
}
}
Variables API
.element {
height: 100vh; /* Fallback for browsers that do not support Custom Properties */
height: calc(var(--vh, 1vh) * 100);
}
window.addEventListener('resize', () => {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
const root = document.documentElement;
const bgColor = getComputedStyle(root).getPropertyValue('--body-bg');
Change --cursor-x and --cursor-y via JavaScript API:
:root::before {
position: fixed;
z-index: 1000;
display: block;
width: 100%;
height: 100%;
pointer-events: none;
content: '';
background: radial-gradient(
circle 16vmax at var(--cursor-x) var(--cursor-y),
rgb(0 0 0 / 0%) 0%,
rgb(0 0 0 / 50%) 80%,
rgb(0 0 0 / 80%) 100%
);
}
Change --percent via JavaScript API:
.bar {
display: flex;
height: 20px;
background-color: #f5f5f5;
}
.bar::before {
display: flex;
justify-content: end;
width: calc(var(--percent) * 1%);
font-size: 12px;
color: #fff;
white-space: nowrap;
content: counter(progress) '%\2002';
counter-reset: progress var(--percent);
background: #2486ff;
}
Properties and Values API
@property --property-name {
syntax: '<color>';
inherits: false;
initial-value: #c0ffee;
}
window.CSS.registerProperty({
name: '--my-color',
syntax: '<color>',
inherits: false,
initialValue: '#c0ffee',
});
CSS 不支持背景渐变色的直接过渡动画,
需要使用两层背景渐变 (background + ::before/::after background)
opacity 变化
实现渐变背景的过渡动画.
现在,
可以对 CSS Houdini 自定义变量
设置 transition/animation,
快速实现渐变背景的过渡动画:
@property --houdini-color-a {
syntax: '<color>';
inherits: false;
initial-value: #fff;
}
@property --houdini-color-b {
syntax: '<color>';
inherits: false;
initial-value: fuchsia;
}
.box {
background: linear-gradient(
45deg,
var(--houdini-color-a),
var(--houdini-color-b)
);
/* stylelint-disable-next-line custom-property-no-missing-var-function */
transition: 1s --houdini-color-a;
animation: change 10s infinite linear;
}
.box:hover {
--houdini-color-a: yellowgreen;
}
@keyframes change {
20% {
--houdini-color-b: red;
}
40% {
--houdini-color-b: #ff3c41;
}
60% {
--houdini-color-b: orange;
}
80% {
--houdini-color-b: #ae63e4;
}
}
@property --per {
syntax: '<percentage>';
inherits: false;
initial-value: 25%;
}
.pie {
background: conic-gradient(
yellowgreen,
yellowgreen var(--per),
transparent var(--per),
transparent 100%
);
/* stylelint-disable-next-line custom-property-no-missing-var-function */
transition: --per 300ms linear;
}
.pie:hover {
--per: 60%;
}
@property feature detection and fallback:
@property --parent-em {
syntax: '<length>';
initial-value: 0;
inherits: true;
}
@property --no-at-property-fallback {
syntax: '*';
inherits: false;
}
select {
--parent-em: 1em;
--no-at-property-fallback: 1em;
}
optgroup {
/* Will only inherit if `@property` not supported */
font-size: var(--no-at-property-fallback, 0);
}
optgroup > * {
font-size: var(--parent-em);
}
CSS Colors
Current Color
currentcolor变量使用当前color计算值.border-color/outline-color/caret-color/text-shadow/box-shadow默认表现为currentcolor.
Accent Color
Change user-interface controls accent color.


