├── CONTRIBUTING ├── LICENSE ├── README.md ├── carousel-configurator ├── .gitignore ├── .npmrc ├── README.md ├── package-lock.json ├── package.json ├── src │ ├── app.d.ts │ ├── app.html │ ├── components │ │ ├── Configurator.svelte │ │ └── Switch.svelte │ ├── lib │ │ └── index.ts │ └── routes │ │ ├── +layout.svelte │ │ ├── +page.js │ │ ├── +page.svelte │ │ └── index.css ├── static │ ├── MonaspaceKrypton-SyntaxHighlighter-Regular.woff2 │ └── favicon.svg ├── svelte.config.js ├── tsconfig.json └── vite.config.ts ├── carousels-gallery ├── .gitignore ├── README.md ├── astro.config.mjs ├── package-lock.json ├── package.json ├── public │ ├── chameleon.mp4 │ ├── favicon.svg │ ├── flora-1.jpg │ ├── flora-2.jpg │ ├── flora-3.jpg │ ├── flora-4.jpg │ ├── flying-cars-2.jpg │ ├── flying-cars-3.jpg │ ├── flying-cars.jpg │ ├── fold-1.png │ ├── fold-2.png │ ├── fold-3.png │ ├── fold-4.png │ ├── fold-5.png │ ├── googletv-logo.svg │ ├── hot-fuss.jpg │ ├── material-symbols.woff2 │ ├── neon-city.jpg │ ├── neon-raptor.jpg │ ├── neon-trex.jpg │ ├── neon-wolf.jpg │ ├── snow.mp4 │ ├── turtle.mp4 │ └── wheel.mp4 ├── src │ ├── components │ │ └── Sidebar.astro │ ├── env.d.ts │ ├── layouts │ │ └── Layout.astro │ ├── pages │ │ ├── bidi │ │ │ └── grid.astro │ │ ├── horizontal │ │ │ ├── 3d.astro │ │ │ ├── app-switcher.astro │ │ │ ├── cards.astro │ │ │ ├── curved.astro │ │ │ ├── gallery.astro │ │ │ ├── hubs.astro │ │ │ ├── list.astro │ │ │ ├── media-player.astro │ │ │ ├── pages.astro │ │ │ ├── product.astro │ │ │ ├── series.astro │ │ │ ├── slider.astro │ │ │ ├── tabs.astro │ │ │ ├── testimonials.astro │ │ │ ├── video.astro │ │ │ ├── weather.astro │ │ │ └── wizard.astro │ │ ├── index.astro │ │ └── vertical │ │ │ ├── list.astro │ │ │ ├── scroll-spy.astro │ │ │ ├── slides.astro │ │ │ ├── stack.astro │ │ │ └── wheel.astro │ └── styles │ │ ├── fonts.css │ │ ├── index.css │ │ ├── utilities.carousel.css │ │ ├── utilities.css │ │ └── utilities.tags.css └── tsconfig.json └── has-ua-visual-transition ├── README.md └── src ├── index.html ├── mpa-navigation ├── . ignore ├── index.html ├── index2.html ├── index3.html ├── index4.html └── scripts.js ├── mpa ├── . ignore ├── index.html ├── index2.html ├── index3.html ├── index4.html └── scripts.js └── spa ├── . ignore ├── index.html └── scripts.js /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 and Web UI Demos 2 | 3 | Collection of demos from the CSS and Web UI Chrome DevRel team. Each demo goes in its own subfolder, each with its own instructions. 4 | 5 | ## License 6 | 7 | This project is released under the Apache 2.0 License. See the enclosed [`LICENSE`](./LICENSE) for details. 8 | 9 | ## Contributing 10 | 11 | We'd love to accept your patches and contributions to this project. See the enclosed [`CONTRIBUTING`](./CONTRIBUTING) for details. -------------------------------------------------------------------------------- /carousel-configurator/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | # Output 4 | .output 5 | .vercel 6 | .netlify 7 | /.svelte-kit 8 | /build 9 | 10 | # OS 11 | .DS_Store 12 | Thumbs.db 13 | 14 | # Env 15 | .env 16 | .env.* 17 | !.env.example 18 | !.env.test 19 | 20 | # Vite 21 | vite.config.js.timestamp-* 22 | vite.config.ts.timestamp-* 23 | -------------------------------------------------------------------------------- /carousel-configurator/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /carousel-configurator/README.md: -------------------------------------------------------------------------------- 1 | # create-svelte 2 | 3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). 4 | 5 | ## Creating a project 6 | 7 | If you're seeing this, you've probably already done this step. Congrats! 8 | 9 | ```bash 10 | # create a new project in the current directory 11 | npm create svelte@latest 12 | 13 | # create a new project in my-app 14 | npm create svelte@latest my-app 15 | ``` 16 | 17 | ## Developing 18 | 19 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: 20 | 21 | ```bash 22 | npm run dev 23 | 24 | # or start the server and open the app in a new browser tab 25 | npm run dev -- --open 26 | ``` 27 | 28 | ## Building 29 | 30 | To create a production version of your app: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | You can preview the production build with `npm run preview`. 37 | 38 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. 39 | -------------------------------------------------------------------------------- /carousel-configurator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carousel-configurator", 3 | "version": "1.0.0", 4 | "author": { 5 | "name": "Adam Argyle", 6 | "url": "https://nerdy.dev" 7 | }, 8 | "description": "Build a carousel while learning the CSS to make it.", 9 | "keywords": [ 10 | "CSS", 11 | "Scroll Markers", 12 | "Scroll Buttons", 13 | "Columns", 14 | "interactivity: inert" 15 | ], 16 | "scripts": { 17 | "dev": "vite dev", 18 | "build": "vite build", 19 | "preview": "vite preview", 20 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 21 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 22 | "deploy": "cp package.json build/ && gsutil -m rsync -rd build gs://chrome-dev-demos/public/carousel-configurator" 23 | }, 24 | "devDependencies": { 25 | "@sveltejs/adapter-auto": "^3.3.1", 26 | "@sveltejs/adapter-netlify": "^4.4.2", 27 | "@sveltejs/kit": "^2.21.1", 28 | "@sveltejs/vite-plugin-svelte": "^3.1.2", 29 | "svelte": "^4.2.20", 30 | "svelte-check": "^4.2.1", 31 | "typescript": "^5.8.3", 32 | "vite": "^5.4.19" 33 | }, 34 | "type": "module", 35 | "dependencies": { 36 | "@sveltejs/adapter-static": "^3.0.8", 37 | "open-props": "^1.7.15" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /carousel-configurator/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | declare global { 4 | namespace App { 5 | // interface Error {} 6 | // interface Locals {} 7 | // interface PageData {} 8 | // interface PageState {} 9 | // interface Platform {} 10 | } 11 | } 12 | 13 | export {}; 14 | -------------------------------------------------------------------------------- /carousel-configurator/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /carousel-configurator/src/components/Switch.svelte: -------------------------------------------------------------------------------- 1 | 30 | 31 | {#if design == 'inner'} 32 |
33 | {label} 34 | 42 |
43 | {:else if design == 'slider'} 44 |
45 | {label} 46 | 52 |
53 | {:else} 54 |
55 |
60 |
{label}
61 | {#each options as option} 62 | 63 | 66 | {/each} 67 |
68 |
69 | 70 | {/if} 71 | 72 | -------------------------------------------------------------------------------- /carousel-configurator/src/lib/index.ts: -------------------------------------------------------------------------------- 1 | // place files you want to import through the `$lib` alias in this folder. 2 | -------------------------------------------------------------------------------- /carousel-configurator/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | 9 | -------------------------------------------------------------------------------- /carousel-configurator/src/routes/+page.js: -------------------------------------------------------------------------------- 1 | // since there's no dynamic data here, we can prerender 2 | // it so that it gets served as a static asset in production 3 | export const prerender = true; -------------------------------------------------------------------------------- /carousel-configurator/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | CSS Carousel Configurator 7 | 11 | 12 | 13 | 14 |
15 |

Experimental Feature

16 |

⚠️ Unsupported ⚠️

17 |

18 | This configurator requires a few CSS features that aren't present in your 19 | current browser. 20 |

21 |

22 | To try this out, download Canary and visit chrome://flags/#enable-experimental-web-platform-features in a tab, enable it, and reload this page. 26 |

27 |
28 | 29 |
30 |

Carousel Configurator

31 |

32 | A builder-like experience to help visualize the capabilities of a CSS only Carousel: buttons, 35 | markers, 36 | paging 37 | and inertness. 38 |

39 |
40 |

Spec · Gallery

41 |
42 | 43 | 44 | 45 | 81 | -------------------------------------------------------------------------------- /carousel-configurator/src/routes/index.css: -------------------------------------------------------------------------------- 1 | @import "open-props/style"; 2 | @import "open-props/normalize"; 3 | 4 | @font-face { 5 | font-family: "Monaspace"; 6 | src: url("/MonaspaceKrypton-SyntaxHighlighter-Regular.woff2") format("woff2"); 7 | } 8 | 9 | @font-face { 10 | font-family: "Material Symbols Outlined"; 11 | font-style: normal; 12 | font-weight: 100 700; 13 | src: url(https://fonts.gstatic.com/s/materialsymbolsoutlined/v207/kJEhBvYX7BgnkSrUwT8OhrdQw4oELdPIeeII9v6oFsLjBuVY.woff2) 14 | format("woff2"); 15 | } 16 | 17 | .icon { 18 | font-family: "Material Symbols Outlined"; 19 | font-weight: normal; 20 | font-style: normal; 21 | font-size: 24px; 22 | line-height: 1; 23 | letter-spacing: normal; 24 | text-transform: none; 25 | display: inline-block; 26 | white-space: nowrap; 27 | word-wrap: normal; 28 | direction: ltr; 29 | -webkit-font-feature-settings: "liga"; 30 | -webkit-font-smoothing: antialiased; 31 | font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24; 32 | } 33 | 34 | pre { 35 | background: var(--gray-10); 36 | color: var(--gray-2); 37 | padding-block: var(--size-3); 38 | padding-inline: var(--size-5); 39 | border-radius: var(--radius-3); 40 | max-width: 90vw; 41 | margin: 0 auto; 42 | overflow-x: auto; 43 | } 44 | 45 | code { 46 | font-family: "Monaspace", monospace; 47 | font-feature-settings: "colr", "calt"; 48 | } 49 | 50 | body { 51 | display: grid; 52 | place-content: center; 53 | padding-block: 15vmin; 54 | padding-inline: 5vmin; 55 | } 56 | -------------------------------------------------------------------------------- /carousel-configurator/static/MonaspaceKrypton-SyntaxHighlighter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousel-configurator/static/MonaspaceKrypton-SyntaxHighlighter-Regular.woff2 -------------------------------------------------------------------------------- /carousel-configurator/static/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 12 | -------------------------------------------------------------------------------- /carousel-configurator/svelte.config.js: -------------------------------------------------------------------------------- 1 | import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; 2 | import adapter from '@sveltejs/adapter-static'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | preprocess: vitePreprocess(), 7 | kit: { 8 | adapter: adapter({ 9 | pages: 'build', 10 | assets: 'build', 11 | fallback: undefined, 12 | precompress: false, 13 | strict: true 14 | }) 15 | } 16 | }; 17 | 18 | export default config; 19 | -------------------------------------------------------------------------------- /carousel-configurator/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "moduleResolution": "bundler" 13 | } 14 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 15 | // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files 16 | // 17 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 18 | // from the referenced tsconfig.json - TypeScript does not merge them in 19 | } 20 | -------------------------------------------------------------------------------- /carousel-configurator/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import { defineConfig } from 'vite'; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()] 6 | }); 7 | -------------------------------------------------------------------------------- /carousels-gallery/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | 4 | # generated types 5 | .astro/ 6 | .vscode/ 7 | 8 | # dependencies 9 | node_modules/ 10 | 11 | # logs 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | 17 | # environment variables 18 | .env 19 | .env.production 20 | 21 | # macOS-specific files 22 | .DS_Store 23 | 24 | # jetbrains setting folder 25 | .idea/ 26 | -------------------------------------------------------------------------------- /carousels-gallery/README.md: -------------------------------------------------------------------------------- 1 | # Astro Starter Kit: Basics 2 | 3 | ![just-the-basics](https://github.com/withastro/astro/assets/2244813/a0a5533c-a856-4198-8470-2d67b1d7c554) 4 | 5 | ## 🚀 Project Structure 6 | 7 | Inside of your Astro project, you'll see the following folders and files: 8 | 9 | ```text 10 | / 11 | ├── public/ 12 | │ └── favicon.svg 13 | ├── src/ 14 | │ ├── components/ 15 | │ │ └── Card.astro 16 | │ ├── layouts/ 17 | │ │ └── Layout.astro 18 | │ └── pages/ 19 | │ └── index.astro 20 | └── package.json 21 | ``` 22 | 23 | Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. 24 | 25 | There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. 26 | 27 | Any static assets, like images, can be placed in the `public/` directory. 28 | 29 | ## 🧞 Commands 30 | 31 | All commands are run from the root of the project, from a terminal: 32 | 33 | | Command | Action | 34 | | :------------------------ | :----------------------------------------------- | 35 | | `npm install` | Installs dependencies | 36 | | `npm run dev` | Starts local dev server at `localhost:4321` | 37 | | `npm run build` | Build your production site to `./dist/` | 38 | | `npm run preview` | Preview your build locally, before deploying | 39 | | `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | 40 | | `npm run astro -- --help` | Get help using the Astro CLI | 41 | | `npm run deploy` | Insert files to `./dist/`, sync to `./dist` | 42 | 43 | ## 👀 Want to learn more? 44 | 45 | Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). 46 | -------------------------------------------------------------------------------- /carousels-gallery/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "astro/config"; 2 | import sitemap from "@astrojs/sitemap"; 3 | 4 | // https://astro.build/config 5 | export default defineConfig({ 6 | integrations: [sitemap()], 7 | devToolbar: { 8 | enabled: false, 9 | }, 10 | site: "https://chrome.dev", 11 | base: "/carousel/", 12 | trailingSlash: "always", 13 | output: "static", 14 | }); 15 | -------------------------------------------------------------------------------- /carousels-gallery/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carousels-gallery", 3 | "type": "module", 4 | "author": { 5 | "name": "Adam Argyle", 6 | "url": "https://nerdy.dev" 7 | }, 8 | "description": "Collection of rad CSS only carousels.", 9 | "keywords": [ 10 | "CSS", 11 | "Scroll Markers", 12 | "Scroll Buttons", 13 | "Scroll State Queries", 14 | "Scroll Driven Animation", 15 | "Scroll Snap", 16 | "interactivity: inert" 17 | ], 18 | "version": "1.0.0", 19 | "scripts": { 20 | "dev": "astro dev", 21 | "start": "astro dev", 22 | "build": "astro check && astro build", 23 | "preview": "astro preview", 24 | "astro": "astro", 25 | "deploy": "npm run add-gitignores && cp package.json dist/ && gsutil -m rsync -rd dist gs://chrome-dev-demos/public/carousel", 26 | "add-gitignores": "find dist -type d -mindepth 1 -exec touch {}/.ignore \\;" 27 | }, 28 | "dependencies": { 29 | "@astrojs/check": "^0.9.4", 30 | "@astrojs/sitemap": "^3.2.1", 31 | "astro": "^5.0.4", 32 | "open-props": "^1.7.8", 33 | "typescript": "^5.7.2" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /carousels-gallery/public/chameleon.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/chameleon.mp4 -------------------------------------------------------------------------------- /carousels-gallery/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 12 | -------------------------------------------------------------------------------- /carousels-gallery/public/flora-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/flora-1.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/flora-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/flora-2.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/flora-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/flora-3.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/flora-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/flora-4.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/flying-cars-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/flying-cars-2.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/flying-cars-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/flying-cars-3.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/flying-cars.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/flying-cars.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/fold-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/fold-1.png -------------------------------------------------------------------------------- /carousels-gallery/public/fold-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/fold-2.png -------------------------------------------------------------------------------- /carousels-gallery/public/fold-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/fold-3.png -------------------------------------------------------------------------------- /carousels-gallery/public/fold-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/fold-4.png -------------------------------------------------------------------------------- /carousels-gallery/public/fold-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/fold-5.png -------------------------------------------------------------------------------- /carousels-gallery/public/googletv-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /carousels-gallery/public/hot-fuss.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/hot-fuss.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/material-symbols.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/material-symbols.woff2 -------------------------------------------------------------------------------- /carousels-gallery/public/neon-city.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/neon-city.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/neon-raptor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/neon-raptor.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/neon-trex.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/neon-trex.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/neon-wolf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/neon-wolf.jpg -------------------------------------------------------------------------------- /carousels-gallery/public/snow.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/snow.mp4 -------------------------------------------------------------------------------- /carousels-gallery/public/turtle.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/turtle.mp4 -------------------------------------------------------------------------------- /carousels-gallery/public/wheel.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/carousels-gallery/public/wheel.mp4 -------------------------------------------------------------------------------- /carousels-gallery/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /carousels-gallery/src/layouts/Layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Sidebar from "../components/Sidebar.astro"; 3 | 4 | interface Props { 5 | title: string; 6 | } 7 | 8 | const { title } = Astro.props; 9 | --- 10 | 11 | 12 | 13 | 14 | 15 | 19 | 23 | 24 | 31 | 44 | {title} 45 | 46 | 47 | 50 |
51 |

⚠️ Unsupported features ⚠️

52 |

53 | This gallery requires a few CSS features that aren't currently available 54 | in your browser. These features are available in Chrome 135+ and other 55 | Chromium-based browsers. 56 |

57 |
58 |
59 | 60 | 61 |
62 | 63 | 64 | 65 | 68 | 69 | 140 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/bidi/grid.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Bi-Directional Grid

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll Initial Target 13 | Anchor 14 |
15 |

16 | Scroll buttons on all sides plus markers for each snap target. This demo 17 | puts everything all together for, what no longer feels like a carousel, 18 | and is instead a manifestation of scroll affordances on a grid. 19 |

20 |
21 | 22 |
23 | 100 |
101 |
102 |
103 | 104 | 171 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/3d.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

3D

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll Driven Animation 13 | Scroll Initial Target 14 | Anchor 15 |
16 |

17 |
18 | 19 |
20 | 73 |
74 |
75 |
76 | 77 | 178 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/app-switcher.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

App Switcher

9 |
10 | Scroll Buttons 11 | Scroll Driven Animation 12 |
13 |

14 | This carousel is akin to the Android and iOS app switcher experiences 15 | where a user horizontally pans through their apps and then chooses one. 16 | Most of the work is done with scroll driven animations, but the scroll 17 | button affordance adds a nice "web style" flare to the experience. 18 |

19 |
20 | 21 |
22 | 96 |
97 |
98 | 99 | 238 |
239 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/cards.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Horizontal Cards

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll-State Queries 13 | Scroll Initial Target 14 | Anchor 15 | Full Bleed 16 |
17 |

Buttons and markers both anchored to the bottom

18 |
19 | 20 |
21 | 142 |
143 |
144 |
145 | 146 | 240 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/curved.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Curved

9 |
10 | Scroll Buttons 11 | Lazy loading 12 | Anchor 13 |
14 |

Just a neat mask illusion.

15 |
16 | 17 |
18 | 38 |
39 |
40 |
41 | 42 | 110 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/gallery.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Image Gallery

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll-State Queries 13 | Anchor 14 |
15 |
16 | 17 |
18 | 99 |
100 |
101 | 102 | 160 |
161 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/hubs.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Hubs

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll-State Queries 13 | Paged 14 | Anchor 15 |
16 |

17 | These are established pages in the markup. See Pages for an automatic paging example. 20 |

21 |
22 | 23 |
24 | 59 |
60 |
61 | 62 | 142 |
143 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/list.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Horizontal List

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll State Queries 13 | Scroll Driven Animation 14 | interactivity: inert 15 | Anchor 16 |
17 |

18 | This is a regular list of items, but they've been given tabindex=0 so they can be focused. In addition, interactivity: inert 21 | is used with scroll driven animation view(x) to make offscreen 22 | items non-focusable. Items in this state also have reduced opacity. 23 |

24 |

25 | Scroll buttons also responsively adapt to inner or outer positioning 26 | based on availability! 27 |

28 |
29 | 30 |
31 | 84 |
85 |
86 |
87 | 88 | 143 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/media-player.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Media Player

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll Driven Animation 13 | interactivity: inert 14 | Anchor 15 |
16 |

17 | Scroll buttons are used as next and previous track controls and scroll 18 | markers are each track, appearing to be a playlist while still 19 | functioning the same as if they were dots. 20 |

21 |

22 | Very nice that the next and previous track buttons automatically disable 23 | when at the end or beginning. 24 |

25 |
26 | 27 |
28 |
29 | 42 |
43 |
44 |

The Killers

45 |
46 | 47 |
48 | 51 |
52 |
53 |
54 |
55 | 56 | 261 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/pages.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Automatic Pages

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll-State Queries 13 | Dynamic Columns 14 | Anchor 15 |
16 |

17 | Pages are automatically generated based on the number of items that can 18 | fit into a ::column. Try resizing it to see the column 19 | layout adjust the items per page. 20 |

21 |
22 | 23 |
24 | 77 |
78 |
79 | 80 | 162 |
163 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/product.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Product Gallery

9 |
10 | Grid 11 | Scroll Markers 12 | Container Queries 13 | Scroll-State Queries 14 |
15 |

16 | Classic product image gallery. Markers are mirrored images of the 17 | products without duplicating elements. The screen reader experience when 18 | navigating via the scroll markers is provided the alt text from the 19 | image. 20 |

21 |
22 | 23 | 109 |
110 | 111 | 235 |
236 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/slider.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Hero Slider

9 |
10 | Scroll Buttons 11 | Scroll-State Queries 12 | Anchor 13 |
14 |
15 | 16 |
17 | 100 |
101 |
102 | 103 | 202 |
203 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/tabs.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Tabs

9 |
10 | Scroll Markers 11 | Scroll-State Queries 12 | interactivity: inert 13 | Anchor 14 |
15 |

16 | Yep, these tab buttons on top are "just scroll markers" with contextual 17 | text inside. 18 |

19 |

20 | See also Scrollspy 21 | and TV Series. 22 |

23 |
24 | 25 |
26 | 97 |
98 | 99 | 195 |
196 |
197 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/testimonials.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Testimonials

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll-State Queries 13 | Anchor 14 |
15 |

16 | Conditional scroll buttons featured in this demo. Hidden, unless the 17 | visiting user has a hover enabled device and is actively hovering the carousel 18 | or keyboard focus is active within the carousel. 19 |

20 |
21 | 22 |
23 | 67 |
68 |
69 | 70 | 136 |
137 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/video.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Video Slider

9 |
10 | Scroll Buttons 11 | Scroll Driven Animation 12 | Anchor 13 | Sticky 14 |
15 |

16 | This example demonstrates a horizontal video slider with scroll buttons. 17 | Scroll driven animation creates a neat parallax and mask effect as you 18 | scroll AND scroll driven animation is incrementing a counter to show the 19 | current page against the total. 20 |

21 |
22 | 23 |
24 | 77 |
78 | 86 |
87 |
88 | 89 | 293 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/weather.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Weather

9 |
10 | Scroll Markers 11 | Anchor 12 |
13 |

14 | A tiny weather widget. Carousels don't always have to be full bleed 15 | animated sliders. This example is from the Android homescreen, showing 16 | contextual messages given the moment. 17 |

18 |
19 | 20 |
21 | 95 |
96 |
97 | 98 | 166 |
167 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/horizontal/wizard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Wizard

9 |
10 | Scroll Markers 11 | Scroll-State Queries 12 | interactivity: inert 13 | Anchor 14 |
15 |

16 | Keep track of user's along a guided process with scroll markers. The 17 | scroll-state() queries inert any form the user isn't currently on. 18 |

19 |

20 | If there's no form elements or numbers, this is often called 21 | "onboarding." Here's a collection of onboarding demos that you could rebuild with CSS carousel markers easily. 25 |

26 |
27 | 28 |
29 | 70 |
71 |
72 | 73 | 210 |
211 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Welcome!

9 |

10 | You've landed on the CSS Carousel Gallery site that showcases the 11 | capabilities and potentials of CSS Carousel specs. 12 |

13 |

There's not a single line of JavaScript in this gallery.

14 |
15 |
16 |
    17 |
  1. 18 | 29 |
    30 | Explore the horizontal, vertical and bi-directional examples in 31 | the left side navigation (or hambuger if on mobile) 32 |
    33 |
  2. 34 |
  3. 35 | 45 |
    46 | Review each demo's tags the CSS feature being showcased in the 47 | example 48 |
    49 |
  4. 50 |
  5. 51 | 61 |
    62 | Checkout the Resources to follow specs or reference details 63 |
    64 |
  6. 65 |
  7. 66 | 76 |
    77 | Inspect the CSS, review the DOM, and check the accessibility tree 78 |
    79 |
  8. 80 |
81 |
82 | 85 |
86 |
87 | 88 | 135 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/vertical/list.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Vertical List

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll-State Queries 13 | Anchor 14 |
15 | 16 |

A basic vertical carousel example with scroll buttons and markers.

17 |
18 | 19 |
20 | 73 |
74 |
75 |
76 | 77 | 140 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/vertical/scroll-spy.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Scroll Spy

9 |
10 | Scroll Markers 11 | Grid 12 |
13 |

14 | This scroll spy component uses scroll markers as in-page links to a 15 | section of content. Scroll markers are aware and stateful to the section 16 | they were generated with, and we use this to highlight the titles. 17 |

18 |

19 | Check the mobile layout, it looks a lot like tabs. It's also very much a vertical variant on the TV Series demo, but it doesn't start you at your current episode. 24 |

25 |
26 | 27 |
28 | 29 | 134 |
135 |
136 | 137 | 251 |
252 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/vertical/slides.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Vertical Slides

9 |
10 | Scroll Markers 11 | Scroll-State Queries 12 | Anchor 13 |
14 |

15 | A basic vertical set of slides with scroll-state() for knowing which 16 | slide is active and anchoring for easily positioning the markers. 17 |

18 |
19 | 20 |
21 | 41 |
42 |
43 |
44 | 45 | 95 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/vertical/stack.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Vertical Stack

9 |
10 | Scroll Buttons 11 | Scroll Driven Animation 12 | Scroll-State Queries 13 | Anchor 14 |
15 |

16 | A vertical scroll that creates a stack effect. Most of the effect is 17 | scroll driven animation but the added scroll button is a meaningful 18 | affordance and scroll hint. 19 |

20 |
21 | 22 |
23 | 70 |
71 |
72 |
73 | 74 | 171 | -------------------------------------------------------------------------------- /carousels-gallery/src/pages/vertical/wheel.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from "../../layouts/Layout.astro"; 3 | --- 4 | 5 | 6 |
7 |
8 |

Wheel

9 |
10 | Scroll Buttons 11 | Scroll Markers 12 | Scroll-State Queries 13 | Scroll Driven Animation 14 | Anchor 15 |
16 |

A classic vertical wheel of choices carousel.

17 |
18 | 19 |
20 | 73 |
74 |
75 |
76 | 77 | 164 | -------------------------------------------------------------------------------- /carousels-gallery/src/styles/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Material Symbols Outlined"; 3 | font-style: normal; 4 | font-weight: 100 700; 5 | font-display: block; 6 | src: url(/carousel/material-symbols.woff2) format("woff2"); 7 | } 8 | 9 | .icon { 10 | font-family: "Material Symbols Outlined"; 11 | font-weight: normal; 12 | font-style: normal; 13 | font-size: 24px; 14 | line-height: 1; 15 | letter-spacing: normal; 16 | text-transform: none; 17 | display: inline-block; 18 | white-space: nowrap; 19 | word-wrap: normal; 20 | direction: ltr; 21 | -webkit-font-feature-settings: "liga"; 22 | -webkit-font-smoothing: antialiased; 23 | font-variation-settings: 24 | "FILL" 0, 25 | "wght" 400, 26 | "GRAD" 0, 27 | "opsz" 24; 28 | } 29 | -------------------------------------------------------------------------------- /carousels-gallery/src/styles/index.css: -------------------------------------------------------------------------------- 1 | @layer system, components, utilities; 2 | 3 | @import "open-props/style" layer(system); 4 | @import "open-props/normalize" layer(system); 5 | @import "open-props/buttons" layer(system); 6 | 7 | @import "./fonts.css" layer(system); 8 | @import "./utilities.css" layer(utilities); 9 | 10 | @view-transition { 11 | navigation: auto; 12 | } 13 | 14 | code { 15 | background: light-dark(white, var(--gray-10)); 16 | 17 | @supports (text-box: cap alphabetic) { 18 | text-box: cap alphabetic; 19 | line-height: 1cap; 20 | padding-block: .25cap; 21 | } 22 | } -------------------------------------------------------------------------------- /carousels-gallery/src/styles/utilities.carousel.css: -------------------------------------------------------------------------------- 1 | /* `.carousel` elements 2 | * -------------------------------------------------------------------------*/ 3 | 4 | 5 | .carousel { 6 | anchor-name: --carousel; 7 | container-type: inline-size; 8 | 9 | /* scroll styles */ 10 | overflow-x: auto; 11 | overscroll-behavior-x: contain; 12 | scroll-snap-type: x mandatory; 13 | scrollbar-width: none; 14 | 15 | &:focus-visible { 16 | scrollbar-color: var(--link) transparent; 17 | outline: none; 18 | } 19 | 20 | @media (prefers-reduced-motion: no-preference) { 21 | scroll-behavior: smooth; 22 | } 23 | } 24 | 25 | .carousel__slide { 26 | scroll-snap-align: start; 27 | 28 | :where(.carousel--offscreen-inert) & { 29 | animation: offscreen-inert linear both; 30 | animation-timeline: view(x); 31 | } 32 | 33 | :where(.carousel--unsnapped-inert) & { 34 | animation: offscreen-inert linear both; 35 | animation-timeline: view(x); 36 | } 37 | 38 | :where(.carousel--unsnapped-inert) & { 39 | container-type: scroll-state; 40 | 41 | & > * { 42 | @container not scroll-state(snapped) { 43 | interactivity: inert; 44 | } 45 | } 46 | } 47 | } 48 | 49 | /* `.carousel` states 50 | * -------------------------------------------------------------------------*/ 51 | 52 | .carousel--vertical { 53 | /* scroll styles */ 54 | overflow-y: auto; 55 | overscroll-behavior-y: contain; 56 | scroll-snap-type: y mandatory; 57 | } 58 | 59 | .carousel--bidi { 60 | /* scroll styles */ 61 | overflow: auto; 62 | overscroll-behavior: contain; 63 | scroll-snap-type: both mandatory; 64 | } 65 | 66 | .carousel--scroll-markers { 67 | scroll-marker-group: before; 68 | 69 | &::scroll-marker-group { 70 | position: absolute; 71 | position-anchor: --carousel; 72 | 73 | container: marker-group / inline-size; 74 | 75 | display: grid; 76 | gap: var(--size-2); 77 | place-content: safe center; 78 | box-sizing: border-box; 79 | border-radius: var(--radius-round); 80 | 81 | scrollbar-width: none; 82 | scroll-behavior: smooth; 83 | } 84 | 85 | &:where(:not(.carousel--vertical), .carousel--bidi)::scroll-marker-group { 86 | inline-size: 100%; 87 | max-inline-size: min(90cqi, 210px); 88 | overflow-x: auto; 89 | scroll-snap-type: x mandatory; 90 | overscroll-behavior-x: contain; 91 | 92 | padding: 5px 10px; /* space for focus and scroll */ 93 | scroll-padding-inline: 10px; 94 | mask: linear-gradient(to right, transparent 0, black 10px, black calc(100% - 10px), transparent 100%); 95 | 96 | top: anchor(bottom); 97 | left: calc(anchor(left) - 10%); 98 | right: calc(anchor(right) - 10%); 99 | margin-block: var(--size-3); 100 | 101 | grid-auto-columns: var(--size-3); 102 | grid-auto-flow: column; 103 | justify-self: center; 104 | } 105 | 106 | &:where(.carousel--vertical)::scroll-marker-group { 107 | position-area: left center; 108 | 109 | margin-inline: var(--size-3); 110 | overflow-y: auto; 111 | scroll-snap-type: y mandatory; 112 | 113 | inline-size: var(--size-5); 114 | block-size: 80cqb; 115 | max-block-size: min(50cqb, 210px); 116 | 117 | grid-auto-rows: var(--size-3); 118 | grid-auto-flow: row; 119 | 120 | padding-block: 10px; /* space for mask */ 121 | padding-inline: 0; 122 | scroll-padding-block: 10px; 123 | mask: linear-gradient(to bottom, transparent 0, black 10px, black calc(100% - 10px), transparent 100%); 124 | } 125 | 126 | .carousel__slide { 127 | &::scroll-marker { 128 | content: "" / attr(data-label); 129 | scroll-snap-align: center; 130 | aspect-ratio: 1; 131 | border: 1px solid light-dark(var(--gray-6), var(--surface-4)); 132 | border-radius: var(--radius-round); 133 | cursor: pointer; 134 | -webkit-tap-highlight-color: transparent; 135 | text-decoration: none; 136 | -webkit-tap-highlight-color: transparent; 137 | transition: 138 | transform 0.3s var(--ease-spring-2), 139 | outline-offset 0.25s var(--ease-3) 140 | ; 141 | animation: scale-in-and-out linear both; 142 | animation-timeline: view(x); 143 | 144 | /* todo: remove once marker `interactivity` is inherited from `::scroll-marker-group` */ 145 | interactivity: auto; 146 | } 147 | 148 | &::scroll-marker:target-current { 149 | background: var(--link); 150 | border-color: var(--link); 151 | } 152 | 153 | @media (forced-colors: active) { 154 | &::scroll-marker:target-current { 155 | background: Highlight; 156 | border-color: Highlight; 157 | } 158 | } 159 | 160 | &::scroll-marker:not(:active):hover { 161 | transform: scale(1.25); 162 | } 163 | 164 | /* todo: switch backt of focus-visible */ 165 | &::scroll-marker:not(:active):focus { 166 | outline: 2px solid var(--link); 167 | outline-offset: 2px; 168 | } 169 | 170 | :where(.carousel--vertical) &::scroll-marker { 171 | animation-timeline: view(y); 172 | } 173 | } 174 | } 175 | 176 | /* TODO: 177 | up, down 178 | use scroll-state(scrollable) to auto generate buttons */ 179 | .carousel--scroll-buttons { 180 | &::scroll-button(*) { 181 | cursor: pointer; 182 | -webkit-tap-highlight-color: transparent; 183 | 184 | position: absolute; 185 | z-index: 1; 186 | position-anchor: --carousel; 187 | 188 | font-size: var(--font-size-3); 189 | inline-size: 44px; 190 | margin: var(--size-3); 191 | 192 | font-family: "Material Symbols Outlined"; 193 | line-height: 1; 194 | font-variation-settings: 195 | "FILL" 0, 196 | "wght" 100, 197 | "GRAD" 0, 198 | "opsz" 24; 199 | 200 | display: flex; 201 | place-items: center; 202 | place-content: center; 203 | aspect-ratio: 1; 204 | background: none; 205 | border: 1px solid var(--surface-3); 206 | border-radius: var(--radius-round); 207 | 208 | transition: 209 | transform 0.3s var(--ease-spring-3), 210 | opacity 0.5s var(--ease-3), 211 | background-color 0.3s var(--ease-3), 212 | outline-offset 0.25s var(--ease-3); 213 | 214 | @media (forced-colors: active) { 215 | background: Canvas; 216 | } 217 | } 218 | 219 | &:where(:not(.carousel--vertical), .carousel--bidi) { 220 | &::scroll-button(right) { 221 | --_inner: center span-inline-start; 222 | --_inner-under: block-end span-inline-start; 223 | --_inner-over: block-start span-inline-start; 224 | --_outer: inline-end center; 225 | --_outer-under: end; 226 | --_outer-over: block-start inline-end; 227 | 228 | position-area: var(--_outer); 229 | content: "arrow_forward" / "Scroll Right"; 230 | } 231 | &::scroll-button(left) { 232 | --_inner: center span-inline-end; 233 | --_inner-under: block-end span-inline-end; 234 | --_inner-over: block-start span-inline-end; 235 | --_outer: inline-start center; 236 | --_outer-under: block-end inline-start; 237 | --_outer-over: start; 238 | 239 | position-area: var(--_outer); 240 | content: "arrow_back" / "Scroll Left"; 241 | } 242 | 243 | /* 120px is both arrows plus their margins */ 244 | /* inner arrows when carousel is reaching full width of viewport or container */ 245 | @container (inline-size >= calc(100cqi - 120px)) { 246 | &::scroll-button(right), 247 | &::scroll-button(left) { 248 | position-area: var(--_inner); 249 | } 250 | } 251 | } 252 | 253 | &:where(.carousel--vertical, .carousel--bidi) { 254 | &::scroll-button(down) { 255 | --_inner: center span-block-start; 256 | --_inner-under: block-end span-inline-end; 257 | --_inner-over: span-block-start span-inline-end; 258 | --_outer: block-end; 259 | --_outer-under: inline-start span-block-start; 260 | --_outer-over: inline-start block-end; 261 | 262 | position-area: var(--_outer); 263 | content: "arrow_downward" / "Scroll Down"; 264 | } 265 | &::scroll-button(up) { 266 | --_inner: center span-block-end; 267 | --_inner-under: span-inline-end block-start; 268 | --_inner-over: span-inline-end span-block-end; 269 | --_outer: block-start; 270 | --_outer-under: inline-start span-block-end; 271 | --_outer-over: block-start inline-start; 272 | 273 | position-area: var(--_outer); 274 | content: "arrow_upward" / "Scroll Up"; 275 | } 276 | 277 | /* 120px is both arrows plus their margins */ 278 | /* inner arrows when carousel is reaching full height of viewport or container */ 279 | @container (block-size >= calc(100cqb - 120px)) { 280 | &::scroll-button(up), 281 | &::scroll-button(down) { 282 | position-area: var(--_inner); 283 | } 284 | } 285 | } 286 | 287 | &::scroll-button(*):not(:disabled):is(:hover, :focus-visible) { 288 | background-color: light-dark(white, var(--surface-1)); 289 | border-color: var(--surface-4); 290 | font-variation-settings: "opsz" 30; 291 | transform: scale(1.1); 292 | } 293 | 294 | &::scroll-button(*):not(:active):focus-visible { 295 | outline-offset: 2px; 296 | outline: 2px solid var(--link); 297 | } 298 | 299 | &::scroll-button(right):not(:disabled):active { 300 | transform: translateX(5px) scale(0.95); 301 | } 302 | &::scroll-button(left):not(:disabled):active { 303 | transform: translateX(-5px) scale(0.95); 304 | } 305 | &::scroll-button(up):not(:disabled):active { 306 | transform: translateY(-5px) scale(0.95); 307 | } 308 | &::scroll-button(down):not(:disabled):active { 309 | transform: translateY(5px) scale(0.95); 310 | } 311 | 312 | &::scroll-button(*):disabled { 313 | opacity: 25%; 314 | cursor: not-allowed; 315 | } 316 | } 317 | 318 | /* `.carousel` animations 319 | * -------------------------------------------------------------------------*/ 320 | 321 | @keyframes scale-in-and-out { 322 | entry 0% { 323 | transform: scale(.25); 324 | } 325 | entry 100% { 326 | transform: scale(1); 327 | } 328 | 329 | exit 0% { 330 | transform: scale(1); 331 | } 332 | exit 100% { 333 | transform: scale(.25); 334 | } 335 | } 336 | 337 | @keyframes offscreen-inert { 338 | entry 0%, exit 100% { 339 | interactivity: inert; 340 | } 341 | entry 100%, exit 0% { 342 | interactivity: auto; 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /carousels-gallery/src/styles/utilities.css: -------------------------------------------------------------------------------- 1 | @import "utilities.tags.css"; 2 | @import "utilities.carousel.css"; 3 | 4 | .scroll-start { 5 | scroll-initial-target: nearest; 6 | } -------------------------------------------------------------------------------- /carousels-gallery/src/styles/utilities.tags.css: -------------------------------------------------------------------------------- 1 | .tags { 2 | display: flex; 3 | flex-wrap: wrap; 4 | gap: var(--size-2); 5 | max-inline-size: var(--size-content-3); 6 | 7 | > * { 8 | border: .5px solid var(--surface-2); 9 | background: light-dark(white, var(--surface-2)); 10 | padding: var(--size-1) var(--size-3); 11 | border-radius: var(--radius-round); 12 | box-shadow: var(--shadow-1); 13 | } 14 | } -------------------------------------------------------------------------------- /carousels-gallery/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/base" 3 | } 4 | -------------------------------------------------------------------------------- /has-ua-visual-transition/README.md: -------------------------------------------------------------------------------- 1 | # hasUAVisualTransition 2 | 3 | Testpages for `PopStateEvent#hasUAVisualTransition` and `NavigateEvent#hasUAVisualTransition` 4 | 5 | ## Instructions 6 | 7 | - Launch the project 8 | - Choose the flavor you want to test 9 | - Click the link a few times 10 | - Navigate back, using the UA back button or using a swipe gesture. 11 | - Check the reported value for `hasUAVisualTransition` 12 | 13 | ## Launching the project 14 | 15 | ### Locally 16 | 17 | - Run `npx serve src` 18 | - Visit http://localhost:3000 19 | 20 | ### Online 21 | 22 | - Visit https://chrome.dev/has-ua-visual-transition/ 23 | 24 | ## Publication 25 | 26 | This demo gets published to https://chrome.dev/. Publishing is only possible by Googlers with proper access. 27 | 28 | ``` 29 | gcloud auth login 30 | gsutil -m rsync -rd src gs://chrome-dev-demos/public/has-ua-visual-transition 31 | ``` -------------------------------------------------------------------------------- /has-ua-visual-transition/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Pages 12 | 13 | 14 |

Choose your flavor

15 | 20 | 21 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa-navigation/. ignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/has-ua-visual-transition/src/mpa-navigation/. ignore -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa-navigation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (MPA + Navigation API) 12 | 13 | 14 | 15 |

To page 2

16 |

hasUAVisualTransition: (firstpage)

17 | 18 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa-navigation/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (MPA + Navigation API) 12 | 13 | 14 | 15 |

To page 3

16 |

hasUAVisualTransition: (firstpage)

17 | 18 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa-navigation/index3.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (MPA + Navigation API) 12 | 13 | 14 | 15 |

To page 4

16 |

hasUAVisualTransition: (firstpage)

17 | 18 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa-navigation/index4.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (MPA + Navigation API) 12 | 13 | 14 | 15 |

(There is no next page)

16 |

hasUAVisualTransition: (firstpage)

17 | 18 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa-navigation/scripts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | // Keep track of the last successful navigation 7 | navigation.lastSuccessfulEntry = navigation?.currentEntry; 8 | navigation.addEventListener('navigatesuccess', e => { 9 | navigation.lastSuccessfulEntry = e.currentTarget.currentEntry; 10 | }); 11 | 12 | // Turn our MPA into an SPA … WOOHOOW! 13 | navigation.addEventListener("navigate", (e) => { 14 | 15 | // Don’t intercept when we shouldn’t 16 | if (shouldNotIntercept(e)) { 17 | return; 18 | } 19 | 20 | e.intercept({ 21 | handler: async () => { 22 | 23 | // @TODO: show loading while fetch is running … 24 | 25 | // @TODO: Maybe I should move this whole fetch logic to the outside of e.intercept? 26 | // Because on slow connections you end up with an updated URL but with the old content still visible … 27 | 28 | // Get new HTML 29 | const response = await fetch(e.destination.url, { 30 | signal: e.signal, // @ref https://developer.chrome.com/docs/web-platform/navigation-api/#abort_signals 31 | }); 32 | const html = await response.text(); 33 | const parser = new DOMParser(); 34 | const doc = parser.parseFromString(html, "text/html"); 35 | const $body = doc.querySelector("body"); 36 | const $title = doc.querySelector("head title"); 37 | 38 | const update = (hasUAVisualTransition) => { 39 | document.title = $title.innerText; 40 | document.querySelector('body').replaceWith($body); // You do trust your own markup, right? 41 | document.querySelector('output').innerText = hasUAVisualTransition; 42 | }; 43 | 44 | // The UA already provided us with a Visual Transition, 45 | // there is no need to do one ourselves. 46 | if (e.hasUAVisualTransition) { 47 | update(true); 48 | } 49 | 50 | // Go View Transitions, go! 51 | else { 52 | const t = document.startViewTransition(() => { 53 | update(false); 54 | }); 55 | } 56 | } 57 | }); 58 | }); 59 | 60 | // Helper function to determine if a navigation should be intercepted or not 61 | // @src https://developer.chrome.com/docs/web-platform/navigation-api/#deciding_how_to_handle_a_navigation 62 | const shouldNotIntercept = (navigationEvent) => { 63 | return ( 64 | !navigationEvent.canIntercept || 65 | // If this is just a hashChange, 66 | // just let the browser handle scrolling to the content. 67 | navigationEvent.hashChange || 68 | // If this is a download, 69 | // let the browser perform the download. 70 | navigationEvent.downloadRequest || 71 | // If this is a form submission, 72 | // let that go to the server. 73 | navigationEvent.formData 74 | ); 75 | }; 76 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa/. ignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/has-ua-visual-transition/src/mpa/. ignore -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa/index.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (MPA) 12 | 13 | 14 | 15 |

To page 2

16 |

hasUAVisualTransition: undefined

17 | 18 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (MPA) 12 | 13 | 14 | 15 |

To page 3

16 |

hasUAVisualTransition: undefined

17 | 18 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa/index3.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (MPA) 12 | 13 | 14 | 15 |

To page 4

16 |

hasUAVisualTransition: undefined

17 | 18 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa/index4.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (MPA) 12 | 13 | 14 | 15 |

(There is no next page)

16 |

hasUAVisualTransition: undefined

17 | 18 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/mpa/scripts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | window.addEventListener('pagereveal', (event) => { 7 | let hasUAVisualTransition; 8 | if (!('hasUAVisualTransition' in PageRevealEvent.prototype)) { 9 | hasUAVisualTransition = 'unsupported (PageRevealEvent.hasUAVisualTransition)'; 10 | } else { 11 | hasUAVisualTransition = event.hasUAVisualTransition ? 'true' : 'false'; 12 | } 13 | document.querySelector('output').innerText = hasUAVisualTransition; 14 | }); 15 | 16 | document.addEventListener('DOMContentLoaded', (event) => { 17 | if (!('PageRevealEvent' in window)) { 18 | document.querySelector('output').innerText = 'unsupported (PageRevealEvent)'; 19 | } 20 | }); -------------------------------------------------------------------------------- /has-ua-visual-transition/src/spa/. ignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/css-web-ui-demos/6f3fe34f6571022115cb49c7a5aea1f2f29c6810/has-ua-visual-transition/src/spa/. ignore -------------------------------------------------------------------------------- /has-ua-visual-transition/src/spa/index.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | hasUAVisualTransition Test Page (SPA) 12 | 13 | 14 | 15 |

You are on page 1

16 |

To page 2

17 |

hasUAVisualTransition: (firstpage)

18 | 19 | -------------------------------------------------------------------------------- /has-ua-visual-transition/src/spa/scripts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Google LLC 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | window.addEventListener("popstate", (event) => { 7 | console.log('popstate'); 8 | let hasUAVisualTransition; 9 | if (!('hasUAVisualTransition' in PopStateEvent.prototype)) { 10 | hasUAVisualTransition = 'unsupported'; 11 | } else { 12 | hasUAVisualTransition = event.hasUAVisualTransition ? 'true' : 'false'; 13 | } 14 | 15 | document.querySelector('output').innerText = hasUAVisualTransition; 16 | curPage = event.state?.curPage ?? 1; 17 | document.querySelector('#curPage').innerText = `${curPage}`; 18 | document.querySelector('a').innerText = `To page ${curPage + 1}`; 19 | }); 20 | 21 | let curPage = 1; 22 | document.addEventListener('DOMContentLoaded', () => { 23 | document.querySelector('a').addEventListener('click', (e) => { 24 | e.preventDefault(); 25 | 26 | // Update page 27 | curPage++; 28 | 29 | // Reflect page in UI 30 | history.pushState({ curPage }, ''); 31 | document.querySelector('#curPage').innerText = `${curPage}`; 32 | document.querySelector('a').innerText = `To page ${curPage + 1}`; 33 | 34 | // Update hasUAVisualTransition 35 | let hasUAVisualTransition; 36 | if (!('hasUAVisualTransition' in PopStateEvent.prototype)) { 37 | hasUAVisualTransition = 'unsupported'; 38 | } else { 39 | hasUAVisualTransition = 'false'; // Because we navigated, it is always false 40 | } 41 | document.querySelector('output').innerText = hasUAVisualTransition; 42 | }); 43 | }) --------------------------------------------------------------------------------