Johnny Wang BlogJohnny Wang Blog
Articles
Project
Live2d
johnnywang/book
Articles
Project
Live2d
johnnywang/book
  • About Me

    • 關於 Johnny
    • 文章清單
  • Javascript

    • View Transitions - 認識並使用原生 document 轉場效果
    • 用 Web Container 打造自己的線上 NodeJS 開發環境
    • 來試用看看原生 Web Popover API
    • 在電腦裡搞一個 RWKV AI 小助手
    • 遊戲 App 素材解包學習紀錄
    • 動手自己做一個 ChatGPT UI 工具吧
    • Create a React Server Components Project without NextJS - 製作一個不依賴 NextJS 的 React Server Components 專案
    • 如何在 Vuepress 裡快樂寫 React
    • 從 Mock Service Worker 源碼中學習
    • 擺脫 Node modules 地獄,擁抱 Yarn Plug'n'Play(PnP)
    • 快速上手 NextJS v13 - 基礎觀念 AppRouter 篇
    • 快速上手 NextJS v13 - Data Fetching, Caching, Revalidating 篇
    • 用 Socket.io 搭配 Matterjs 製作一款 Real-Time Canvas 聊天室(文長慎入)
    • 如何只用一支 CDN 及 4行設定,讓瀏覽器讀懂 Typescript, React, Vue
    • 用 tsup 快速建立 Typescript 開發環境
    • 開發 Email EDM 你可以更輕鬆
    • 關於我的 Side project - Maju Web Editor
    • Web URL 中神奇的 createObjectURL method
    • Awesome Vite 一個由社群維護的 template 集大成
    • Vue、React 使用心得分享(文長慎入)
    • 一起動手用 Socket.io 和 Peerjs 打造 WebRTC 即時視訊
    • Temporal Typescript SDK 學習筆記
    • React Web3 Storage
    • React useState 取得最新值
    • Babel 7 Decorator 的神奇小問題
    • 用 Koa + Vite + Pinia 打造基礎 SSR 環境
    • Live2d 官方範例改寫
    • 如何把 Video 畫在 Canvas 上
    • 史上最簡單的 Webpack 5 教學
    • 在瀏覽器中直接 import Vue SFC 開發起來
    • 手寫一個可中斷的 delay promise
    • NodeJS 輕量開發框架 Expressjs 與 Koa2 的區別
    • 用 2D 物理引擎 Matterjs 製作經典馬力歐 1-1
    • 原生 Javascript 的類型標註工具 JSDoc
    • Pinia - Vuex 的後繼者
    • 用 Nodejs 寫個 FTP command line 工具
    • Vue3 Server Render 手把手帶你搭建
    • 你真的懂 Event Loop 嗎
    • Babel7 基本介紹與使用
    • Vue/Vitejs 部分源碼解析
    • Vuejs 依賴追蹤 2020 版
    • Vuejs 依賴追蹤 2019 版
    • Js literal 模板編譯
    • 用 JavaScript 鎖定用戶調整畫面比例
    • Date.now() 與 new Date()
    • Promise 相關知識
    • Web Component 學習筆記
    • TypeScript 基礎篇
    • TypeScript 進階篇
    • MVC, MVVM, MVI 軟體設計架構
    • MVVM 簡單模擬框架實作
  • CSS & Sass

    • 2024 CSS 年度報告筆記
      • Layout
      • Animations
      • Pseudo-classes
      • Components
      • JS related
      • Others
      • References
    • 2021 CSS 年度報告筆記
    • 如何不用 setTimeout 幫 display: none 的 DOM 加動畫
    • 純 CSS 實作星球環繞動畫效果
    • 差點錯過的 Tailwindcss 入門學習筆記
    • Tailwindcss 進階學習筆記
    • Sass, SCSS Built-In-Modules 內建模組與函數
    • SCSS Parent Selector
    • CSS 畫面鎖橫屏時,滾動的問題!!
    • Safari 使用 animation 時動態產生 rem 的坑
    • CSS: mix-blend-mode 屬性混合圖層動畫
  • Memo

    • Javascript

      • Yarn Plug'n'Play (PnP) 的 VSCode 設定方式
      • 如何用 Web API 讀取剪貼簿內容
      • CSP (Content Security Policy) 是什麼?
      • Astro 入門學習筆記
      • 如何解決 Astro 套用主題切換時,畫面抖動瞬閃問題
      • Rspack - 以 Rust 打造的快速構建工具
      • Typescript v5 Decorator 學習筆記
      • Sequelize 筆記
      • ES2022 學習筆記
      • Crypto 密碼加密方法
      • 實作 Test 的注意事項
      • Jest 測試工具 - 基礎篇
      • 正則表達式
      • Rxjs 學習筆記
      • Gulp 學習筆記
      • Clean Code Javascript 學習
      • JS 實戰開發特殊小技巧
    • React

      • React forwardRef 使用筆記
      • 如何在 Nextjs 中使用 middleware set cookie
      • React Styled-Components 基礎篇
      • React Styled-Components 進階篇
      • React Unit Test
      • React Testing Library
      • React Emotion Basic
      • React Styled-JSX
      • React 18 - Concurrent Features Memo
      • useEffect 的高階封裝範例
      • React useContext & useReducer 搭配
      • React Router Config 筆記
    • Vue

      • Cypress Vue
      • Vue 單元測試學習筆記
      • 學習 Vuetify 的一些筆記
      • Vuex 學習筆記
    • React Native

      • React Native - basic
      • Expo Basic
      • Expo Router
      • Expo Build
      • Issues
    • GraphQL

      • GraphQL 學習筆記 - 基礎篇
      • GraphQL 學習筆記 - 進階篇
      • Apollo Client 學習使用筆記
      • GraphQL Memo
    • Parse

      • Parse Javascript 文檔閱讀筆記
      • Parse User Object 章節
      • Parse Session Object 章節
      • Parse Schema Object 章節
      • Parse Cloud Code 章節
    • CSS

      • Sass, SCSS 基礎筆記
    • Docker

      • Docker 基礎技術
      • Dockerfile 技術篇
      • Docker-compose 技術篇 - 3.7
      • Kubernetes 學習筆記
      • ArgoCD 學習筆記
      • Podman 學習筆記
      • Colima 安裝使用筆記
    • Git Learning

      • Git 版本控制
      • Git 基礎使用 - init, clone, add, commit, status, log
      • Git 分支
      • Git Merge 分支合併指令
      • Git Stash 保存紀錄
      • Git 基礎復原指令 - restore
      • Remote 遠端協同工作 - remote, fetch, pull, push
      • Git Tag 標籤 - tag
      • Git 設定 - config
      • Git 檔案比對與差異 - diff
      • Git Rebase 定義分支的參考基準
      • Subtree 子樹
      • Git Reflog 指令紀錄
      • Git Filter Branch
      • Git Crypt 使用筆記
      • Git 客製化工具
    • Bash

      • Bash 基礎概念
      • Variable 變數
      • Script 腳本撰寫
      • Condition 流程控制
      • Operation 算數表達式
      • Function 函數
      • Command Line Params 指令列參數處理
    • Python

      • Pyenv with virtualenv 配置
    • Patterns

      • Introduce
      • Design Patterns

        • Singleton Pattern
        • Compound Pattern
        • Proxy Pattern
        • Hooks Pattern
        • Observer Pattern
        • Mediator/Middleware Pattern
        • HOC Pattern
        • Factory Pattern
        • Render Props Pattern
        • Flyweight Pattern
        • Container/Presentational Component
        • Prototype Pattern
        • Mixin Pattern
        • Provider Component
        • Command Component
        • Module Pattern
      • Render Patterns

        • Rendering Patterns 渲染模式介紹
    • FE 性能優化

      • 前端性能優化
      • 靜態資源優化
      • 頁面渲染架構優化
      • Server 與 Network 優化
      • 開發流程、監控體系優化
    • Ollama 筆記
    • Nginx JS module 基本使用筆記
    • FlowiseAI 使用介紹筆記
    • Github Copilot 使用筆記
    • Traefik Memo
    • API First 學習筆記
    • What is AC - Acceptance Criteria 驗收條件
    • Mermaid 學習筆記
    • 串接 Sonarcube 筆記
    • Youtube Data API 基礎使用筆記
    • FB API 學習筆記
    • VSCode 好用快捷鍵
    • 在 Simulator 上開發測試
    • 問題修正紀錄
  • References

    • 全端開發學習資源
    • 實用工具
    • 網頁前端課程目錄
  • Daily

    • 中醫學習

      • 中醫自學方向
      • 黃帝內經

        • 黃帝內經-素問
      • 基礎理論

        • 中藥治病
        • 中藥產地與採收
        • 陰陽五行
        • 精氣血津液
        • 整體觀與臟象
        • 病因病機
        • 辨證論治
        • 四診八綱
        • 五運六氣
        • 經絡
      • 診斷學

        • 辯證
        • 望診
        • 聞診
        • 問診
        • 脈診簡史
        • 切診
        • 常見脈象與臨床意義
        • 經脈辨證
        • 中醫的六邪在疾病初期、後期分別有那些症狀
      • 中藥學

        • 中藥基礎理論
        • 常見中藥材
        • 解表藥(30)
        • 清熱藥(82)
        • 瀉下藥(16)
        • 利水渗湿药(8)
        • 化痰止咳平喘药(15)
        • 止血藥(8)
        • 開竅-平肝-安神藥(11)
        • 化濕藥(5)
        • 祛風濕藥(12)
        • 理氣藥(13)
        • 活血祛瘀藥(7)
        • 消食藥(4)
        • 驅蟲藥(6)
        • 祛寒药(6)
        • 補虛藥(43)
        • 收斂藥(13)
      • 方劑學

        • 總論
        • 解表劑
        • 瀉下劑
        • 清熱劑
        • 理血劑
        • 去暑劑
        • 去濕劑
      • 針灸學

        • 特定穴
      • 其他

        • 內證觀察筆記 上篇【內證漫談】
        • 內證觀察筆記 中篇【太極器官、五藏】
        • 內證觀察筆記 下篇【十二正經】
        • 磁力對生理的影響
    • 易經學習

      • 易經入門
    • 道德經學習

      • 道德經學習重點筆記
      • 第一章 道可道,非常道
      • 第二章 夫唯弗居,是以不去
      • 第三章 不尚賢,使民不爭
      • 第四章 道沖而用之或不盈,淵兮似萬物之宗
      • 第五章 天地不仁,以萬物為芻狗,多聞數窮,不如守中
      • 第六章 谷神不死,是謂玄牝
      • 第七章 天長地久。天地所以能長且久者,以其不自生,故能長生。
      • 第八章 上善若水。水善利萬物而不爭,處眾人之所惡,故幾於道
      • 第九章 功成身退,天之道也。
      • 第十章 載營魄抱一,能無離乎﹖
      • 第十一章 有之以為利,無之以為用
      • 第十二章 五色令人目盲,五音令人耳聾,五味令人口爽,馳騁畋獵令人心發狂,難得之貨令人行妨。
      • 第十三章 寵辱若驚,貴大患若身。愛以身為天下,若可托天下
      • 第十四章 是謂無狀之狀,無物之象,是謂惚恍。迎之不見其首,隨之不見其後。執古之道,以御今之有。
      • 第十五章 保此道者,不欲盈。夫唯不盈,故能蔽而新成。
      • 第十六章 致虛極,守靜篤。萬物並作,吾以觀復。
      • 第十七章 太上,下知有之。悠兮其貴言,功成事遂,百姓皆謂我自然。
      • 第十八章 大道廢,有仁義;智慧出,有大偽;
      • 第十九章 絕聖棄智,民利百倍。見素抱樸,少私寡欲
      • 第二十章 絕學無憂。眾人皆有餘,而我獨若遺。
      • 第二十一章 道之為物,惟恍惟惚。惚兮恍兮,其中有象;恍兮惚兮,其中有物。
      • 第二十二章 曲則全,枉則直,窪則盈,敝則新,少則得,多則惑。是以聖人抱一為天下式
      • 第二十三章 希言自然。天地尚不能久,而況於人乎?信不足焉,有不信焉。
      • 第二十四章 企者不立,跨者不行
      • 第二十五章 有物混成,先天地生。人法地,地法天,天法道,道法自然。
      • 第二十六章 重為輕根,靜為躁君。輕則失本,躁則失君。
      • 第二十七章 善行無轍跡,善言無瑕謫。故善人者,不善人之師;不善人者,善人之資。不貴其師,不愛其資,雖智大迷,是謂要妙。
      • 第二十八章 知雄守雌,為天下谿,知榮守辱,為天下谷
      • 第二十九章 天下神器,不可為也,是以聖人去甚,去奢,去泰。
      • 第三十章 以道佐人主者,不以兵強天下
      • 第三十一章 夫兵者,不祥之器,物或惡之,故有道者不處。
      • 第三十二章 道常無名,樸雖小,天下莫能臣也。
      • 第三十三章 知人者智,自知者明。
      • 第三十四章 大道氾兮,其可左右。以其終不自為大,故能成其大。
      • 第三十五章 執大象,天下往。往而不害,安平太。樂與餌,過客止。
      • 第三十六章 將欲歙之,必固張之;將欲弱之,必固強之
      • 第三十七章 道常無為而無不為
      • 第三十八章 上德不德,是以有德;下德不失德,是以無德
      • 第三十九章 昔之得一者,天得一以清。不欲琭琭如玉,珞珞如石。
      • 第四十章 反者道之動,弱者道之用。天下萬物生於有,有生於無
      • 第四十一章 上士聞道,勤而行之;大方無隅,大器晚成,大音希聲,大象無形,道隱無名。
      • 第四十二章 道生一,一生二,二生三,三生萬物。
      • 第四十三章 天下之至柔,馳騁天下之至堅
      • 第四十四章 名與身孰親﹖身與貨孰多﹖得與亡孰病﹖
      • 第四十五章 大成若缺,其用不弊。大盈若沖,其用不窮。
      • 第四十六章 天下有道,卻走馬以糞。天下無道,戎馬生於郊。
      • 第四十七章 不出戶,知天下;不窺牖,見天道。
      • 第四十八章 為學日益,為道日損。損之又損,以至於無為。
      • 第四十九章 聖人無常心,以百姓心為心。
      • 第五十章 出生入死。生之徒,十有三;死之徒,十有三;人之生,動之死地,亦十有三。
      • 第五十一章 道生之,德畜之,物形之,勢成之。
      • 第五十二章 天下有始,以為天下母。以知其子,既知其子,復守其母,沒身不殆。
      • 第五十三章 使我介然有知,行於大道,唯施是畏。大道甚夷,而人好徑。
      • 第五十四章 善建者不拔,善抱者不脫,子孫以祭祀不輟。
      • 第五十五章 含德之厚,比於赤子。知和曰常,知常曰明。益生曰祥。心使氣曰強。
      • 第五十六章 知者不言,言者不知。
      • 第五十七章 以正治國,以奇用兵,以無事取天下。
      • 第五十八章 其政悶悶,其民淳淳;其政察察,其民缺缺。禍兮福之所倚,福兮禍之所伏。
      • 第五十九章 治人事天,莫若嗇。夫唯嗇,是謂早服
      • 第六十章 治大國,若烹小鮮。夫兩不相傷,故德交歸焉。
      • 第六十一章 大國者下流,天下之交。天下之牝,牝常以靜勝牡,以靜為下。
      • 第六十二章 道者萬物之奧。雖有拱璧以先駟馬,不如坐進此道。
      • 第六十三章 為無為,事無事,味無味。圖難於其易,為大於其細;
      • 第六十四章 合抱之木,生於毫末;九層之臺,起於累土;千里之行,始於足下。為者敗之,執者失之。
      • 第六十五章 古之善為道者,非以明民,將以愚之。
      • 第六十六章 是以欲上民,必以言下之。欲先民,必以身後之。
      • 第六十七章 天下皆謂我道大,似不肖。夫唯大,故似不肖。
      • 第六十八章 善為士者不武,善戰者不怒,善勝敵者不與
      • 第六十九章 吾不敢為主而為客,不敢進寸而退尺。禍莫大於輕敵,輕敵幾喪吾寶。
      • 第七十章 吾言甚易知,甚易行。天下莫能知,莫能行。
      • 第七十一章 知不知上,不知知病。夫唯病病,是以不病。
      • 第七十二章 民不畏威,則大威至。無狎其所居,無厭其所生。夫唯不厭,是以不厭。
      • 第七十三章 天之道,不爭而善勝,不言而善應,不召而自來,繟然而善謀。
      • 第七十四章 民不畏死,奈何以死懼之?若使民常畏死,而為奇者,吾得執而殺之,孰敢?
      • 第七十五章 民之饑,以其上食稅之多,是以饑。
      • 第七十六章 人之生也柔弱,其死也堅強。萬物草木之生也柔脆,其死也枯槁。
      • 第七十七章 天之道,其猶張弓與﹖高者抑之,下者舉之;有餘者損之,不足者補之。
      • 第七十八章 天下莫柔弱於水,而攻堅強者莫之能勝,以其無以易之。
      • 第七十九章 和大怨,必有餘怨,安可以為善﹖
      • 第八十章 小國寡民。使有什伯之器而不用,使民重死而不遠徙。
      • 第八十一章 信言不美,美言不信。天之道,利而不害;聖人之道,為而不爭。
    • 人類真相推廣協會

      • 人類真相介紹
      • 人生大挑戰-閱讀筆記
      • 書籍-人生大挑戰

        • 序文
        • 童年的回憶
        • 賺外快的童年
        • 養家的童年
        • 少年時期的回憶
        • 粉紅睡衣女鬼的祕密
        • 麵線、甘蔗和賽鴿
        • 我在黑社會的日子
        • 『台北一條龍』
        • 賭徒‧妻子‧盤仔人
        • 人鬼之戰—正邪不分的恐怖
        • 開展創業石銅雕畫的日子
        • 渡畜牲者‧瞎掰鬼與邪靈
        • 無所不在的陷阱—邪靈的詭計
        • 鬼屋‧符令‧大揭祕
        • 妖魔鬼怪大變身—邪靈與動物
        • 乩童與宮廟的祕密
        • 活鬼纏身的恐怖亂象
        • 前面親兄弟、後面無情義的假面
        • 前面手牽手、後面下毒手的險境
        • 人心險惡、五馬分屍所逼自殺的真相
        • 自殺後的奇遇—人死後的世界
        • 我自殺後的奇遇—「陰間地府處」與「陰府大本營」
        • 我被趕出家門、面臨眾叛親離的苦境
        • 其他
    • 英文學習

      • 自我介紹
      • 簡單寒暄
      • 指路
      • 買賣
      • 轉接電話
      • 通勤
      • 訂位
      • 數字
    • 金剛經 時間不存在?自我是虛擬?
    • 20250319 外婆過世
    • 說服的藝術:避免陷阱,建立共識
    • 禪修一定要去除「如何」嗎?
    • 不對稱的回報
    • 避免慢性壓力
    • 關鍵溝通表達力
    • 快樂的秘訣
    • 生活在現代社會,維持高品質思考的重要性
    • 心理學家的面相術:解讀情緒的密碼
    • 什麼是真相,真相是什麼
    • 身為一位歷史觀察者(文長慎入)
    • 2022 Leisure Learn
    • 兩年八個月,我從 Garena 畢業了
    • DeFi
    • 我的終生大事,交往到結婚
    • 轉職前端工程師 3 年多的回顧
    • MacOS + Iterm2 + Oh My Zsh
    • 我喜歡的名言佳句
    • Web Interview Preparation

2024 CSS 年度報告筆記

tags: CSS report 2024

Share On:

FacebookLINEMessengerTelegram

大家好~今天來個久違的 2024 CSS report 大補帖,好久沒有做 CSS 相關的系列了,時間都被 JS 吸乾拉~,今天要來一次把過去幾年 2022-2024 年的 3年中,重要的 CSS 革命性更新功能惡補及記錄下來!

因為是累積了 3年的份量,且我實在懶得切分成好幾篇文章紀錄(不想一直換頁找東西),所以整個新功能內容非常長,建議分批觀看,避免學習過多消化不良

注意!以下介紹的所有 feature,有些還在實驗開發階段,在正式環境使用之前,請確保前往相關 CSS 瀏覽器相容性查詢網站確認是否穩定可用!

Layout

Sub Grid

當使用 display: grid 時,只有直接指定的元素本身會成為網格區塊。這些元素的子元素則仍以正常流程顯示,雖然我們能夠再加入更多層 grid 子層,但這些子元素的 grid 與父層之間的 grid 並沒有關聯參照的能力,會導致子元素 grid 與父元素之間版面對齊的困難

如果在 grid-template-columns、grid-template-rows 或兩者上設定 subgrid,則 nested grid 將使用在父級上定義的軌道,而不是建立一個新的 grid

如下使用 grid-template-columns: subgrid 並且巢狀網格跨越父 grid 的三個列軌道,則巢狀網格將具有與父網格大小相同的三個列軌道

<div class="grid">
  <div class="item">
    <div class="subitem"></div>
  </div>
</div>

<style>
.grid {
  border: 2px solid #f76707;
  border-radius: 5px;
  background-color: #fff4e6;
}

.item {
  border: 2px solid #ffa94d;
  border-radius: 5px;
  background-color: #ffd8a8;
  color: #d9480f;
}

.subitem {
  background-color: rgb(40, 240, 83);
}

.grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(4, minmax(100px, auto));
}

.item {
  display: grid;
  grid-column: 2 / span 4;
  grid-row: 2 / 4;
  grid-template-columns: subgrid;
  grid-template-rows: repeat(3, 80px);
}

.subitem {
  grid-column: 1 / span 2;
  grid-row: 1 / 3;
}
</style>

注意,行編號在 subgrid 中會重新計算,因此 1 / span 2 是從子 grid 中的 1 開始算起

text-wrap

作為網頁切版主力的前端,過去在控制文字換行時常常手忙腳亂,一查就會跳出 word-break、word-wrap、overflow-wrap,頓時不知道到底要用哪個來做到需求(索幸全部亂加一通),以後可以透過 text-wrap 輕鬆讓瀏覽器自己去控制元素內文字的換行及美化方式!

  • 排版改進,例如跨標題的行長度更加平衡
  • 一種完全關閉文字換行的方法
text-wrap: wrap;
text-wrap: nowrap;
text-wrap: balance;
text-wrap: pretty;
text-wrap: stable;

詳細想知道怎麼更好處理文字換行可以參考這篇

@container query

類似於 @media 的能力,差別在 @media 針對 browser screen size,而 @container 針對 element size,總共有如下三種屬性

  • container-type、container-name、container,其中 container 是另外兩個的簡寫
    • container: <container-name> / <container-type>
    • container-type: normal, size, inline-size, scroll-state
    • container-name: 取你喜歡的名子
/* 當 component 元素寬度大於 350px 時套用樣式 */
.component {
  max-width: 400px;
  height: 200px;
  background: red;
  container: fancy / inline-size;
}

@container fancy (inline-size > 350px) {
  a {
    color: green;
  }
}

@layer - Cascade Layers

使用 CSS 時如果稍不注意,很容易發生樣式互相覆蓋的問題,或是必須使用 @important 去強制改寫覆蓋優先級,但更容易導致維護困難,此時就可以使用 @layer 定義層級的優先關係,方便後續管理,使用方式如下

  • 預先定義好層級關係,層級定義越下面的優先,此處即使 B 層級中使用了 id selector,但因為 C 層級位於更下方,具有更高優先級,所以最終會是 green 而不是 blue 套用
<div id="app"></div>

<style>
@layer A, B, C;

@layer A {
  div {
    background-color: red;
  }
}

@layer B {
  #app {
    background-color: blue;
  }
}

@layer C {
  div {
    background-color: green;
  }
}
</style>

Media Query Ranges

過去在設定 @media 的大小範圍時常常需要像下面這樣,結合 min-width, max-width 使用,既沒有效率也很冗長

@media (max-width: 750px) {
	/* */
}
@media (min-width: 750px) {
  /* */
}
@media (min-width: 375px) and (max-width: 750px) {
  /* */
}

現在可以寫成這樣

@media (width <= 750px) {
	/* */
}
@media (width >= 750px) {
  /* */
}
@media (375px <= width <= 750px) {
  /* */
}

Media Query Update

更新媒體查詢讓我們能根據用戶裝置的螢幕刷新率提供不同的樣式套用,格式如下

  • none, slow, fast
@media (update: < none | slow | fast >) {
  /* styles to apply if the update frequency of the output device is a match */
}
@keyframes jiggle {
  from {
    transform: translateY(0);
  }

  to {
    transform: translateY(25px);
  }
}

@media (update: fast) {
  p {
    animation: 1s jiggle linear alternate infinite;
  }
}

Media Query Scripting

過去我們需要使用 html 的 nojs script 來判斷環境是否支援 javascript,而在 CSS 中我們可以透過 @media 輕鬆做到,格式如下

@media (scripting: < none, initial-only, enabled >) {
  /* styles to apply in specific script support environment */
}

@scope

@scope 讓我們能選擇特定 DOM 子樹中的元素,精確定位元素範圍,而無需編寫難以覆蓋的過於特定的選擇器,並且不會將選擇器與 DOM 結構耦合得太緊密,格式如下

@scope (scope root) to (scope limit) {
  rulesets
}
  • 假設我們有一個 DOM 結構,並且需要指定 section.article-body 中的 img 添加樣式,我們可能會寫成
    • .feature > .article-body > img: 這樣寫太特定,導致後續樣式難以覆蓋,並且與 DOM 結構耦合過高,後續調整結構後必須相應來調整 CSS 否則會出問題
    • .feature img: 這樣寫太鬆散,會匹配到所有 image
<article class="feature">
  <section class="article-hero">
    <img />
  </section>
  <section class="article-body">
    <h3></h3>
    <p></p>
    <img />
    <figure>
      <img />
      <figcaption></figcaption>
    </figure>
  </section>
</article>

此時就可以用 @scope 改寫如下,指定起點範圍是 .article-body,終點(不包含其中)figure,我們就可以只匹配到 .article-body 中的 img,而不包含到 figure 裡的 img,提升了匹配的效率與彈性

@scope (.article-body) to (figure) {
  img {
    border: 5px solid black;
    background-color: goldenrod;
  }
}

Anchor Positioning 錨點定位

  • MDN Document 此功能讓開發者能精準設定兩個元素的相對位置,使用 anchor-name、position-anchor 及 position-area 快速定位元素位置

下面範例文字是在圖片之前,但透過錨點定位到圖片下方居中

<span class="anchor-el">Pretty Girl</span>
<img class="anchor-to" src="img.jpg" />

<style>
.anchor-to {
  anchor-name: --myimg;
  width: 200px;
}

.anchor-el {
  position: fixed;
  position-anchor: --myimg;
  position-area: bottom center;
}
</style>

Animations

@property - Custom Property 自定義屬性

  • MDN Document@property rule 讓開發者可以直接在樣式表中註冊自訂屬性,無需執行任何 JavaScript,允許對屬性類型檢查和約束、設定預設值以及定義自訂屬性是否可以繼承值,自定義屬性名稱以 -- 開頭,後面跟著使用者定義的名稱,且需要區分大小寫
@property --rotation {
  syntax: "<angle>";
  inherits: false;
  initial-value: 45deg;
}
  • 以下範例,定義了兩個 custom 屬性 --item-size, --item-color,後者沒有自動繼承父層
@property --item-size {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 40%;
}

@property --item-color {
  syntax: "<color>";
  inherits: false;
  initial-value: "aqua";
}

.container {
  display: flex;
  height: 200px;
  border: 1px dashed black;

  /* 父元素設定 custom property values */
  --item-size: 20%;
  --item-color: orange;
}

/* 子元素設定 custom properties */
.item {
  width: var(--item-size);
  height: var(--item-size);
  background-color: var(--item-color);
}

/* 個別設定子元素 custom property values */
.two {
  --item-size: initial;
  --item-color: inherit;
}

.three {
  /* 不合法值 */
  --item-size: 1000px;
  --item-color: xyz;
}

Transition Behavior 離散屬性動畫

  • MDN Document
  • transition-behavior: normal | allow-discrete; 這個屬性可以讓元素屬性具有在兩個或以上的狀態間變化的能力,例如 display, content-visibility 可以在 50% 處過度屬性,而不總是 0, 100%

@starting-style

這個屬性主要針對元素進入畫面時套用樣式,除了元素初次渲染以外,由 display: none 切換顯示的元素也可以使用,透過 @starting-style 搭配上面的 transition-behavior: allow-discrete 我們可以製作一個簡單的元素原生 fade in/out 效果如下,不再需要 setTimeout 手動處理了:

function App() {
  const [show, setShow] = useState(true);
  return (
    <div>
      <div id="box" className={show ? '' : 'hide'}></div>
      <button onClick={() => setShow(!show)}>Toggle</button>
    </div>
  );
}
#box {
  width: 50px;
  height: 50px;
  background: red;
  transition-property: display, opacity;
  transition-duration: 250ms;
  transition-behavior: allow-discrete;
}

#box.hide {
  display: none;
  opacity: 0;
}

@starting-style {
  #box {
    opacity: 0;
  }
}

overlay 屬性

  • MDN Document
  • overlay: auto|none; 這個屬性指定元素是否已 top layer 的形式出現(比如 popover 及 dialog 元素),使用時需搭配上面提到的 transition-behavior: allow-discrete; 才能製作 overlay 的 transition 效果,要注意的是 overlay 只能由瀏覽器設定,開發者樣式無法更改任何元素的overlay 值

高度 transition

有兩種方式做到,一個是使用 interpolate-size,第二種是透過 calc-size(),其中第二種在使用時預設會自動套用 interpolate-size: allow-keywords 的效果

interpolate-size

可以選擇在 root 上全局開啟功能,或是針對特定 scope 套用

:root {
  interpolate-size: allow-keywords;
}
/* or */
main {
  interpolate-size: allow-keywords;
}

之後就可以在全局或指定 scope 中使用 height transition

<section tabindex="0">
  <header>
    <h2>Tanuki</h2>
  </header>
  <main>
    <p>Tanuki is the silent phantom of MDN.</p>
    <ul>
      <li><strong>Height</strong>: 3.03m</li>
      <li><strong>Weight</strong>: 160kg</li>
      <li><strong>Tech Fu</strong>: 7</li>
      <li><strong>Bad Jokes</strong>: 9</li>
    </ul>
  </main>
</section>

<style>
section {
  height: 2.5rem;
  overflow: hidden;
  transition: height ease 1s;
}

section:hover,
section:focus {
  height: max-content;
}
</style>

calc-size([calc-size-basis], [calc-sum])

  • MDN Document 這個函數允許我們使用內建尺寸進行運算(比如 auto, fix-content, max-content),常見的 calc() 函數不支援這個功能。
/* Pass a value through calc-size() */
calc-size(auto, size)
calc-size(fit-content, size)

/* Perform a calculation */
calc-size(min-content, size + 100px)
calc-size(fit-content, size / 2)

/* Calculation including a function */
calc-size(auto, round(up, size, 50px))

.container:hover p {
  height: calc-size(min-content, size + 200px);
}

CSS Cross-Document View Transitions 過場動畫

跨文檔的視圖過渡 (View Transitions) 讓我們能輕易在不同 document page 之間套用轉場動畫,詳細設定可透過 js 進行更精準控制,會另一篇介紹 View Transitions - 認識並使用原生 document 轉場效果

  • 最簡單的方式,只要兩個 page 是在同源的情況下(same-origin)
@view-transition {
  navigation: auto;
}

CSS Scroll-Driven Animations 滾動驅動動畫

  • MDN Document

    • animation-timeline
    • JS ScrollTimeline 與後續會介紹的 JS 的 ScrollTimeline 有關,這邊是介紹透過純 CSS 的 animation-timeline 對滾動元素添加動畫
  • 指定特定滾動元素 scroll-timeline-name 定義一個 scroll timeline 名稱,再透過 animation-timeline 指定動畫的元素套用某個 scroll-timeline,也可以直接使用 scroll() 建立匿名 scroll timeline 使用,這個情況下預設 scroll() 等於 scroll(block nearest)

<div id="container">
  <div id="square"></div>
  <div id="stretcher"></div>
</div>

<style>
#container {
  position: relative;
  height: 300px;
  overflow-y: scroll;
  scroll-timeline-name: --squareTimeline;
}

#stretcher {
  height: 600px;
}

#square {
  background-color: deeppink;
  width: 100px;
  height: 100px;
  margin-top: 100px;
  animation-name: rotateAnimation;
  animation-duration: 1ms; /* Firefox requires this to apply the animation */
  animation-direction: alternate;
  animation-timeline: --squareTimeline; /* Named */
  /* or */
  animation-timeline: scroll(); /* Anonymous */

  position: absolute;
  bottom: 0;
}

@keyframes rotateAnimation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>
  • 全畫面滾動套用使用則設定 view-timeline-name,或是用 view() 匿名定義立即使用
svg {
  animation: scrollin linear;
  view-timeline-name: --subjectReveal;
  animation-timeline: --subjectReveal;
  /* or */
  animation-timeline: view();
}

@keyframes scrollin {
  0% {
    scale: 1;
  }
  50% {
    scale: 10;
  }
  80%,
  100% {
    scale: 800;
  }
}

Pseudo-classes

:has(selector)

接受一個 selector,並給有匹配子元素的父類樣式

  • 匹配包含 a 子元素的 div 元素
div:has(a) {
  color: blue;
}

:nth-child(nth [of complex-selector-list]?)

透過加入 of,可以在進行 nth filter 前先篩選一次,比如下方將 .note 的元素先過濾出後才進行 nth 內容樣式套用

function App() {
  return (
    <ul>
      {Array(20).fill(1).map((_, i) => (
        <li className={i <= 10 ? 'noted' : ''}>{i + 1}</li>
      ))}
    </ul>
  );
}
li:nth-child(even of .noted) {
  background-color: tomato;
}

:user-valid 和 :user-invalid

兩者行為類似 :valid 和 :invalid,但只有在使用者進行交互後才會匹配檢查,至此再也不用自己追蹤輸入狀態進行手動檢查拉!~

input:user-valid,
select:user-valid,
textarea:user-valid {
  --state-color: green;
  --bg: linear-gradient(45deg in oklch, lime, #02c3ff);
}

input:user-invalid,
select:user-invalid,
textarea:user-invalid {
  --state-color: red;
  --bg: linear-gradient(15deg in oklch, #ea00ff, #ffb472);
}

Components

popover

這個組件在之前的文章中有詳細介紹,有興趣的可以前往看看 來試用看看原生 Web Popover API

select 分隔線

現在可以在 select 中使用 <hr> 渲染分隔線,比如

<select name="majors" id="major-select">
  <option value="">Select a favorite feature</option>
  <hr>
  <optgroup label="Foundations">
    <option value="trig">Trigonometric functions</option>
    <option value="nth">Complex nth-* selection</option>
    <option value="nesting">Nesting</option>
    <option value="subgrid">Subgrid</option>
    <option value="mq-ranges">Media query range syntax</option>
  </optgroup>
  <optgroup label="Typography">
    <option value="initial-letter">Initial-letter</option>
    <option value="text-wrap-b-p">Text-wrap: balance / pretty</option>
  </optgroup>
  <optgroup label="Color">
    <option value="color-4">CSS Color level 4</option>
    <option value="color-mix">Color-mix function</option>
    <option value="rcs">Relative color syntax</option>
  </optgroup>
  <optgroup label="Responsive Design">
    <option value="cq">Size container queries</option>
    <option value="sq">Style container queries</option>
    <option value="has">:has() selector</option>
  </optgroup>
</select>

Exclusive Accordion 獨家手風琴

<details> 給一個 name 屬性即可讓相同 name 值的 details 元素彼此連動,當開啟其中一個時,已開啟的分頁將會被自動關閉

<details name="my-accordion">
  <summary>Summary 1</summary>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</details>

<details name="my-accordion" open>
  <summary>Summary 2</summary>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</details>

<details name="my-accordion">
  <summary>Summary 3</summary>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</details>

客製化 details 元素樣式

現在可以對 details 元素加上自定義樣式調整外觀

  • ::marker 隱藏 detail 的 icon
::marker {
  content: '';
}
  • [open] 設定打開的樣式
details[open] p {
  color: red;
}
  • ::details-content 設定開啟時效果,以下搭配前面學到的 interpolate-size 及 transition-behavior 就可以製作出一款堪用的原生獨家手風琴配上開闔的動畫
:root {
  interpolate-size: allow-keywords;
}

details[open] p {
  color: red;
}

details::details-content {
  height: 0;
  overflow: hidden;
  transition-property: height, content-visibility;
  transition-behavior: allow-discrete;
  transition-duration: 0.5s;
}

details[open]::details-content {
  height: auto;
}

JS related

View Transitions

除了上面提到的 CSS 畫面轉場效果,更多進階內容將涉及 Javascript,獨立一篇記錄在這View Transitions - 認識並使用原生 document 轉場效果

ScrollTimeline

此 API 可以讓開發者獲取元素的滾動進度,結合 JS Animate 或 CSS Animation 做到將動畫與滾動進度綁定的效果,內容涉及較長,詳細可參考這篇 MDN - ScrollTimeline

Others

Nested CSS 嵌套

這在過去使用 SASS 的年代想都不敢想,原生 CSS 居然能支援嵌套語法!!

.blog {
  position: relative;
  padding: 1rem;

  .blog-item {
    width: 100%;
    & span {
      font-size: 1rem;
    }
  }
}

Accent Color

accent-color 可以調整指定區塊內的表單預設樣式

<ul className="component" style={{ accentColor: 'red' }}>
  <li>
    <input type="checkbox" checked />
  </li>
  <li>
    <input type="radio" checked />
  </li>
  <li>
    <input type="range" />
  </li>
  <li>
    <progress value="0.8"></progress>
  </li>
</ul>

CSS Function

除了過去的 css function 之外,還新增了 color-mix(), sin(), cos(), tan(), asin(), acos(), atan(), atan2(),以及擴展了一些過去的函數比如 rgb()、hsl()、hwb()

  • color-mix: 混色功能
.text {
  color: color-mix(in lch, purple 50%, plum 50%);
  color: color-mix(in lch, plum, purple);
}
  • 三角函數相關 sin(), cos()...,加強 CSS 動畫計算能力
div.box-1 {
  transform: rotate(atan2(3, 4)); /* atan2(y, x) */
}

References

  • CSS 和網頁版 UI 最新動態:2024 年 I/O 大會重點回顧
  • 為何我放棄 SASS 轉用原生 CSS
  • 2023 年 CSS 新特性大盤點
最近更新: 2025/6/1 下午2:35
Contributors: johnnywang, Lindy Liao
Next
2021 CSS 年度報告筆記