├── .gitignore ├── .vscode ├── extensions.json └── launch.json ├── CONTRIBUTING ├── LICENSE ├── README.md ├── astro.config.mjs ├── package-lock.json ├── package.json ├── public ├── authors │ ├── argyle.jpg │ ├── barry.jpg │ ├── bramus.jpg │ ├── rachel.jpg │ └── una.jpg ├── baseline-status.min.js ├── biomes │ ├── arctic.png │ ├── arctic.svg │ ├── cyberspace-header.png │ ├── cyberspace-sidebar.png │ ├── cyberspace.png │ ├── cyberspace.svg │ ├── desert.png │ ├── desert.svg │ ├── jungle.png │ └── jungle.svg ├── cactus.svg ├── favicon.svg ├── fight.otf ├── fight.woff2 ├── hero-video-poster.jpg ├── images │ ├── ruby-align.png │ ├── ruby_after.png │ └── ruby_before.png ├── social.png ├── track-grunge.svg └── video │ ├── anchoring.mp4 │ ├── anchoring.png │ ├── animate-to-auto.mp4 │ ├── animated-details-accordion.mp4 │ ├── animated-details-horizontal.mp4 │ ├── cross-document-view-transitions.mp4 │ ├── cross-document-view-transitions.png │ ├── field-sizing.mp4 │ ├── field-sizing.png │ ├── line-clamp-auto.mp4 │ ├── line-clamp-number.mp4 │ ├── line-clamp-transition.mp4 │ ├── paint-order.mp4 │ ├── paint-order.png │ ├── scrollbar-color.mp4 │ ├── snap-change.mp4 │ ├── snap-change.png │ ├── snap-changing.mp4 │ └── snap-changing.png ├── src ├── components │ ├── author.astro │ ├── authors.astro │ ├── biome.astro │ ├── biomes.astro │ ├── codepen.astro │ ├── cookieconsent.astro │ ├── feature.filmstrip.astro │ ├── feature.title.astro │ ├── footer.astro │ ├── hero.astro │ ├── intro.astro │ ├── nav.aside.astro │ ├── nav.bento.astro │ ├── nav.primary.astro │ ├── theme.switch.astro │ ├── video.astro │ └── youtube.astro ├── data │ └── authors.json ├── env.d.ts ├── features │ ├── _layout.astro │ ├── components │ │ ├── anchor-positioning.astro │ │ ├── animate-to-height-auto.astro │ │ ├── exclusive-details.astro │ │ ├── field-sizing.astro │ │ └── styleable-details.astro │ ├── developerexperience │ │ ├── at-property.astro │ │ ├── backdrop-inheritance.astro │ │ ├── cssom-nested-declarations.astro │ │ ├── light-dark.astro │ │ ├── paint-order.astro │ │ ├── popover.astro │ │ ├── ruby-align.astro │ │ └── starting-style.astro │ └── interactions │ │ ├── scroll-driven-animations.astro │ │ ├── scroll-snap-events.astro │ │ ├── scrollbar-styling.astro │ │ └── view-transitions-mpa.astro ├── icons │ ├── book.svg │ ├── check.svg │ ├── chrome.svg │ ├── close.svg │ ├── css.svg │ ├── dino.svg │ ├── down-arrow.svg │ ├── feedback.svg │ ├── github.svg │ ├── hamburger.svg │ ├── home.svg │ ├── play.svg │ └── star.svg ├── pages │ └── index.astro ├── styles │ ├── code.css │ ├── global.css │ └── utilities.css └── util │ ├── shuffle.ts │ └── slugify.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | 23 | # jetbrains setting folder 24 | .idea/ 25 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We'd love to accept your patches and contributions to this project. 4 | 5 | ## Before you begin 6 | 7 | ### Sign our Contributor License Agreement 8 | 9 | Contributions to this project must be accompanied by a 10 | [Contributor License Agreement](https://cla.developers.google.com/about) (CLA). 11 | You (or your employer) retain the copyright to your contribution; this simply 12 | gives us permission to use and redistribute your contributions as part of the 13 | project. 14 | 15 | If you or your current employer have already signed the Google CLA (even if it 16 | was for a different project), you probably don't need to do it again. 17 | 18 | Visit to see your current agreements or to 19 | sign a new one. 20 | 21 | ### Review our community guidelines 22 | 23 | This project follows 24 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). 25 | 26 | ## Contribution process 27 | 28 | ### Code reviews 29 | 30 | All submissions, including submissions by project members, require review. We 31 | use GitHub pull requests for this purpose. Consult 32 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 33 | information on using pull requests. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS Wrapped 2024 2 | 3 | Source code for CSS Wrapped 2024 – https://chrome.dev/css-wrapped-2024/ 4 | 5 | ## Development 6 | 7 | Spin up with `npm start` 8 | 9 | ## Deploying to production 10 | 11 | To deploy, invoke `npm run deploy`. 12 | 13 | This will build the project to `./dist` with the `--base` flag set to `css-wrapped-2024`, and then upload the files to the `chrome-dev-demos` bucket. 14 | 15 | Only Googlers with sufficient permissions can deploy to `chrome.dev`. Make sure you are authenticated with `gcloud auth login`. 16 | 17 | ## License 18 | 19 | This project is released under the Apache 2.0 License. See the enclosed [`LICENSE`](./LICENSE) for details. 20 | 21 | ## Contributing 22 | 23 | We'd love to accept your patches and contributions to this project. See the enclosed [`CONTRIBUTING`](./CONTRIBUTING) for details. -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | import { defineConfig } from "astro/config"; 7 | import { fileURLToPath, URL } from 'node:url'; 8 | import icon from "astro-icon"; 9 | 10 | export default defineConfig({ 11 | devToolbar: { 12 | enabled: false 13 | }, 14 | integrations: [icon()], 15 | vite: { 16 | resolve: { 17 | alias: { 18 | '@public': fileURLToPath(new URL('./public', import.meta.url)), 19 | } 20 | } 21 | } 22 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-wrapped-2024", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro check && astro build", 9 | "preview": "astro preview", 10 | "astro": "astro", 11 | "deploy": "gsutil -m rsync -rd dist gs://chrome-dev-demos/public/css-wrapped-2024", 12 | "predeploy": "astro check && astro build --base css-wrapped-2024" 13 | }, 14 | "license": "Apache-2.0", 15 | "dependencies": { 16 | "@astrojs/check": "^0.9.4", 17 | "astro": "^4.16.15", 18 | "astro-icon": "^1.1.4", 19 | "lite-youtube-embed": "^0.3.3", 20 | "open-props": "^1.7.8", 21 | "typescript": "^5.7.2" 22 | } 23 | } -------------------------------------------------------------------------------- /public/authors/argyle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/authors/argyle.jpg -------------------------------------------------------------------------------- /public/authors/barry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/authors/barry.jpg -------------------------------------------------------------------------------- /public/authors/bramus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/authors/bramus.jpg -------------------------------------------------------------------------------- /public/authors/rachel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/authors/rachel.jpg -------------------------------------------------------------------------------- /public/authors/una.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/authors/una.jpg -------------------------------------------------------------------------------- /public/biomes/arctic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/biomes/arctic.png -------------------------------------------------------------------------------- /public/biomes/cyberspace-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/biomes/cyberspace-header.png -------------------------------------------------------------------------------- /public/biomes/cyberspace-sidebar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/biomes/cyberspace-sidebar.png -------------------------------------------------------------------------------- /public/biomes/cyberspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/biomes/cyberspace.png -------------------------------------------------------------------------------- /public/biomes/desert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/biomes/desert.png -------------------------------------------------------------------------------- /public/biomes/jungle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/biomes/jungle.png -------------------------------------------------------------------------------- /public/cactus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 12 | -------------------------------------------------------------------------------- /public/fight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/fight.otf -------------------------------------------------------------------------------- /public/fight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/fight.woff2 -------------------------------------------------------------------------------- /public/hero-video-poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/hero-video-poster.jpg -------------------------------------------------------------------------------- /public/images/ruby-align.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/images/ruby-align.png -------------------------------------------------------------------------------- /public/images/ruby_after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/images/ruby_after.png -------------------------------------------------------------------------------- /public/images/ruby_before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/images/ruby_before.png -------------------------------------------------------------------------------- /public/social.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/social.png -------------------------------------------------------------------------------- /public/track-grunge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /public/video/anchoring.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/anchoring.mp4 -------------------------------------------------------------------------------- /public/video/anchoring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/anchoring.png -------------------------------------------------------------------------------- /public/video/animate-to-auto.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/animate-to-auto.mp4 -------------------------------------------------------------------------------- /public/video/animated-details-accordion.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/animated-details-accordion.mp4 -------------------------------------------------------------------------------- /public/video/animated-details-horizontal.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/animated-details-horizontal.mp4 -------------------------------------------------------------------------------- /public/video/cross-document-view-transitions.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/cross-document-view-transitions.mp4 -------------------------------------------------------------------------------- /public/video/cross-document-view-transitions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/cross-document-view-transitions.png -------------------------------------------------------------------------------- /public/video/field-sizing.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/field-sizing.mp4 -------------------------------------------------------------------------------- /public/video/field-sizing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/field-sizing.png -------------------------------------------------------------------------------- /public/video/line-clamp-auto.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/line-clamp-auto.mp4 -------------------------------------------------------------------------------- /public/video/line-clamp-number.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/line-clamp-number.mp4 -------------------------------------------------------------------------------- /public/video/line-clamp-transition.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/line-clamp-transition.mp4 -------------------------------------------------------------------------------- /public/video/paint-order.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/paint-order.mp4 -------------------------------------------------------------------------------- /public/video/paint-order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/paint-order.png -------------------------------------------------------------------------------- /public/video/scrollbar-color.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/scrollbar-color.mp4 -------------------------------------------------------------------------------- /public/video/snap-change.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/snap-change.mp4 -------------------------------------------------------------------------------- /public/video/snap-change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/snap-change.png -------------------------------------------------------------------------------- /public/video/snap-changing.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/snap-changing.mp4 -------------------------------------------------------------------------------- /public/video/snap-changing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-wrapped-2024/ce996350d757a7e9372e4d25b35a7482af07194c/public/video/snap-changing.png -------------------------------------------------------------------------------- /src/components/author.astro: -------------------------------------------------------------------------------- 1 | --- 2 | interface Props { 3 | name: string; 4 | } 5 | 6 | import authors from './../data/authors.json'; 7 | 8 | const { name } = Astro.props; 9 | const author = authors[name]; 10 | --- 11 | 12 |
13 | Profile picture 20 | 21 |
22 | 23 | 39 | -------------------------------------------------------------------------------- /src/components/authors.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import authors from './../data/authors.json'; 3 | 4 | const authorKeys = Object.keys(authors); 5 | const authorInfo = Object.values(authors); 6 | --- 7 | 8 |
9 | {authorInfo.map((author, index) => {author.name}{`Profile)} 10 |
11 | 12 | -------------------------------------------------------------------------------- /src/components/biome.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import slugify from "./../util/slugify"; 3 | const { title, image, alt, description, features } = Astro.props; 4 | --- 5 | 6 |
7 | {alt} 8 |
9 |

10 | # 11 | {title} 12 |

13 |

14 |

15 |
16 |
17 |
18 | { 19 | features.map((Feature) => ( 20 |
23 | 24 |
25 | )) 26 | } 27 |
28 |
29 | 30 | 131 | -------------------------------------------------------------------------------- /src/components/biomes.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { biomes } = Astro.props; 3 | import slugify from "./../util/slugify"; 4 | import Biome from "../components/biome.astro"; 5 | --- 6 | 7 |
8 | { 9 | biomes.map((biome) => { 10 | return ( 11 |
15 | 16 |
17 | ); 18 | }) 19 | } 20 |
21 | 22 | 45 | -------------------------------------------------------------------------------- /src/components/codepen.astro: -------------------------------------------------------------------------------- 1 | --- 2 | interface Props { 3 | id: string; 4 | width?: number; 5 | height?: number; 6 | title?: string; 7 | } 8 | 9 | const { id, height = 300, title = 'CodePen demo' } = Astro.props; 10 | const [ user, hash ] = id.split('/'); 11 | const src = `https://codepen.io/${user}/embed/${hash}?default-tab=result`; 12 | const url = `https://codepen.io/${user}/pen/${hash}`; 13 | 14 | --- 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/cookieconsent.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | 6 | 54 | -------------------------------------------------------------------------------- /src/components/feature.filmstrip.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import slugify from "./../util/slugify"; 3 | 4 | const { biomes } = Astro.props; 5 | 6 | // Flatten all Biome features to one flat array 7 | const features = biomes 8 | .reduce((features, biome) => [...features, ...biome.features], []) 9 | .map((feature) => feature.title); 10 | --- 11 | 12 |
13 |
14 |

{biomes[0].features.length} Component Features

15 |
16 | { 17 | biomes[0].features.map((feature) => ( 18 | 23 | )) 24 | } 25 |
26 |
27 |
28 |

{biomes[1].features.length} Interaction Features

29 |
40 |
41 |
42 |

{biomes[2].features.length} Developer Experience Features

43 |
54 |
55 |
56 | 57 | 207 | -------------------------------------------------------------------------------- /src/components/feature.title.astro: -------------------------------------------------------------------------------- 1 | --- 2 | interface Props { 3 | slug: string; 4 | title: string; 5 | shorttitle?: string; 6 | } 7 | 8 | const { slug, title, shorttitle } = Astro.props; 9 | 10 | --- 11 | 12 |

# {shorttitle && }

13 | 14 | -------------------------------------------------------------------------------- /src/components/footer.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Authors from "./authors.astro"; 3 | --- 4 | 5 | 23 | 24 | 87 | -------------------------------------------------------------------------------- /src/components/hero.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Icon } from "astro-icon/components"; 3 | import NavBento from "./nav.bento.astro"; 4 | import Intro from "./intro.astro"; 5 | import Youtube from "./youtube.astro"; 6 | 7 | const { biomes } = Astro.props; 8 | const totalFeatures = biomes.reduce((total, biome) => { 9 | return (total += biome.features.length); 10 | }, 0); 11 | --- 12 | 13 |
14 |
15 |

CSS Wrapped 2024

16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 | {/* if changing the Video, then update the preload of the image in index.astro */} 42 | 43 |
44 |
45 |
46 |

47 | Chrome and in 2024 journeyed
48 | through the forest, over the mountains, and across the seas… 49 |

50 |
51 |
52 |
53 | 54 |
55 | 56 | 57 | 58 |
59 |

Join the Chrome DevRel team and a skateboarding Chrome Dino on a journey through the latest CSS launched for Chrome and the web platform in 2024, highlighting {totalFeatures} new features

60 |
61 | 62 |
63 |
64 |
65 |
66 |
67 | 68 | 96 | 97 | 351 | -------------------------------------------------------------------------------- /src/components/intro.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Icon } from "astro-icon/components"; 3 | --- 4 | 5 |
6 |

7 | 2024 has been another amazing year for CSS! 8 |

9 | 10 |

11 | Cross-document view transitions and scroll-driven animations let you add 12 | more interactivity to your applications with a few lines of CSS. You can now 13 | animate to height: auto;, style scrollbars, and size text 14 | inputs to their contents. 15 |

16 | 17 |

18 | Many features have become Baseline Newly Available this year with exclusive accordions, @property, popover, and @starting-style all interoperable across major browsers. 24 |

25 | 26 |

27 | Thanks to the hard work by browser engineers, specification writers, and the 28 | input of the community, CSS has taken another great leap forward this year. 29 |

30 | 31 |
32 |
34 | 35 |

Scroll down to explore these exciting additions to the platform.

36 |
37 | 38 | 71 | -------------------------------------------------------------------------------- /src/components/nav.aside.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Icon } from "astro-icon/components"; 3 | import slugify from "./../util/slugify"; 4 | 5 | const { biomes } = Astro.props; 6 | --- 7 | 8 | 84 | 85 | 128 | 129 | 236 | 237 | 591 | 592 | 625 | -------------------------------------------------------------------------------- /src/components/nav.bento.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { biomes } = Astro.props; 3 | 4 | const counts = { 5 | components: biomes[0].features.length, 6 | interactions: biomes[1].features.length, 7 | developerExperience: biomes[2].features.length, 8 | }; 9 | --- 10 | 11 | 30 | 31 | 128 | -------------------------------------------------------------------------------- /src/components/nav.primary.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Icon } from "astro-icon/components"; 3 | import ThemeSwitch from "./theme.switch.astro"; 4 | --- 5 | 6 | 21 | 22 | 75 | -------------------------------------------------------------------------------- /src/components/theme.switch.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | 71 | 72 | 109 | 110 | 133 | 134 | 257 | -------------------------------------------------------------------------------- /src/components/video.astro: -------------------------------------------------------------------------------- 1 | --- 2 | interface Props { 3 | src: string; 4 | width?: number; 5 | height?: number; 6 | poster?: string; 7 | preload?: string; 8 | } 9 | 10 | const { src, width = 720, height = 480, poster = "", preload = "metadata" } = Astro.props; 11 | --- 12 | 13 | 27 | 28 | 54 | -------------------------------------------------------------------------------- /src/components/youtube.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import 'lite-youtube-embed/src/lite-yt-embed.css'; 3 | 4 | interface Props { 5 | id: string; 6 | width?: number; 7 | height?: number; 8 | poster?: string; 9 | } 10 | 11 | const { 12 | id, 13 | width = 560, 14 | height = 315, 15 | poster, 16 | } = Astro.props; 17 | const posterURL = poster || `https://i.ytimg.com/vi/${id}/hqdefault.jpg`; 18 | const embedURL = `https://www.youtube.com/embed/${id}`; 19 | const watchURL = `https://youtube.com/watch?v=${id}`; 20 | --- 21 | 22 | 23 | 24 | 25 | 26 | Play Video 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/data/authors.json: -------------------------------------------------------------------------------- 1 | { 2 | "adam": { 3 | "name": "Adam Argyle", 4 | "url": "https://developer.chrome.com/authors/adam-argyle", 5 | "image": "./authors/argyle.jpg" 6 | }, 7 | "bramus": { 8 | "name": "Bramus", 9 | "url": "https://developer.chrome.com/authors/bramus", 10 | "image": "./authors/bramus.jpg" 11 | }, 12 | "rachel": { 13 | "name": "Rachel Andrew", 14 | "url": "https://developer.chrome.com/authors/rachel-andrew", 15 | "image": "./authors/rachel.jpg" 16 | }, 17 | "barry": { 18 | "name": "Barry Pollard", 19 | "url": "https://developer.chrome.com/authors/barry-pollard", 20 | "image": "./authors/barry.jpg" 21 | }, 22 | "una": { 23 | "name": "Una Kravets", 24 | "url": "https://una.im", 25 | "image": "./authors/una.jpg" 26 | } 27 | } -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | /// 7 | -------------------------------------------------------------------------------- /src/features/_layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | interface Props { 3 | slug: string; 4 | } 5 | 6 | const { slug } = Astro.props; 7 | --- 8 | 9 |
10 | 11 |
12 | 13 | 197 | -------------------------------------------------------------------------------- /src/features/components/anchor-positioning.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "Anchor Positioning"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | 16 | 17 | <div class="support"> 18 | <baseline-status featureId="anchor-positioning"></baseline-status> 19 | </div> 20 | <p> 21 | Anchoring is a fresh and declarative way to position elements relative to 22 | each other. It's perfect for menus, tooltips, selects, labels, cards, 23 | settings dialogs, and many more. With anchor positioning built into the 24 | browser, you can build layered user interfaces without relying on 25 | third-party libraries. 26 | </p> 27 | <p> 28 | It takes two elements to create an anchor relationship: the <b>anchor</b> and 29 | <b>positioned element(s)</b>. 30 | </p> 31 | <p> 32 | The <b>anchor</b> is the element that the positioned elements orient to. Turn 33 | an element into an anchor with one line of CSS: 34 | </p> 35 | <Code 36 | lang="css" 37 | theme="css-variables" 38 | code={`.anchor { 39 | anchor-name: --over-easy; 40 | }`} 41 | /> 42 | <p> 43 | The <b>positioned elements</b> are the elements that are positioned relative 44 | to the anchor. These point to the anchor they want to be positioned relative 45 | to with <code>position-anchor</code> and a second line of CSS to specify the 46 | side or area the positioned should be in. 47 | </p> 48 | <Code 49 | lang="css" 50 | theme="css-variables" 51 | code={`.positioned-element { 52 | position: fixed; 53 | position-anchor: --over-easy; 54 | position-area: block-end; 55 | }`} 56 | /> 57 | 58 | <p>In the following demo, the cute egg is the anchor and the text "Over-Easy" is the positioned element.</p> 59 | 60 | <CodePen id="web-dot-dev/wBwKpmP" height={700} /> 61 | 62 | <p>The <code>position-area</code> property offers all sorts of options! The demo uses the logical property value <code>block-end</code>, but there's <code>center</code >, <code>button</code>, and tons more. Una made a GUI to help you visualize the options:</p> 63 | 64 | <Video src="./video/anchoring.mp4" width={1280} height={720} poster="./video/anchoring.png" preload="none" /> 65 | 66 | <div class="resources"> 67 | <p> 68 | <Icon name="book" title="Book Icon"aria-hidden="true" /> 69 | Resources: 70 | </p> 71 | <ul> 72 | <li> 73 | <a href="http://anchor-tool.com/">anchor-tool.com</a> — Una's GUI 74 | </li> 75 | <li> 76 | <a href="https://www.youtube.com/watch?v=ASb9vO3ARHo" 77 | >Over-Easy Mini Web Machine</a 78 | > — CSS anchor + popover 79 | </li> 80 | </ul> 81 | </div> 82 | <Author name="adam" /> 83 | <footer> 84 | <a href="https://codepen.io/collection/ExkRWw">Try demos</a> 85 | <div class="articles"> 86 | <a href="https://developer.chrome.com/blog/anchor-positioning-api" 87 | >developer.chrome.com</a 88 | > 89 | <a href="https://developer.mozilla.org/docs/Web/CSS/anchor">MDN</a> 90 | </div> 91 | </footer> 92 | </FeatureLayout> 93 | -------------------------------------------------------------------------------- /src/features/components/animate-to-height-auto.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "Animate to height: auto"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | <div class="support"> 18 | <baseline-status featureId="interpolate-size"></baseline-status> 19 | </div> 20 | 21 | <p> 22 | An often requested CSS feature is the ability to animate to <code 23 | >height: auto</code 24 | >. A slight variation of that request is to transition the width property 25 | instead of the height, or to transition to any of the other intrinsic sizes 26 | represented by keywords like <code>min-content</code>, <code 27 | >max-content</code 28 | >, and <code>fit-content</code>. 29 | </p> 30 | 31 | <p> 32 | From Chrome 129 you can use the <code>interpolate-size</code> property or the 33 | <code>calc-size()</code> function to enable smooth transitions and animations 34 | from lengths to intrinsic sizing keywords and back. 35 | </p> 36 | 37 | <figure> 38 | <CodePen id="web-dot-dev/GRbbNra" /> 39 | <figcaption> 40 | CSS <code>interpolate-size</code> demo. If your browser has no support, you 41 | can <a 42 | href="./video/animate-to-auto.mp4" 43 | >check the recording</a 44 | >. 45 | </figcaption> 46 | </figure> 47 | 48 | <p> 49 | The easiest way to enable this behavior is have the entire page opt-in to it 50 | by declaring <code style="white-space: break-spaces;" 51 | >interpolate-size: allow-keywords</code 52 | > on <code>:root</code>. 53 | </p> 54 | 55 | <Code 56 | lang="css" 57 | theme="css-variables" 58 | code={`/* Opt-in the whole page to animating to/from intrinsic sizing keywords */ 59 | :root { 60 | interpolate-size: allow-keywords; /* 👈 */ 61 | }`} 62 | /> 63 | <p> 64 | In most cases using <code>interpolate-size</code> should be sufficient. If you 65 | need more control over things–such as doing calculations with the resulting pixel 66 | value, or transitioning between the same two intrinsic sizing keywords use <a 67 | href="https://developer.chrome.com/docs/css-ui/animate-to-height-auto#animate_to_and_from_intrinsic_sizing_keywords_with_calc-size" 68 | ><code>calc-size()</code></a 69 | > instead. 70 | </p> 71 | 72 | <Author name="bramus" /> 73 | 74 | <footer> 75 | <a href="https://codepen.io/web-dot-dev/pen/GRbbNra">Try demo</a> 76 | <div class="articles"> 77 | <a href="https://developer.chrome.com/docs/css-ui/animate-to-height-auto" 78 | >developer.chrome.com</a 79 | > 80 | <a 81 | href="https://developer.mozilla.org/docs/Web/CSS/interpolate-size" 82 | >MDN</a 83 | > 84 | </div> 85 | </footer> 86 | </FeatureLayout> 87 | -------------------------------------------------------------------------------- /src/features/components/exclusive-details.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "Exclusive <details>"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | <div class="support"> 18 | <baseline-status featureId="details-name"></baseline-status> 19 | </div> 20 | 21 | <p> 22 | A common UI pattern on the web is an accordion component. This component 23 | consists of several disclosure widgets that individually can be expanded (or 24 | collapsed) to reveal (or hide) their content. 25 | </p> 26 | 27 | <p> 28 | This pattern can be created on the web with a few <code 29 | ><details></code 30 | > elements. These are typically grouped visually to indicate that they belong 31 | together. 32 | </p> 33 | 34 | <p> 35 | To make an exclusive accordion, add a name attribute to the <code 36 | ><details></code 37 | > elements. When this attribute is used, multiple <code 38 | ><details></code 39 | > elements that have the same name value form a semantic group. When you open 40 | one of the <code><details></code> elements from the group, the previously 41 | opened one will automatically close. 42 | </p> 43 | 44 | <Code 45 | lang="html" 46 | theme="css-variables" 47 | code={`<details name="learn-css"> 48 | <summary>Welcome to Learn CSS!</summary> 49 | <p>…</p> 50 | </details> 51 | <details name="learn-css"> 52 | <summary>Box Model</summary> 53 | <p>…</p> 54 | </details> 55 | <details name="learn-css"> 56 | <summary>Selectors</summary> 57 | <p>…</p> 58 | </details> 59 | `} 60 | /> 61 | 62 | <figure> 63 | <CodePen id="web-dot-dev/BaMbKyM" height={800} /> 64 | <figcaption>Exclusive Accordion demo</figcaption> 65 | </figure> 66 | 67 | <Author name="bramus" /> 68 | 69 | <footer> 70 | <a href="https://codepen.io/web-dot-dev/pen/BaMbKyM">Try demo</a> 71 | <div class="articles"> 72 | <a href="https://developer.chrome.com/docs/css-ui/exclusive-accordion" 73 | >developer.chrome.com</a 74 | > 75 | <a 76 | href="https://developer.mozilla.org/docs/Web/HTML/Element/details#name" 77 | >MDN</a 78 | > 79 | </div> 80 | </footer> 81 | </FeatureLayout> 82 | -------------------------------------------------------------------------------- /src/features/components/field-sizing.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | 12 | export const title = "Field Sizing"; 13 | const slug = slugify(title); 14 | --- 15 | 16 | <FeatureLayout slug={slug}> 17 | <Title slug={slug} title={title} /> 18 | <div class="support"> 19 | <baseline-status featureId="field-sizing"></baseline-status> 20 | </div> 21 | <p> 22 | Without <code>field-sizing</code>, to create a content-sized input field you 23 | had to either guess at an average size of a text field input or use 24 | JavaScript to count characters and increase the element height or width as 25 | the user entered text. <b>Now it's a CSS one-liner.</b> 26 | </p> 27 | <Code 28 | lang="css" 29 | theme="css-variables" 30 | code={`textarea, select, input { 31 | field-sizing: content; 32 | }`} 33 | /> 34 | <p> 35 | The following video demonstrates how a <code>textarea</code>, <code>select</code>, 36 | and <code>input</code> can now shrink to fit the size of the placeholder or 37 | content value. 38 | </p> 39 | <Video src="./video/field-sizing.mp4" width={1242} height={698} poster="./video/field-sizing.png" preload="none" /> 40 | <p> 41 | The following demo offers a side by side comparison of how inputs behave 42 | without <code>field-sizing</code> and with <code>field-sizing</code>. 43 | </p> 44 | <CodePen id="web-dot-dev/poYmRvp" height={500} /> 45 | <p> 46 | This will work for any font, any font size, any language and any writing 47 | mode. What used to be high effort will now be low effort. 48 | </p> 49 | <Author name="adam" /> 50 | <footer> 51 | <a href="https://codepen.io/web-dot-dev/pen/poYmRvp">Try demo</a> 52 | <div class="articles"> 53 | <a href="https://developer.chrome.com/docs/css-ui/css-field-sizing" 54 | >developer.chrome.com</a 55 | > 56 | <a href="https://developer.mozilla.org/docs/Web/CSS/field-sizing">MDN</a> 57 | </div> 58 | </footer> 59 | </FeatureLayout> 60 | -------------------------------------------------------------------------------- /src/features/components/styleable-details.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "Styleable <details>"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | <div class="support"> 18 | <baseline-status featureId="details-content"></baseline-status> 19 | </div> 20 | 21 | <p> 22 | From Chrome 131 you have more options to style the structure of <code 23 | ><details></code 24 | > and <code><summary></code> elements. You can now use these elements when 25 | building disclosure or accordion widgets. 26 | </p> 27 | 28 | <p> 29 | In particular, the changes introduced in Chrome 131 enable the use of the 30 | `display` property on these elements, and add a <code 31 | >::details-content</code 32 | > pseudo-element to style the part that expands and collapses. 33 | </p> 34 | 35 | <p> 36 | For example, to create a horizontal exclusive accordion, apply a flex layout 37 | that flows in the row direction to each <code><details></code> element. 38 | </p> 39 | 40 | <Code 41 | lang="css" 42 | theme="css-variables" 43 | code={`details { 44 | display: flex; 45 | flex-direction: row; 46 | }`} 47 | /> 48 | 49 | <figure> 50 | <CodePen id="web-dot-dev/XWvBZNo" height={680} /> 51 | <figcaption> 52 | Demo: Horizontal exclusive accordion. If your browser has no support, <a 53 | href="./video/animated-details-horizontal.mp4" 54 | >check out the recording</a 55 | >. 56 | </figcaption> 57 | </figure> 58 | 59 | <p> 60 | In addition to using more display types, the content of the <code 61 | ><details></code 62 | > element automatically gets wrapped in a <code>::details-content</code> pseudo-element. 63 | All children of the <code><details></code> element except the <code 64 | ><summary></code 65 | > get slotted into that pseudo. 66 | </p> 67 | 68 | <p> 69 | You can use this pseudo to control the part of the details disclosure 70 | element that expands and collapses. 71 | </p> 72 | 73 | <figure> 74 | <CodePen id="web-dot-dev/ExqpQZM" height={600} /> 75 | <figcaption> 76 | Demo: Material UI accordion. If your browser has no support, <a 77 | href="./video/animated-details-accordion.mp4" 78 | >check out the recording</a 79 | >. 80 | </figcaption> 81 | </figure> 82 | 83 | <Author name="bramus" /> 84 | <footer> 85 | <a href="https://codepen.io/web-dot-dev/pen/XWvBZNo">Try demo</a> 86 | <div class="articles"> 87 | <a href="https://developer.chrome.com/blog/styling-details" 88 | >developer.chrome.com</a 89 | > 90 | </div> 91 | </footer> 92 | </FeatureLayout> 93 | -------------------------------------------------------------------------------- /src/features/developerexperience/at-property.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "@property"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | <div class="support"> 18 | <baseline-status featureId="registered-custom-properties"></baseline-status> 19 | </div> 20 | 21 | <p> 22 | 2024 marked the year that <code>@property</code> finally became <a 23 | href="https://web.dev/baseline">Baseline Newly available</a 24 | >. Having cross-browser support for <code>@property</code> is a very exciting 25 | milestone as with <code>@property</code> and its <code 26 | >CSS.registerProperty</code 27 | > counterpart you can register custom properties to be of a certain type, control 28 | their inheritance behavior, and give them an initial value. 29 | </p> 30 | 31 | <Code 32 | lang="css" 33 | theme="css-variables" 34 | code={`@property --myColor { 35 | syntax: '<color>'; 36 | inherits: false; 37 | initial-value: hotpink; 38 | }`} 39 | /> 40 | 41 | <p> 42 | By registering a custom property to be of a certain type, the browser knows 43 | how to interpolate its values when used in transitions and animations. 44 | </p> 45 | 46 | <p> 47 | By animating a custom property, your CSS becomes more concise and also 48 | easier to read, as shown in the following snippet that animates the <code 49 | >--angle</code 50 | > property from <code>0deg</code> to <code>360deg</code>. 51 | </p> 52 | 53 | <Code 54 | lang="css" 55 | theme="css-variables" 56 | code={`@property --angle { 57 | syntax: '<angle>'; 58 | initial-value: 0deg; 59 | inherits: false; 60 | } 61 | 62 | @keyframes adjust-angle { 63 | to { 64 | --angle: 360deg; 65 | } 66 | } 67 | 68 | div { 69 | --angle: 0deg; 70 | animation: 10s adjust-angle linear infinite; 71 | rotate: var(--angle); 72 | }`} 73 | /> 74 | 75 | <figure> 76 | <CodePen id="web-dot-dev/QwLjYWZ" height={600} /> 77 | <figcaption> 78 | A demo with a rotating gradient border. The rotation is done by animating 79 | the <code>--angle</code> property which the gradient border uses. 80 | </figcaption> 81 | </figure> 82 | 83 | <div class="resources"> 84 | <p> 85 | <Icon name="book" title="Book Icon"aria-hidden="true" /> 86 | Resources: 87 | </p> 88 | <ul> 89 | <li> 90 | <a href="https://web.dev/blog/at-property-baseline" 91 | ><code>@property</code> goes baseline</a 92 | > 93 | </li> 94 | <li> 95 | <a href="https://web.dev/blog/at-property-performance" 96 | >Benchmarking the performance of CSS <code>@property</code></a 97 | > 98 | </li> 99 | <li> 100 | <a 101 | href="https://css-tricks.com/exploring-property-and-its-animating-powers/" 102 | >Exploring <code>@property</code> and its Animating Powers</a 103 | > 104 | </li> 105 | </ul> 106 | </div> 107 | 108 | <Author name="bramus" /> 109 | 110 | <footer> 111 | <a href="https://codepen.io/web-dot-dev/pen/QwLjYWZ">Try demo</a> 112 | <div class="articles"> 113 | <a href="https://web.dev/articles/at-property">web.dev</a> 114 | <a href="https://developer.mozilla.org/docs/Web/CSS/anchor">MDN</a> 115 | </div> 116 | </footer> 117 | </FeatureLayout> 118 | -------------------------------------------------------------------------------- /src/features/developerexperience/backdrop-inheritance.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "Backdrop Inheritance"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | 18 | { 19 | /* Disabled because the baseline widget shows ::backdrop support in general, not the inheritance changes specifically 20 | <div class="support"> 21 | <baseline-status featureId="backdrop"></baseline-status> 22 | </div> 23 | */ 24 | } 25 | <p> 26 | Historically the <code>::backdrop</code> pseudo-element didn’t inherit from anywhere. 27 | From Chrome 122, this <code>::backdrop</code> pseudo-element has been converted 28 | into a tree abiding element, meaning that it inherits any inheritable properties 29 | from its originating element. 30 | </p> 31 | 32 | <p> 33 | Thanks to this change it is possible to override custom property values on 34 | specific elements and <code>::backdrop</code> will have access to them. For example, 35 | the <code>::backdrop</code> associated with an open <code 36 | ><dialog></code 37 | > element can now access the custom properties available in that <code 38 | ><dialog></code 39 | >. 40 | </p> 41 | 42 | <figure> 43 | <CodePen id="web-dot-dev/MWxLzgx" height={600} /> 44 | <figcaption><code>::backdrop</code> demo</figcaption> 45 | </figure> 46 | 47 | <Author name="bramus" /> 48 | <footer> 49 | <a href="https://codepen.io/web-dot-dev/pen/MWxLzgx">Try demo</a> 50 | <div class="articles"> 51 | <a href="https://developer.chrome.com/blog/css-backdrop-inheritance" 52 | >developer.chrome.com</a 53 | > 54 | </div> 55 | </footer> 56 | </FeatureLayout> 57 | -------------------------------------------------------------------------------- /src/features/developerexperience/cssom-nested-declarations.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "CSSOM Nested Declarations"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | 18 | <!-- <div class="support"> 19 | <baseline-status featureId="scrollbar-width"></baseline-status> 20 | </div> --> 21 | 22 | <p> 23 | To fix some weird quirks with CSS nesting, the <code 24 | >CSSNestedDeclarations</code 25 | > interface was added to the CSS Nesting spec. With it, declarations that come 26 | after style rules no longer shift up. 27 | </p> 28 | 29 | <p> 30 | This means that the following CSS snippet gives the <code>.foo</code> element 31 | a <code>green</code> background color instead of a <code>red</code> one, as would 32 | happen without <code>CSSNestedDeclarations</code>. 33 | </p> 34 | 35 | <Code 36 | lang="css" 37 | theme="css-variables" 38 | code={`.foo { 39 | width: fit-content; 40 | 41 | @media screen { 42 | background-color: red; 43 | } 44 | 45 | background-color: green; 46 | }`} 47 | /> 48 | 49 | <p> 50 | With <code>CSSNestedDeclarations</code> the CSS rule serializes to the following, 51 | keeping the <code>background-color: green</code> declaration at its original 52 | location: 53 | </p> 54 | 55 | <Code 56 | theme="css-variables" 57 | code={`↳ CSSStyleRule 58 | .type = STYLE_RULE 59 | .selectorText = ".foo" 60 | .resolvedSelectorText = ".foo" 61 | .specificity = (0,1,0) 62 | .style (CSSStyleDeclaration, 1) = 63 | - width: fit-content 64 | .cssRules (CSSRuleList, 2) = 65 | ↳ CSSMediaRule 66 | .type = MEDIA_RULE 67 | .cssRules (CSSRuleList, 1) = 68 | ↳ CSSNestedDeclarations 69 | .style (CSSStyleDeclaration, 1) = 70 | - background-color: red 71 | ↳ CSSNestedDeclarations 72 | .style (CSSStyleDeclaration, 1) = 73 | - background-color: green 74 | `} 75 | /> 76 | 77 | <p> 78 | This addition landed in Chrome 130 and complements <a 79 | href="https://developer.chrome.com/blog/css-nesting-relaxed-syntax-update" 80 | >earlier changes that relaxed the parsing of nested styles</a 81 | >. 82 | </p> 83 | 84 | <Author name="bramus" /> 85 | 86 | <footer> 87 | <a href="https://codepen.io/web-dot-dev/pen/oNKzGvo">Try demo</a> 88 | <div class="articles"> 89 | <a href="https://web.dev/blog/css-nesting-cssnesteddeclarations" 90 | >web.dev</a 91 | > 92 | </div> 93 | </footer> 94 | </FeatureLayout> 95 | -------------------------------------------------------------------------------- /src/features/developerexperience/light-dark.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "light-dark()"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | <div class="support"> 18 | <baseline-status featureId="light-dark"></baseline-status> 19 | </div> 20 | 21 | <p>System colors in CSS have the ability to react to the current used <code>color-scheme</code> value. For example, if you declare <code>color: CanvasText</code> in a CSS rule, the color of the matched elements will be either light or dark depending on the <code>color-scheme</code> value.</p> 22 | 23 | <p>In the following demo, use the dropdown to control the <code>color-scheme</code> of the <code>div</code>. Because the <code>div</code> is styled with system colors, it supports both light and dark styles.</p> 24 | 25 | <figure> 26 | <CodePen id="web-dot-dev/ByBoMrG" height={500} /> 27 | <figcaption>System colors demo.</figcaption> 28 | </figure> 29 | 30 | <p> 31 | The <code>light-dark()</code> function exposes the same capability to developers. 32 | This function accepts two arguments, both of which must be a <code 33 | ><color></code 34 | >. 35 | </p> 36 | 37 | <Code 38 | lang="css" 39 | theme="css-variables" 40 | code={`:root { 41 | color-scheme: light dark; 42 | --primary-color: light-dark(#333, #fafafa); 43 | --primary-background: light-dark(#e4e4e4, #121212); 44 | --highlight-color: light-dark(hotpink, lime); 45 | }`} 46 | /> 47 | 48 | <p> 49 | By changing the value of <code>color-scheme</code>, either the first or the 50 | second value of <code>light-dark()</code> is used. 51 | </p> 52 | 53 | <ul> 54 | <li> 55 | If the used color scheme is <code>light</code> or unknown then the computed 56 | value of the first value gets returned. 57 | </li> 58 | <li> 59 | If the used color scheme is <code>dark</code> then the computed value of the 60 | second color is returned. 61 | </li> 62 | </ul> 63 | 64 | <figure> 65 | <CodePen id="web-dot-dev/zYXdRKW" height={600} /> 66 | <figcaption> 67 | <code>light-dark()</code> demo. Changing the selection changes the <code 68 | >color-scheme</code 69 | > value 70 | </figcaption> 71 | </figure> 72 | 73 | <div class="resources"> 74 | <p> 75 | <Icon name="book" title="Book Icon"aria-hidden="true" /> 76 | Resources: 77 | </p> 78 | <ul> 79 | <li> 80 | <a href="https://brm.us/light-dark" 81 | >“Easy Light-Dark Mode Color Switching with <code>light-dark()</code>” 82 | </a> article on bram.us 83 | </li> 84 | <li> 85 | <a 86 | href="https://developer.mozilla.org/docs/Web/CSS/color_value/light-dark" 87 | ><code>light-dark()</code></a 88 | > on MDN 89 | </li> 90 | </ul> 91 | </div> 92 | 93 | <Author name="bramus" /> 94 | 95 | <footer> 96 | <a href="https://codepen.io/web-dot-dev/pen/MWxLzgx">Try demo</a> 97 | <div class="articles"> 98 | <a href="https://developer.chrome.com/blog/css-backdrop-inheritance" 99 | >developer.chrome.com</a 100 | > 101 | </div> 102 | </footer> 103 | </FeatureLayout> 104 | -------------------------------------------------------------------------------- /src/features/developerexperience/paint-order.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "paint-order"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | 18 | <div class="support"> 19 | <baseline-status featureId="paint-order"></baseline-status> 20 | </div> 21 | 22 | <p>When using <code>text-stroke</code>, the <code>paint-order</code> property can control the order that the text fill and desired stroke are stacked or rendered together. This can be useful when you want to ensure that the stroke is rendered on top of the fill.</p> 23 | 24 | <p>The default paint order is: <code>fill</code>, <code>stroke</code>, then <code>markers</code>.</p> 25 | 26 | <p>The following video shows how the result of the text stroke is undesirable if the text is filled white and then given a black stroke. Switch those around, so the stroke is drawn first and then filled, and the result is quite nice!</p> 27 | 28 | <Video src="./video/paint-order.mp4" width={1470} height={828} poster="./video/paint-order.png" preload="none" /> 29 | 30 | <p>The CSS to control this is one line. Set the <code>paint-order</code> to draw the stroke before the fill by specifying those keywords in that order.</p> 31 | 32 | <Code 33 | lang="css" 34 | theme="css-variables" 35 | code={`h1 { 36 | paint-order: stroke fill; 37 | 38 | color: white; 39 | -webkit-text-stroke: 5px black; 40 | }`} 41 | /> 42 | 43 | <p>Try it for yourself in this CodePen:</p> 44 | 45 | <CodePen id="web-dot-dev/dyxryKE" height={600} /> 46 | 47 | <p>Some folks say that the ability to control <code>paint-order</code> has finally made <code>text-stroke</code> usable in production. What do you think?</p> 48 | 49 | <Author name="adam" /> 50 | 51 | <footer> 52 | <a href="https://codepen.io/web-dot-dev/pen/dyxryKE">Try demo</a> 53 | <div class="articles"> 54 | <a href="https://developer.mozilla.org/docs/Web/CSS/paint-order">MDN</a> 55 | </div> 56 | </footer> 57 | </FeatureLayout> 58 | -------------------------------------------------------------------------------- /src/features/developerexperience/popover.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "The Popover API"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title={title} /> 17 | <div class="support"> 18 | <baseline-status featureId="popover"></baseline-status> 19 | </div> 20 | 21 | <p> 22 | The Popover API provides ways to build layered interfaces like tooltips, 23 | menus, teaching UIs, and more. 24 | </p> 25 | 26 | <p> 27 | To create a popover with default values, all you need is a <code 28 | >button</code 29 | > to trigger the popover, and an element that is the popover. 30 | </p> 31 | 32 | <Code 33 | lang="html" 34 | theme="css-variables" 35 | code={`<button popovertarget="my-popover">Open Popover</button> 36 | 37 | <div id="my-popover" popover> 38 | <p><p>I am a popover with more information. Hit <kbd>esc</kbd> or click away to close me.<p></p> 39 | </div>`} 40 | /> 41 | 42 | <figure> 43 | <CodePen id="web-dot-dev/ExJrbjw" height={500} /> 44 | <figcaption>Simple popover demo</figcaption> 45 | </figure> 46 | 47 | <p> 48 | Popovers come with built-in support for top layer promotion, light-dismiss 49 | functionality, default focus management, and accessibility features. 50 | </p> 51 | 52 | <Author name="bramus" /> 53 | 54 | <footer> 55 | <a href="https://codepen.io/web-dot-dev/pen/ExJrbjw">Try demo</a> 56 | <div class="articles"> 57 | <a href="https://web.dev/blog/popover-api">web.dev</a> 58 | <a href="https://developer.mozilla.org/docs/Web/API/Popover_API">MDN</a> 59 | </div> 60 | </footer> 61 | </FeatureLayout> 62 | -------------------------------------------------------------------------------- /src/features/developerexperience/ruby-align.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "ruby-align"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title="Line-breakable <ruby> + CSS ruby-align" shorttitle={title} /> 17 | 18 | <div class="support"> 19 | <baseline-status featureId="ruby-align"></baseline-status> 20 | </div> 21 | 22 | <p> 23 | From Chrome 128, ruby annotations are line-breakable and you can style ruby 24 | text with the <code>ruby-align</code> CSS property. This gives you finer control 25 | on how phonetic annotations or other supplemental information above or beside 26 | base text with <code><ruby></code> should be presented. 27 | </p> 28 | 29 | <p> 30 | With line-breakable ruby, wrapped ruby annotation text gets placed over 31 | wrapped base text, achieving ideal text rendering. Compare this before and 32 | after: 33 | </p> 34 | 35 | <figure> 36 | <img 37 | src="./images/ruby_before.png" 38 | width="1860" 39 | height="492" 40 | loading="lazy" 41 | alt="Rendering result before Chrome 128 with long ruby annotation text." 42 | /> 43 | <figcaption> 44 | Rendering result before Chrome 128 with long ruby annotation text. 45 | </figcaption> 46 | </figure> 47 | 48 | <figure> 49 | <img 50 | src="./images/ruby_after.png" 51 | width="455" 52 | height="1722" 53 | loading="lazy" 54 | alt="Rendering result from Chrome 128 with long ruby annotation text." 55 | /> 56 | <figcaption> 57 | Rendering result as of Chrome 128 with long ruby annotation text. 58 | </figcaption> 59 | </figure> 60 | 61 | <p> 62 | The new CSS property <code>ruby-align</code> controls the alignment of ruby base 63 | text and ruby annotation text. The property accepts one of the keyword values 64 | <code>space-around</code>, <code>space-between</code>, <code>start</code>, 65 | and <code>center</code>. 66 | </p> 67 | 68 | <figure> 69 | <img 70 | src="./images/ruby-align.png" 71 | width="2454" 72 | height="651" 73 | loading="lazy" 74 | alt="Image showing use-case for ruby-align property." 75 | /> 76 | <figcaption>Image showing use-case for ruby-align property.</figcaption> 77 | </figure> 78 | 79 | <p>To automatically add <em>pinyin</em> to Chinese text and tweak its appearance, use <a href="https://codepen.io/yisi/full/WNWxvJr">this tool</a> created by <a href="https://github.com/yisibl">yisi(一丝)</a></p> 80 | 81 | <Author name="bramus" /> 82 | 83 | <footer style="place-content: end;"> 84 | <div class="articles"> 85 | <a href="https://developer.chrome.com/blog/line-breakable-ruby" 86 | >developer.chrome.com</a 87 | > 88 | <a href="https://developer.mozilla.org/docs/Web/CSS/ruby-align">MDN</a> 89 | </div> 90 | </footer> 91 | </FeatureLayout> 92 | 93 | <style> 94 | figure img { 95 | width: 100%; 96 | height: auto; 97 | } 98 | </style> -------------------------------------------------------------------------------- /src/features/developerexperience/starting-style.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | export const title = "@starting-style"; 12 | const slug = slugify(title); 13 | --- 14 | 15 | <FeatureLayout slug={slug}> 16 | <Title slug={slug} title="Entry effects with @starting-style" shorttitle={title} /> 17 | <div class="support"> 18 | <baseline-status featureId="starting-style"></baseline-status> 19 | </div> 20 | 21 | <p> 22 | The <code>@starting-style</code> at-rule is used to define styles for an element 23 | before it has received the first style update. When setting those targeted properties 24 | to transition with CSS transitions, you can use these starting-styles to create 25 | entry effects. 26 | </p> 27 | 28 | <p> 29 | In the following example, newly added <code><div></code> elements fade 30 | from <code>yellow</code> to their initial background-color which is transparent. 31 | </p> 32 | 33 | <Code 34 | lang="css" 35 | theme="css-variables" 36 | code={`div { 37 | transition: background-color 0.5s; 38 | background-color: transparent; 39 | 40 | @starting-style { 41 | background-color: yellow; 42 | } 43 | }`} 44 | /> 45 | 46 | <figure> 47 | <CodePen id="web-dot-dev/JoPYxRR" height={400} /> 48 | <figcaption><code>@starting-style</code> demo</figcaption> 49 | </figure> 50 | 51 | <p>Another use case is to animate-in dialogs when opened.</p> 52 | 53 | <Code 54 | lang="css" 55 | theme="css-variables" 56 | code={`dialog[open] { 57 | opacity: 1; 58 | transform: scaleX(1); 59 | 60 | @starting-style { 61 | opacity: 0; 62 | transform: scaleX(0); 63 | } 64 | }`} 65 | /> 66 | 67 | <figure> 68 | <CodePen id="web-dot-dev/dyQxmzg" height={500} /> 69 | <figcaption><code>@starting-style</code> demo</figcaption> 70 | </figure> 71 | 72 | <p> 73 | Don’t forget to set <code>transition-behavior</code> to <code 74 | >allow-discrete</code 75 | > when animating discretely animatable properties such as <code 76 | >display</code 77 | >. 78 | </p> 79 | 80 | <div class="resources"> 81 | <p> 82 | <Icon name="book" title="Book Icon"aria-hidden="true" /> 83 | Resources: 84 | </p> 85 | <ul> 86 | <li> 87 | <a 88 | href="https://nerdy.dev/using-starting-style-and-transition-behavior-for-enter-and-exit-stage-effects" 89 | >Using <code>@starting-style</code> and <code 90 | >transition-behavior</code 91 | > for enter and exit stage effects</a 92 | > 93 | </li> 94 | </ul> 95 | </div> 96 | 97 | <Author name="bramus" /> 98 | 99 | <footer> 100 | <a href="https://codepen.io/web-dot-dev/pen/dyQxmzg">Try demo</a> 101 | <div class="articles"> 102 | <a href="https://developer.chrome.com/blog/entry-exit-animations" 103 | >developer.chrome.com</a 104 | > 105 | <a href="https://developer.mozilla.org/docs/Web/CSS/@starting-style" 106 | >MDN</a 107 | > 108 | </div> 109 | </footer> 110 | </FeatureLayout> 111 | -------------------------------------------------------------------------------- /src/features/interactions/scroll-driven-animations.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import YouTube from "../../components/youtube.astro"; 8 | import { Code } from "astro:components"; 9 | import { Icon } from "astro-icon/components"; 10 | 11 | import slugify from "./../../util/slugify"; 12 | export const title = "Scroll-Driven Animations"; 13 | const slug = slugify(title); 14 | --- 15 | 16 | <FeatureLayout slug={slug}> 17 | <Title slug={slug} title={title} /> 18 | 19 | <div class="support"> 20 | <baseline-status featureId="scroll-driven-animations"></baseline-status> 21 | </div> 22 | 23 | <p> 24 | Scroll-driven animations are a common UX pattern on the web. A scroll-driven 25 | animation is linked to the scroll position of a scroll container. This means 26 | that as you scroll up or down, the linked animation scrubs forward or 27 | backward in direct response. 28 | </p> 29 | 30 | <p>In the following demo, if your browser has support for CSS scroll-driven animations, the images get unclipped as they cross the scrollport.</p> 31 | 32 | <figure> 33 | <iframe src="https://scroll-driven-animations.style/demos/image-reveal/css/?embed" height="500" loading="lazy" title="Scroll-driven animation demo"></iframe> 34 | <figcaption>Demo featuring <a href="https://scroll-driven-animations.style/demos/image-reveal/css/">self-revealing images</a> powered by scroll-driven animations.</figcaption> 35 | </figure> 36 | 37 | <p>To support the launch of scroll-driven animations in Chrome 115, Chrome DevRel created <a href="https://goo.gle/learn-scroll-driven-animations">“Unleash the Power of Scroll-Driven Animations”</a>, a 10-part video course that teaches you all there is to know about scroll-driven animations with CSS or JavaScript.</p> 38 | 39 | <figure> 40 | <YouTube id="5noL_qFobm0" width={375} height={211} /> 41 | <figcaption> 42 | The first episode of <a 43 | href="https://goo.gle/learn-scroll-driven-animations" 44 | >“Unleash the Power of Scroll-Driven Animations”</a 45 | > 46 | </figcaption> 47 | </figure> 48 | 49 | <p>Watch this series and become a scroll-driven animations expert.</p> 50 | 51 | <div class="resources"> 52 | <p> 53 | <Icon name="book" title="Book Icon"aria-hidden="true" /> 54 | Resources: 55 | </p> 56 | <ul> 57 | <li> 58 | <a href="https://scroll-driven-animations.style/" 59 | >scroll-driven-animations.style</a 60 | > — Your one-stop shop for all your scroll-driven animations needs 61 | </li> 62 | <li> 63 | <a href="https://goo.gle/learn-scroll-driven-animations" 64 | >“Unleash the Power of Scroll-Driven Animations”</a 65 | > on YouTube 66 | </li> 67 | <li> 68 | <a 69 | href="https://css-tricks.com/unleash-the-power-of-scroll-driven-animations/" 70 | >“Unleash the Power of Scroll-Driven Animations”</a 71 | > course notes by Geoff Graham 72 | </li> 73 | </ul> 74 | </div> 75 | 76 | <Author name="bramus" /> 77 | 78 | <footer> 79 | <a href="https://scroll-driven-animations.style/demos/contact-list/css/" 80 | >Try demo</a 81 | > 82 | <div class="articles"> 83 | <a href="https://goo.gle/scroll-driven-animations">developer.chrome.com</a 84 | > 85 | <a 86 | href="https://developer.mozilla.org/docs/Web/CSS/CSS_scroll-driven_animations" 87 | >MDN</a 88 | > 89 | </div> 90 | </footer> 91 | </FeatureLayout> 92 | 93 | <style> 94 | iframe { 95 | width: 100%; 96 | border-radius: var(--radius-3); 97 | overflow: clip; 98 | box-shadow: var(--shadow-3); 99 | background-color: white; 100 | border: 1px solid var(--text-1); 101 | } 102 | </style> -------------------------------------------------------------------------------- /src/features/interactions/scroll-snap-events.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | 12 | export const title = "Scroll Snap Events"; 13 | const slug = slugify(title); 14 | --- 15 | 16 | <FeatureLayout slug={slug}> 17 | <Title slug={slug} title={title} /> 18 | 19 | <div class="support"> 20 | <baseline-status featureId="scroll-snap-events"></baseline-status> 21 | </div> 22 | 23 | <p>Built-in snap events have made previously invisible moments during scrolling, visible, at the right time, and always correct. They are the missing piece of the puzzle that makes scroll snapping a complete solution.</p> 24 | 25 | <p>Two new snap events: <a href="https://developer.mozilla.org/docs/Web/API/Element/scrollsnapchange_event"><code>scrollsnapchange</code></a> and <a href="https://developer.mozilla.org/docs/Web/API/Element/scrollsnapchanging_event"><code>scrollsnapchanging</code></a>.</p> 26 | 27 | <Code lang="js" theme="css-variables" code={`scroller.addEventListener('scrollsnapchange', event=> { 28 | console.log(event.snapTargetBlock); 29 | console.log(event.snapTargetInline); 30 | })`} 31 | /> 32 | 33 | <p>The <code>scrollsnapchange</code> event fires at a similar moment as <a href="https://developer.chrome.com/blog/scrollend-a-new-javascript-event"><code>scrollend</code></a>, when scroll has rested and the user has stopped 34 | interacting with the scroller.</p> 35 | 36 | <Video src="./video/snap-change.mp4" width={1920} height={1082} poster="./video/snap-change.png" preload="none" /> 37 | 38 | <p>The <code>scrollsnapchanging</code>event is eager to fire, and calls the callback the moment the scroller has a new snap target. This is useful for instant UX feedback, providing a mechanism for immediate visual updates based on the user's interaction.</p> 39 | 40 | <Video src="./video/snap-changing.mp4" width={1920} height={1082} poster="./video/snap-changing.png" preload="none" /> 41 | 42 | <Code lang="js" theme="css-variables" code={`scroller.addEventListener('scrollsnapchanging', event=> { 43 | console.log(event.snapTargetBlock); 44 | console.log(event.snapTargetInline); 45 | })`} 46 | /> 47 | 48 | <p>By combining these events together you can create a seamless experience for picking elements with a scroll gesture. The following ruler experience snaps to quarter inch values and uses <a href="#scroll-driven-animations">scroll driven animation</a> to highlight the selected value. The <code>scrollsnapchanging</code>event is used to immediately update the number input value, while the <code>scrollsnapchange</code> event is used to support and confirm the selected value.</p> 49 | 50 | <CodePen id="web-dot-dev/LYKOOpd" height={300} /> 51 | 52 | <p>Checkout the article on <a href="https://developer.chrome.com/blog/scroll-snap-events">developer.chrome.com</a> for more details and examples. Also, the following demo link is to a Snap Event visualizer, helping you feel and see the timing of these new events.</p> 53 | 54 | <Author name="adam" /> 55 | <footer> 56 | <a href="https://codepen.io/web-dot-dev/pen/jOjaaEP">Try demo</a> 57 | <div class="articles"> 58 | <a href="https://developer.chrome.com/blog/scroll-snap-events" 59 | >developer.chrome.com</a 60 | > 61 | <a href="https://developer.mozilla.org/docs/Web/API/SnapEvent">MDN</a> 62 | </div> 63 | </footer> 64 | </FeatureLayout> 65 | -------------------------------------------------------------------------------- /src/features/interactions/scrollbar-styling.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import { Code } from "astro:components"; 8 | import { Icon } from "astro-icon/components"; 9 | 10 | import slugify from "./../../util/slugify"; 11 | 12 | export const title = "Custom Scrollbars"; 13 | const slug = slugify(title); 14 | --- 15 | 16 | <FeatureLayout slug={slug}> 17 | <Title slug={slug} title={title} /> 18 | 19 | <div class="support"> 20 | <baseline-status featureId="scrollbar-color"></baseline-status> 21 | <baseline-status featureId="scrollbar-width"></baseline-status> 22 | </div> 23 | 24 | <p> 25 | Styling scrollbars has long been possible with the <code 26 | >::-webkit-scrollbar-*</code 27 | > pseudo-elements. This approach works fine in Chrome and Safari, but was never 28 | standardized by the CSS Working Group. 29 | </p> 30 | 31 | <p> 32 | Available from Chrome 121 are the <code>scrollbar-width</code> and <code 33 | >scrollbar-color</code 34 | > properties to style the width and, respectively, the color of the scrollbar. 35 | </p> 36 | 37 | <Code 38 | lang="css" 39 | theme="css-variables" 40 | code={`.scroller { 41 | scrollbar-color: hotpink blue; 42 | scrollbar-width: 10%; 43 | }`} 44 | /> 45 | 46 | <p> 47 | These properties are also supported by Firefox and have partial support in 48 | Safari. 49 | </p> 50 | 51 | <figure> 52 | <CodePen id="web-dot-dev/QwLbJVg" height={500} /> 53 | <figcaption> 54 | Custom Scrollbars demo. Use the color inputs to change the colors. 55 | </figcaption> 56 | </figure> 57 | 58 | <div class="resources"> 59 | <p> 60 | <Icon name="book" title="Book Icon"aria-hidden="true" /> 61 | Resources: 62 | </p> 63 | <ul> 64 | <li> 65 | <a href="https://developer.mozilla.org/docs/Web/CSS/scrollbar-color" 66 | ><code>scrollbar-color</code> on MDN</a 67 | > 68 | </li> 69 | <li> 70 | <a href="https://developer.mozilla.org/docs/Web/CSS/scrollbar-width" 71 | ><code>scrollbar-width</code> on MDN</a 72 | > 73 | </li> 74 | <li> 75 | <a href="https://www.bram.us/2021/07/09/custom-scrollbars-in-css/">Custom Scrollbars on bram.us</a> 76 | </li> 77 | </ul> 78 | </div> 79 | 80 | <Author name="bramus" /> 81 | 82 | <footer> 83 | <a href="https://codepen.io/collection/ExkRWw">Try demo</a> 84 | <div class="articles"> 85 | <a href="https://developer.chrome.com/docs/css-ui/scrollbar-styling" 86 | >developer.chrome.com</a 87 | > 88 | </div> 89 | </footer> 90 | </FeatureLayout> 91 | -------------------------------------------------------------------------------- /src/features/interactions/view-transitions-mpa.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import FeatureLayout from "./../_layout.astro"; 3 | import Title from "../../components/feature.title.astro"; 4 | import Author from "../../components/author.astro"; 5 | import Video from "../../components/video.astro"; 6 | import CodePen from "../../components/codepen.astro"; 7 | import YouTube from "../../components/youtube.astro"; 8 | import { Code } from "astro:components"; 9 | import { Icon } from "astro-icon/components"; 10 | 11 | import slugify from "./../../util/slugify"; 12 | 13 | export const title = "Cross-Document View Transitions"; 14 | const slug = slugify(title); 15 | --- 16 | 17 | <FeatureLayout slug={slug}> 18 | <Title slug={slug} title={title} /> 19 | 20 | <div class="support"> 21 | <baseline-status featureId="view-transitions"></baseline-status> 22 | </div> 23 | 24 | <p> 25 | In 2023, Chrome was the first browser to ship same-document view 26 | transitions, an exciting addition to the web platform that allows you to 27 | have rich and seamless transitions between various views of your website. 28 | This year, Chrome continued to push the web forwards by shipping 29 | cross-document view transitions in Chrome 126. 30 | </p> 31 | 32 | <p> 33 | Cross-document view transitions allow you to run a view transition between 34 | two separate documents. As a result, you no longer need to rework your 35 | website as a SPA to use view transitions. All it takes is a navigation from 36 | one page to another, a core primitive that makes the web “the web”. 37 | </p> 38 | 39 | <figure> 40 | <Video src="./video/cross-document-view-transitions.mp4" width={2160} height={1216} poster="./video/cross-document-view-transitions.png" preload="none" /> 41 | <figcaption> 42 | Recording of the <a href="https://view-transitions.chrome.dev/stack-navigator/mpa/">“Stack Navigator” demo that uses cross-document view transitions</a> 43 | </figcaption> 44 | </figure> 45 | 46 | <p> 47 | To allow a view transition to run between two pages you need to fulfill two 48 | conditions: the navigation must be a same-origin navigation and both pages 49 | need to opt in to allow the view transition to run. Opting in is done with 50 | the following CSS rule: 51 | </p> 52 | 53 | <Code 54 | lang="css" 55 | theme="css-variables" 56 | code={`@view-transition { 57 | navigation: auto; 58 | }`} 59 | /> 60 | 61 | <p> 62 | Once enabled, cross-document view transitions use the same building blocks 63 | as same-document view transitions: add the <code>view-transition-name</code> 64 | property to the elements that you want to capture, and the animations are powered 65 | by CSS animations. 66 | </p> 67 | 68 | <p> 69 | Apart from shipping cross-document view transitions, Chrome also shipped a 70 | few extra additions to more easily work with view transitions, such as <code 71 | >view-transition-class</code 72 | >. These changes were announced at Google I/O ’24 in May. 73 | </p> 74 | 75 | <figure> 76 | <YouTube id="eY6C_-aDdTo" width={560} height={315} /> 77 | <figcaption> 78 | Video from Google I/O ’24: “Multi-page application View Transitions are 79 | here” 80 | </figcaption> 81 | </figure> 82 | 83 | <p> 84 | This year we also welcomed Safari in shipping view transitions and are 85 | looking forward to seeing Firefox continue working on their same-document 86 | implementation. 87 | </p> 88 | 89 | <div class="resources"> 90 | <p> 91 | <Icon name="book" title="Book Icon"aria-hidden="true" /> 92 | Resources: 93 | </p> 94 | <ul> 95 | <li> 96 | <a href="https://developer.chrome.com/blog/view-transitions-update-io24" 97 | >“What's new in view transitions? (Google I/O 2024 update)”</a 98 | > 99 | </li> 100 | <li> 101 | <a 102 | href="https://developer.chrome.com/docs/web-platform/view-transitions" 103 | >Documentation “Smooth transitions with the View Transition API”</a 104 | > 105 | </li> 106 | </ul> 107 | </div> 108 | 109 | <Author name="bramus" /> 110 | 111 | <footer> 112 | <a href="https://view-transitions.chrome.dev/">Try demo</a> 113 | <div class="articles"> 114 | <a href="https://developer.chrome.com/docs/web-platform/view-transitions" 115 | >developer.chrome.com</a 116 | > 117 | <a 118 | href="https://developer.mozilla.org/docs/Web/CSS/@view-transition" 119 | >MDN</a 120 | > 121 | </div> 122 | </footer> 123 | </FeatureLayout> -------------------------------------------------------------------------------- /src/icons/book.svg: -------------------------------------------------------------------------------- 1 | <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M6.5 16q1.175 0 2.288.263T11 17.05V7.2q-1.025-.6-2.175-.9T6.5 6q-.9 0-1.788.175T3 6.7v9.9q.875-.3 1.738-.45T6.5 16m6.5 1.05q1.1-.525 2.213-.787T17.5 16q.9 0 1.763.15T21 16.6V6.7q-.825-.35-1.713-.525T17.5 6q-1.175 0-2.325.3T13 7.2zm-1 2.425q-.35 0-.663-.087t-.587-.238q-.975-.575-2.05-.862T6.5 18q-1.05 0-2.062.275T2.5 19.05q-.525.275-1.012-.025T1 18.15V6.1q0-.275.138-.525T1.55 5.2q1.15-.6 2.4-.9T6.5 4q1.45 0 2.838.375T12 5.5q1.275-.75 2.663-1.125T17.5 4q1.3 0 2.55.3t2.4.9q.275.125.413.375T23 6.1v12.05q0 .575-.487.875t-1.013.025q-.925-.5-1.937-.775T17.5 18q-1.125 0-2.2.288t-2.05.862q-.275.15-.587.238t-.663.087m2-10.7q0-.225.163-.462T14.525 8q.725-.25 1.45-.375T17.5 7.5q.5 0 .988.063t.962.162q.225.05.388.25t.162.45q0 .425-.275.625t-.7.1q-.35-.075-.737-.112T17.5 9q-.65 0-1.275.125t-1.2.325q-.45.175-.737-.025T14 8.775m0 5.5q0-.225.163-.462t.362-.313q.725-.25 1.45-.375T17.5 13q.5 0 .988.063t.962.162q.225.05.388.25t.162.45q0 .425-.275.625t-.7.1q-.35-.075-.737-.112T17.5 14.5q-.65 0-1.275.113t-1.2.312q-.45.175-.737-.012T14 14.275m0-2.75q0-.225.163-.462t.362-.313q.725-.25 1.45-.375t1.525-.125q.5 0 .988.063t.962.162q.225.05.388.25t.162.45q0 .425-.275.625t-.7.1q-.35-.075-.737-.112t-.788-.038q-.65 0-1.275.125t-1.2.325q-.45.175-.737-.025t-.288-.65"/></svg> -------------------------------------------------------------------------------- /src/icons/check.svg: -------------------------------------------------------------------------------- 1 | <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z"/></svg> -------------------------------------------------------------------------------- /src/icons/chrome.svg: -------------------------------------------------------------------------------- 1 | <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"> 2 | <path fill="#FFF" 3 | d="M128.003 199.216c39.335 0 71.221-31.888 71.221-71.223S167.338 56.77 128.003 56.77S56.78 88.658 56.78 127.993s31.887 71.223 71.222 71.223" /> 4 | <path fill="#229342" 5 | d="M35.89 92.997Q27.92 79.192 17.154 64.02a127.98 127.98 0 0 0 110.857 191.981q17.671-24.785 23.996-35.74q12.148-21.042 31.423-60.251v-.015a63.993 63.993 0 0 1-110.857.017Q46.395 111.19 35.89 92.998" /> 6 | <path fill="#FBC116" 7 | d="M128.008 255.996A127.97 127.97 0 0 0 256 127.997A128 128 0 0 0 238.837 64q-36.372-3.585-53.686-3.585q-19.632 0-57.152 3.585l-.014.01a63.99 63.99 0 0 1 55.444 31.987a63.99 63.99 0 0 1-.001 64.01z" /> 8 | <path fill="#1A73E8" 9 | d="M128.003 178.677c27.984 0 50.669-22.685 50.669-50.67s-22.685-50.67-50.67-50.67c-27.983 0-50.669 22.686-50.669 50.67s22.686 50.67 50.67 50.67" /> 10 | <path fill="#E33B2E" 11 | d="M128.003 64.004H238.84a127.973 127.973 0 0 0-221.685.015l55.419 95.99l.015.008a63.993 63.993 0 0 1 55.415-96.014z" /> 12 | </svg> -------------------------------------------------------------------------------- /src/icons/close.svg: -------------------------------------------------------------------------------- 1 | <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="m12 13.4l-4.9 4.9q-.275.275-.7.275t-.7-.275t-.275-.7t.275-.7l4.9-4.9l-4.9-4.9q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275l4.9 4.9l4.9-4.9q.275-.275.7-.275t.7.275t.275.7t-.275.7L13.4 12l4.9 4.9q.275.275.275.7t-.275.7t-.7.275t-.7-.275z"/></svg> -------------------------------------------------------------------------------- /src/icons/css.svg: -------------------------------------------------------------------------------- 1 | <svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 1000 1000" role="img" aria-labelledby="css-logo-title css-logo-description"> 2 | <title id="css-logo-title">CSS Logo 3 | A purple square with rounded corners and the letters CSS inside in white 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/icons/dino.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/icons/down-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/feedback.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/hamburger.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/icons/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /src/icons/star.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import "../styles/global.css"; 3 | import slugify from "./../util/slugify"; 4 | 5 | import PrimaryNav from "../components/nav.primary.astro"; 6 | import Hero from "../components/hero.astro"; 7 | import FeatureFilmstrip from "../components/feature.filmstrip.astro"; 8 | import Biomes from "../components/biomes.astro"; 9 | import Footer from "../components/footer.astro"; 10 | import AsideNav from "../components/nav.aside.astro"; 11 | import CookieConsent from "../components/cookieconsent.astro"; 12 | 13 | import * as FieldSizing from "../features/components/field-sizing.astro"; 14 | import * as AnimateToHeightAuto from "../features/components/animate-to-height-auto.astro"; 15 | import * as ExclusiveDetails from "../features/components/exclusive-details.astro"; 16 | import * as StyleableDetails from "../features/components/styleable-details.astro"; 17 | import * as AnchorPositioning from "../features/components/anchor-positioning.astro"; 18 | 19 | import * as BackdropInheritance from "../features/developerexperience/backdrop-inheritance.astro"; 20 | import * as LightDarkFunction from "../features/developerexperience/light-dark.astro"; 21 | import * as AtProperty from "../features/developerexperience/at-property.astro"; 22 | import * as Popover from "../features/developerexperience/popover.astro"; 23 | import * as StartingStyle from "../features/developerexperience/starting-style.astro"; 24 | import * as RubyAlign from "../features/developerexperience/ruby-align.astro"; 25 | import * as PaintOrder from "../features/developerexperience/paint-order.astro"; 26 | import * as CSSOMNestedDeclarations from "../features/developerexperience/cssom-nested-declarations.astro"; 27 | 28 | import * as ScrollbarStyling from "../features/interactions/scrollbar-styling.astro"; 29 | import * as ViewTransitionsMPA from "../features/interactions/view-transitions-mpa.astro"; 30 | import * as ScrollDrivenAnimations from "../features/interactions/scroll-driven-animations.astro"; 31 | import * as ScrollSnapEvents from "../features/interactions/scroll-snap-events.astro"; 32 | 33 | const biomes = [ 34 | { 35 | title: "Components", 36 | description: `We traveled over the mountains to bring 37 | exciting overlay UX with anchor, 38 | the power to animate to height auto, 39 | easily turn details into an accordion, 40 | get more access to details styling, 41 | and intrinsically size form elements!`, 42 | backdrop: "desert", 43 | image: "./biomes/desert.png", 44 | alt: "Desert scene in low-res bitmap style", 45 | features: [ 46 | FieldSizing, 47 | AnimateToHeightAuto, 48 | ExclusiveDetails, 49 | StyleableDetails, 50 | AnchorPositioning, 51 | ], 52 | }, 53 | { 54 | title: "Interactions", 55 | description: `Through the forest we found features for styling the scrollbar, 56 | using multi-page view transitions, 57 | creating scroll animations and 58 | events for scroll snap!`, 59 | backdrop: "arctic", 60 | image: "./biomes/arctic.png", 61 | alt: "Arctic scene in low-res bitmap style", 62 | features: [ 63 | ScrollbarStyling, 64 | ViewTransitionsMPA, 65 | ScrollDrivenAnimations, 66 | ScrollSnapEvents, 67 | ], 68 | }, 69 | { 70 | title: "Developer Experience", 71 | description: `Things got even easier after we traveled across the seas.

72 | 73 |

We discovered ways to simplify backdrop inheritance, 74 | a magic color function called light-dark(), 75 | safer and smarter variables with @property, 76 | a way to specify a starting style for transitions, 77 | ways to pop into the top-layer, 78 | improved ruby alignment, 79 | options for layering text strokes with text fill, 80 | and even more ways to relax CSS nesting!`, 81 | backdrop: "jungle", 82 | image: "./biomes/jungle.png", 83 | alt: "Jungle scene in low-res bitmap style", 84 | features: [ 85 | BackdropInheritance, 86 | LightDarkFunction, 87 | AtProperty, 88 | Popover, 89 | StartingStyle, 90 | RubyAlign, 91 | PaintOrder, 92 | CSSOMNestedDeclarations, 93 | ], 94 | }, 95 | ]; 96 | 97 | // Flatten all Biome features to a list of CSS timeline names 98 | const timelines = biomes.reduce( 99 | (timelines, biome) => [ 100 | `--vtl--${slugify(biome.title)}`, 101 | ...biome.features.map( 102 | (feature) => `--vtl--${slugify(biome.title)}--${slugify(feature.title)}` 103 | ), 104 | ...timelines, 105 | ], 106 | [] 107 | ); 108 | --- 109 | 110 | {/* remove the VT until the clientside theme switch is loaded so we dont flash a VT */} 114 | 115 | 116 | 117 | 118 | CSS Wrapped 2024 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | {/* */} 145 | 146 |

147 | 148 | 149 |
150 | 151 |