├── .nvmrc ├── src ├── _data │ ├── layout.yaml │ ├── redirects.yaml │ ├── github.yaml │ ├── feed.yaml │ ├── refs.yaml │ └── status.yaml ├── rwd │ ├── rwd.11tydata.yaml │ ├── grids │ │ ├── grids.11tydata.yaml │ │ └── index.md │ ├── interpolation │ │ ├── interpolation.11tydata.yaml │ │ └── index.md │ ├── query │ │ ├── query.11tydata.yaml │ │ ├── index.md │ │ ├── resources.md │ │ ├── contain.md │ │ ├── syntax.md │ │ ├── switch.md │ │ ├── switch-query.md │ │ └── containers.md │ ├── style │ │ ├── style.11tydata.yaml │ │ ├── index.md │ │ └── style-cases.md │ └── index.md ├── sass │ ├── sass.11tydata.yaml │ ├── color-spaces │ │ ├── color-spaces.11tydata.yaml │ │ ├── index.md │ │ ├── proposal.11tydata.yaml │ │ └── resources.md │ └── index.md ├── logical │ ├── logical.11tydata.yaml │ ├── index.md │ ├── research.md │ └── properties.md ├── overflow │ ├── overflow.11tydata.yaml │ └── index.md ├── elsewhere │ ├── elsewhere.11tydata.yaml │ ├── index.md │ └── 21-brooklyn.md ├── favicon.ico ├── layers │ ├── layers.11tydata.yaml │ ├── link-supports.md │ ├── index.md │ ├── resources.md │ ├── link-layer.md │ └── placement.md ├── feed.njk ├── scope │ ├── scope.11tydata.yaml │ ├── resources.md │ ├── index.md │ ├── prior-art.md │ ├── parent-selector.md │ ├── syntax.md │ └── nesting.md ├── styles │ ├── patterns │ │ ├── _index.scss │ │ ├── _base.scss │ │ ├── _media.scss │ │ ├── _alert.scss │ │ ├── _buttons.scss │ │ ├── _links.scss │ │ ├── _colors.scss │ │ ├── _layout.scss │ │ └── _type.scss │ └── style.scss ├── sasslike │ ├── sasslike.11tydata.yaml │ └── index.md ├── toggles │ ├── index.md │ └── toggles.11tydata.yaml ├── redirects.md ├── _layouts │ ├── content.njk │ ├── base.njk │ └── feed.njk ├── _includes │ ├── base │ │ ├── footer.njk │ │ ├── changes.njk │ │ ├── nav.njk │ │ ├── alerts.njk │ │ ├── links.njk │ │ ├── support.njk │ │ └── list.macros.njk │ ├── alert.njk │ ├── utility.njk │ └── embed.njk ├── 404.md ├── changelog │ ├── detail.njk │ └── index.njk ├── index.md ├── favicon.svg └── resources.md ├── .gitignore ├── README.md ├── filters ├── time.js ├── get.js └── type.js ├── package.json └── .eleventy.js /.nvmrc: -------------------------------------------------------------------------------- 1 | 16.13 2 | -------------------------------------------------------------------------------- /src/_data/layout.yaml: -------------------------------------------------------------------------------- 1 | content.njk 2 | -------------------------------------------------------------------------------- /src/rwd/rwd.11tydata.yaml: -------------------------------------------------------------------------------- 1 | parent: rwd 2 | tags: [rwd] 3 | -------------------------------------------------------------------------------- /src/sass/sass.11tydata.yaml: -------------------------------------------------------------------------------- 1 | parent: sass 2 | tags: [sass] 3 | -------------------------------------------------------------------------------- /src/logical/logical.11tydata.yaml: -------------------------------------------------------------------------------- 1 | parent: logical 2 | tags: [logical] 3 | -------------------------------------------------------------------------------- /src/overflow/overflow.11tydata.yaml: -------------------------------------------------------------------------------- 1 | parent: overflow 2 | tags: [overflow] 3 | -------------------------------------------------------------------------------- /src/rwd/grids/grids.11tydata.yaml: -------------------------------------------------------------------------------- 1 | parent: grids 2 | tags: 3 | - grids 4 | -------------------------------------------------------------------------------- /src/elsewhere/elsewhere.11tydata.yaml: -------------------------------------------------------------------------------- 1 | parent: elsewhere 2 | tags: [elsewhere] 3 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddbird/css-sandbox/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /src/layers/layers.11tydata.yaml: -------------------------------------------------------------------------------- 1 | archive: shipped 2 | parent: layers 3 | tags: 4 | - layers 5 | -------------------------------------------------------------------------------- /src/_data/redirects.yaml: -------------------------------------------------------------------------------- 1 | - from: /layers/guide/ 2 | to: https://css-tricks.com/css-cascade-layers/ 3 | -------------------------------------------------------------------------------- /src/rwd/interpolation/interpolation.11tydata.yaml: -------------------------------------------------------------------------------- 1 | parent: interpolation 2 | tags: 3 | - interpolation 4 | -------------------------------------------------------------------------------- /src/feed.njk: -------------------------------------------------------------------------------- 1 | --- 2 | layout: feed.njk 3 | permalink: feed.xml 4 | eleventyExcludeFromCollections: true 5 | --- 6 | -------------------------------------------------------------------------------- /src/rwd/query/query.11tydata.yaml: -------------------------------------------------------------------------------- 1 | archive: shipped 2 | parent: container-queries 3 | tags: 4 | - container-queries 5 | -------------------------------------------------------------------------------- /src/scope/scope.11tydata.yaml: -------------------------------------------------------------------------------- 1 | archive: moved 2 | moved: > 3 | [the latest specification](https://www.w3.org/TR/css-cascade-6/) 4 | parent: scope 5 | tags: 6 | - scope 7 | -------------------------------------------------------------------------------- /src/styles/patterns/_index.scss: -------------------------------------------------------------------------------- 1 | @use 'base'; 2 | @use 'colors'; 3 | @use 'links'; 4 | @use 'buttons'; 5 | @use 'type'; 6 | @use 'layout'; 7 | @use 'media'; 8 | @use 'alert'; 9 | -------------------------------------------------------------------------------- /src/styles/style.scss: -------------------------------------------------------------------------------- 1 | @use '../../node_modules/cssremedy/css/remedy.css'; 2 | @use '../../node_modules/prism-themes/themes/prism-a11y-dark.css'; 3 | 4 | @use 'patterns'; 5 | -------------------------------------------------------------------------------- /src/rwd/style/style.11tydata.yaml: -------------------------------------------------------------------------------- 1 | archive: moved 2 | moved: > 3 | [the published specification](https://www.w3.org/TR/css-contain-3/) 4 | parent: style-queries 5 | tags: 6 | - style-queries 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies installed by npm 2 | node_modules 3 | 4 | # build artefacts 5 | public 6 | css 7 | 8 | # secrets and errors 9 | .env 10 | .log 11 | 12 | # macOS related files 13 | .DS_Store 14 | 15 | -------------------------------------------------------------------------------- /src/sasslike/sasslike.11tydata.yaml: -------------------------------------------------------------------------------- 1 | archive: moved 2 | moved: > 3 | [the latest specification](https://www.w3.org/TR/css-mixins-1/) 4 | (currently only defines functions) 5 | parent: sasslike 6 | tags: [sasslike] 7 | -------------------------------------------------------------------------------- /src/sass/color-spaces/color-spaces.11tydata.yaml: -------------------------------------------------------------------------------- 1 | archive: moved 2 | moved: > 3 | [the Sass blog post](https://sass-lang.com/blog/wide-gamut-colors-in-sass/) 4 | parent: sass-color-spaces 5 | tags: 6 | - sass-color-spaces 7 | -------------------------------------------------------------------------------- /src/_data/github.yaml: -------------------------------------------------------------------------------- 1 | repo: https://github.com/oddbird/css-sandbox/ 2 | files: https://github.com/oddbird/css-sandbox/blob/main/ 3 | history: https://github.com/oddbird/css-sandbox/commits/main/ 4 | issues: https://github.com/oddbird/css-sandbox/issues 5 | -------------------------------------------------------------------------------- /src/_data/feed.yaml: -------------------------------------------------------------------------------- 1 | title: OddBird CSS Notebook 2 | subtitle: Notes towards the future of CSS, from Miriam Suzanne & OddBird 3 | url: https://css.oddbird.net/ 4 | feedUrl: https://css.oddbird.net/feed.xml 5 | author: 6 | name: OddBird 7 | email: birds@oddbird.net 8 | -------------------------------------------------------------------------------- /src/toggles/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Declarative Toggles 3 | created: 2021-05-28 4 | index: toggles 5 | --- 6 | 7 | There are many use-cases 8 | that require "toggling" the state of one element 9 | by interacting with a different element. 10 | Many of these could be described 11 | in terms of _show/hide_ states specifically. 12 | -------------------------------------------------------------------------------- /src/redirects.md: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyExcludeFromCollections: true 3 | title: Redirecting 4 | pagination: 5 | data: redirects 6 | size: 1 7 | alias: redirect 8 | permalink: '{{ redirect.from }}' 9 | --- 10 | 11 | Redirecting you to 12 | [{{ redirect.to }}]({{ redirect.to }}). 13 | If you are not redirected shortly, follow the link. 14 | -------------------------------------------------------------------------------- /src/_layouts/content.njk: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base.njk 3 | --- 4 | 5 | {% include "base/alerts.njk" %} 6 | 7 | {{ content | safe }} 8 | 9 | {% include "base/links.njk" %} 10 | 11 | {% set related = collections[index] | noSelf(page) if index else [] %} 12 | {% if related | length > 0 %} 13 | {% import "base/list.macros.njk" as list %} 14 | 15 |

Related Notes

16 | {{ list.all(related, collections) }} 17 | {% endif %} 18 | -------------------------------------------------------------------------------- /src/_includes/base/footer.njk: -------------------------------------------------------------------------------- 1 | 2 | {% md %} 3 | Maintained by [OddBird](https://oddbird.net/) ([change log](/changelog/)) 4 | 5 | Subscribe to the 6 | [newsletter](https://www.oddbird.net/oddnews/) or 7 | [RSS feed](/feed.xml) 8 | for updates. 9 | 10 | [Edit this page]({{ [github.files, page.inputPath] | join }}), 11 | [view page history]({{ [github.history, page.inputPath] | join }}), 12 | or 13 | [file an issue]({{ github.issues }}) 14 | on GitHub. 15 | {% endmd %} 16 | -------------------------------------------------------------------------------- /src/rwd/style/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Style Queries 3 | created: 2022-10-25 4 | index: style-queries 5 | links: 6 | spec: css-contain-3 7 | project: 18 8 | caniuse: css-container-queries-style 9 | tag: 787 10 | wpt: css-contain/container-queries?q=style 11 | --- 12 | 13 | Style queries are a subset of 'container queries', 14 | but rather than querying conditions of the _container size_, 15 | we can query the _computed value_ 16 | of any CSS properties on the container. 17 | -------------------------------------------------------------------------------- /src/_includes/base/changes.njk: -------------------------------------------------------------------------------- 1 | {% if changes and not (is_log) %} 2 | 15 | {% endif %} 16 | -------------------------------------------------------------------------------- /src/styles/patterns/_base.scss: -------------------------------------------------------------------------------- 1 | html { 2 | --system-fonts: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; 3 | --body-fonts: Palatino,Palatino Linotype,Palatino LT STD,Book Antiqua,Georgia,serif; 4 | --code-fonts: monaco,Consolas,'Lucida Console',monospace; 5 | 6 | background-color: #f9f9f9; 7 | font-family: var(--body-fonts); 8 | font-size: 1.15em; 9 | font-size: calc(1em + 0.4vw); 10 | height: 100%; 11 | line-height: 1.4; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/_includes/alert.njk: -------------------------------------------------------------------------------- 1 | 2 | {% macro note(description, label='Note', close=false) %} 3 |
4 | {{ label }}: 5 |
{{ description | md | safe }}
6 |
7 | {% endmacro %} 8 | 9 | {% macro warn(description, label='Warning', close=false) %} 10 |
11 | {{ label }}: 12 |
{{ description | md | safe }}
13 |
14 | {% endmacro %} 15 | -------------------------------------------------------------------------------- /src/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Page Not Found (404) 3 | permalink: /404.html 4 | eleventyExcludeFromCollections: true 5 | --- 6 | 7 | **Sorry**! 8 | It seems like we sent you 9 | to the wrong page. 10 | Since this is a sandbox, 11 | things move around sometimes. 12 | Try the [home page](/), 13 | or one of these options? 14 | 15 | {% import "base/list.macros.njk" as list %} 16 | 17 | ## Explainers 18 | 19 | {{ list.all(collections.explainer, collections) }} 20 | 21 | ## More Topics 22 | 23 | {{ list.all(collections.index, collections) }} 24 | -------------------------------------------------------------------------------- /src/changelog/detail.njk: -------------------------------------------------------------------------------- 1 | --- 2 | pagination: 3 | data: collections.changes 4 | size: 1 5 | alias: change 6 | permalink: '{{ change.url }}' 7 | eleventyComputed: 8 | title: 'Changes to _{{ change.post.data.title or "Needs Title" }}_ on {{ change.date | date("short") }}' 9 | eleventyExcludeFromCollections: true 10 | --- 11 | 12 |
13 | {{ change.log | md | safe }} 14 |
15 | 16 |

17 | 18 | {{ change.post.data.title or "Needs Title" }} » 19 | 20 |

21 | -------------------------------------------------------------------------------- /src/_includes/base/nav.njk: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | 15 | 16 |
17 | -------------------------------------------------------------------------------- /src/_includes/base/alerts.njk: -------------------------------------------------------------------------------- 1 | {% import "alert.njk" as alert %} 2 | 3 | {% if draft %} 4 | {{ alert.warn( 5 | 'This document is still under active development, and likely incomplete', 6 | 'Rough Draft' 7 | ) }} 8 | {% elif archive %} 9 | {% set details %} 10 | {{ status.archive[archive] or archive }} 11 | {% if moved %}See {{ moved }} for details.{% endif %} 12 | {% endset %} 13 | 14 | {{ alert.warn( 15 | details, 16 | 'Archived' 17 | ) }} 18 | {% endif %} 19 | 20 | {{ alert.note(note) if note else none }} 21 | {{ alert.warn(warn) if warn else none }} 22 | -------------------------------------------------------------------------------- /src/elsewhere/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: External Ideas & Proposals 3 | created: 2021-10-05 4 | index: elsewhere 5 | --- 6 | 7 | Some old notes & proposals 8 | ([written in collaboration with Fantasai](/elsewhere/21-brooklyn/)) 9 | are documented on the [CSSWG Wiki](https://wiki.csswg.org/ideas): 10 | 11 | - [Margin Collapse Controls](https://wiki.csswg.org/ideas/margin-collapsing) 12 | - [Timelines and Interpolation](https://wiki.csswg.org/ideas/timelines) 13 | - [Column and Row Gaps and Rules](https://wiki.csswg.org/ideas/gutter-styling) 14 | - [Logical (Flow-relative) Syntax](https://wiki.csswg.org/ideas/logical-syntax) 15 | -------------------------------------------------------------------------------- /src/rwd/query/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Container Queries 3 | created: 2020-11-14 4 | index: container-queries 5 | links: 6 | spec: css-contain-3 7 | project: 18 8 | mdn: CSS_Container_Queries 9 | caniuse: css-container-queries 10 | tag: 592 11 | wpt: css-contain/container-queries 12 | --- 13 | 14 | While media queries provide a method 15 | to query aspects of the user agent or device environment 16 | that a document is being displayed in 17 | (such as viewport dimensions or user preferences), 18 | container queries allow testing aspects 19 | of elements within the document 20 | (such as box dimensions or computed styles). 21 | -------------------------------------------------------------------------------- /src/sasslike/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | created: 2023-06-22 3 | title: Sass Features in CSS 4 | --- 5 | 6 | Over the last decade, 7 | several features have made the move 8 | from Sass (and other pre-processors) to CSS -- 9 | most notably 'variables' 10 | (as custom properties), 11 | and now 'nesting'. 12 | 13 | Here we consider 14 | some of the other Sass structures, 15 | and what advantages we would see 16 | from moving them into CSS. 17 | 18 | As a useful reference-point, 19 | the HTTP Archive 20 | has done some 21 | [basic tracking of Sass usage](https://github.com/w3c/csswg-drafts/issues/5798) 22 | across sites that provide 23 | public Sass sourcemaps. 24 | -------------------------------------------------------------------------------- /src/overflow/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | created: 2023-04-17 3 | title: CSS Overflow Extensions 4 | index: overflow 5 | --- 6 | 7 | Managing content 'overflow' effectively on the web 8 | requires a careful balance 9 | of semantics, presentation, 10 | and interactions. 11 | While existing scroll/snapping 12 | and disclosure widgets 13 | provide a partial solution, 14 | authors often have to cobble together 15 | tabs, carousels, and accordions 16 | from an incomplete set of tools. 17 | 18 | Rather than developing a proposal 19 | to handle one of these patterns, 20 | I'm interested in what tools are needed 21 | to make the existing patterns easier to build 22 | effectively and accessibly. 23 | -------------------------------------------------------------------------------- /src/changelog/index.njk: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyExcludeFromCollections: true 3 | title: Full Site Changelog 4 | created: 2021-10-20 5 | is_log: true 6 | --- 7 | 8 |
9 | {% for date, changes in collections.changes | groupby('date_group') %} 10 |

11 | 12 | {% for change in changes %} 13 |
14 |

15 | {{ change.post.data.title or "Needs Title" }}: 16 |

17 | 18 |
19 | {{ change.log | md | safe }} 20 |
21 | 22 | 23 |
24 | {% endfor %} 25 | {% endfor %} 26 |
27 | -------------------------------------------------------------------------------- /src/styles/patterns/_media.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:math'; 2 | 3 | figure { 4 | margin: 1.5em 0; 5 | } 6 | 7 | img { 8 | width: 100%; 9 | } 10 | 11 | [style*="--ratio"], 12 | [data-ratio] { 13 | > :first-child { 14 | width: 100%; 15 | } 16 | 17 | > img { 18 | height: auto; 19 | } 20 | 21 | @supports (--custom:property) { 22 | display: grid; 23 | grid-template: 'media' auto / 100%; 24 | 25 | &::before { 26 | content: ""; 27 | display: block; 28 | grid-area: media; 29 | padding-bottom: calc(100% / var(--ratio)); 30 | } 31 | 32 | > :first-child { 33 | grid-area: media; 34 | height: 100%; 35 | } 36 | } 37 | } 38 | 39 | [data-ratio] { 40 | --ratio: #{(math.div(16, 9))}; 41 | } 42 | -------------------------------------------------------------------------------- /src/rwd/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Responsive Components 3 | created: 2020-11-09 4 | index: rwd 5 | --- 6 | 7 | Currently `@media` queries give us a way to adjust a design 8 | based on device features, user-preferences, and viewport size. 9 | But modern web development relies heavily on modular 10 | "blocks" and "components" 11 | that can be moved around. 12 | 13 | Authors want a way to style these components 14 | based on more immediate context -- 15 | like the width of a parent container -- 16 | which might not match cleanly to viewport media. 17 | 18 | Grid and flexbox both provide some tools 19 | for managing available space, 20 | so in addition to "container query" solutions, 21 | I also want to think about if/where they can also be improved 22 | for responsive design. 23 | -------------------------------------------------------------------------------- /src/_includes/base/links.njk: -------------------------------------------------------------------------------- 1 | {% if links %} 2 |

Important Links

3 | 28 | {% endif %} 29 | -------------------------------------------------------------------------------- /src/_data/refs.yaml: -------------------------------------------------------------------------------- 1 | draft: 2 | name: Editor's Draft 3 | url: https://drafts.csswg.org/%s/ 4 | spec: 5 | name: Published Specification 6 | url: https://www.w3.org/TR/%s/ 7 | mdn: 8 | name: MDN Documentation 9 | url: https://developer.mozilla.org/en-US/docs/Web/CSS/%s 10 | caniuse: 11 | name: CanIUse 12 | url: https://caniuse.com/%s 13 | issue: 14 | name: Github Issue 15 | url: https://github.com/w3c/csswg-drafts/issues/%s 16 | label: 17 | name: Github Issues 18 | url: https://github.com/w3c/csswg-drafts/labels/%s 19 | project: 20 | name: Github Project 21 | url: https://github.com/w3c/csswg-drafts/projects/%s 22 | tag: 23 | name: TAG Review 24 | url: https://github.com/w3ctag/design-reviews/issues/%s 25 | wpt: 26 | name: Web Platform Tests 27 | url: https://wpt.fyi/results/css/%s 28 | -------------------------------------------------------------------------------- /src/styles/patterns/_alert.scss: -------------------------------------------------------------------------------- 1 | [data-alert] { 2 | --alert: var(--neutral); 3 | --alert-contrast: var(--bg); 4 | background: var(--callout); 5 | border: medium solid var(--alert); 6 | color: var(--text); 7 | display: grid; 8 | grid: 'title' auto 'content' auto / auto; 9 | font-family: var(--system-fonts); 10 | margin: 1em 0; 11 | } 12 | 13 | [data-alert] summary { 14 | background-color: var(--alert); 15 | color: var(--alert-contrast, inherit); 16 | font-size: max(16px, 0.5em); 17 | font-weight: bold; 18 | grid-area: title; 19 | padding: 0.25em 0.5em; 20 | } 21 | 22 | [data-alert] > div { 23 | font-size: max(16px, 0.8em); 24 | grid-area: content; 25 | padding: 0 0.5em; 26 | } 27 | 28 | [data-alert='warn'] { 29 | --alert: var(--mark); 30 | --alert-contrast: var(--text); 31 | } 32 | -------------------------------------------------------------------------------- /src/scope/resources.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Scope Resources 3 | created: 2021-10-05 4 | tags: 5 | - resources 6 | --- 7 | 8 | ## Talks & Podcasts 9 | 10 | - [CSSWG Proposals](https://slides.oddbird.net/csswg/) 11 | - [Styling the Intrinsic Web](https://www.oddbird.net/talks/intrinsic-web/) 12 | ([slides](https://slides.oddbird.net/css-next/)) 13 | - [Front End Nerdery](https://www.oddbird.net/2021/08/15/fe-nerdery-10/) 14 | - [Container Queries & The Future of CSS](https://www.oddbird.net/talks/responsive-components/) 15 | ([slides](https://slides.oddbird.net/css-next/)) 16 | - [Syntax.fm](https://www.oddbird.net/2021/06/16/syntaxfm-362/) 17 | - [Word Wrap Show](https://www.oddbird.net/2021/05/17/word-wrap-11/) 18 | - [The F-Word](https://www.oddbird.net/2021/05/06/f-word-11/) 19 | - [Smashing Podcast](https://www.oddbird.net/2021/05/04/smashing-36/) 20 | -------------------------------------------------------------------------------- /src/toggles/toggles.11tydata.yaml: -------------------------------------------------------------------------------- 1 | archive: abandoned 2 | parent: toggles 3 | tags: 4 | - toggles 5 | warn: | 6 | I'm convinced this doesn't belong in CSS: 7 | 8 | - The style part of the problem -- 9 | responding to state -- 10 | is conditional CSS 11 | that can be handled with 12 | [container style queries](https://www.w3.org/TR/css-conditional-5/#style-container). 13 | - The issue of creating toggles 14 | should be addressed 15 | in other parts of the platform 16 | with features like 17 | [invoker commands](https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API). 18 | 19 | In retrospect, 20 | I'm afraid this exploration 21 | acted as a distraction 22 | from more viable solutions -- 23 | while requiring extra effort from accessibility experts 24 | to document all the issues with our approach. 25 | -------------------------------------------------------------------------------- /src/styles/patterns/_buttons.scss: -------------------------------------------------------------------------------- 1 | button { 2 | background: var(--bg); 3 | color: var(--text); 4 | cursor: pointer; 5 | border: 2px solid var(--neutral); 6 | border-radius: 0.25em; 7 | font: inherit; 8 | font-size: 0.75rem; 9 | font-style: italic; 10 | padding: 0.125em 0.5em; 11 | 12 | &:hover, 13 | &:focus { 14 | background: var(--action); 15 | border-color: var(--action); 16 | color: var(--bg); 17 | } 18 | 19 | &:active { 20 | background: var(--focus); 21 | border-color: var(--focus); 22 | } 23 | } 24 | 25 | [data-toggle] { 26 | display: flex; 27 | 28 | button { 29 | flex: auto; 30 | border-radius: 0; 31 | } 32 | 33 | button + button { 34 | margin-inline-start: -2px; 35 | } 36 | } 37 | 38 | [aria-pressed=true] { 39 | border-color: var(--action); 40 | position: relative; 41 | z-index: 2; 42 | } 43 | -------------------------------------------------------------------------------- /src/_includes/base/support.njk: -------------------------------------------------------------------------------- 1 | 25 | -------------------------------------------------------------------------------- /src/styles/patterns/_links.scss: -------------------------------------------------------------------------------- 1 | a { 2 | &:link, 3 | &:visited { 4 | color: var(--link, var(--action)); 5 | } 6 | 7 | &:hover, 8 | &:focus, 9 | &:active { 10 | color: var(--focus); 11 | } 12 | 13 | &[href*='://']::after { 14 | font-family: var(--system-fonts); 15 | content: ' ↗'; 16 | } 17 | } 18 | 19 | .header-anchor { 20 | &:link, 21 | &:visited { 22 | --link: var(--neutral); 23 | --scale: 0.75; 24 | --x: 0; 25 | display: inline-block; 26 | font-weight: normal; 27 | text-decoration: none; 28 | transition: transform 300ms ease-out; 29 | transform: scale(var(--scale)) translateX(var(--x)); 30 | 31 | @media (min-width: 48em) { 32 | --scale: 0.6; 33 | --x: -25%; 34 | position: absolute; 35 | right: 100%; 36 | } 37 | } 38 | 39 | &:hover, 40 | &:focus, 41 | &:active { 42 | --scale: 0.8; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/_includes/utility.njk: -------------------------------------------------------------------------------- 1 | {% macro attr_if( 2 | attr, 3 | value=none 4 | ) %} 5 | {%- if (value and (value | string | lower == 'true')) or (value == '') -%} 6 | {{ attr }} 7 | {%- elif value -%} 8 | {{ attr }}="{{ value }}" 9 | {%- endif -%} 10 | {% endmacro %} 11 | 12 | {% macro show_attrs( 13 | attrs 14 | ) %} 15 | {%- for attr, value in attrs %} {{ attr_if(attr, value) }}{%- endfor -%} 16 | {% endmacro %} 17 | 18 | {% macro link_if( 19 | content, 20 | url=none, 21 | class=none, 22 | attrs={} 23 | ) -%} 24 | {%- set content = content if (content != none) else caller() -%} 25 | {%- if url -%} 26 | {{ 27 | content | safe 28 | }} 29 | {%- else -%} 30 | {{ 31 | content | safe 32 | }} 33 | {%- endif -%} 34 | {%- endmacro %} 35 | -------------------------------------------------------------------------------- /src/sass/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Sass Core Features 3 | created: 2021-12-06 4 | index: sass 5 | --- 6 | 7 | In addition to our work on CSS specifications, 8 | we're also working on new feature proposals and specs 9 | for the [Sass](https://sass-lang.com/) preprocessor. 10 | 11 | The priorities right now are: 12 | 13 | - Tools for managing new color syntax and multiple color-spaces 14 | - Try/catch syntax, for error handling 15 | - First-class css function calls 16 | - Expanding internal utilities (lists & strings etc) 17 | - URL handling & package management 18 | 19 | From a broader perspective, 20 | we believe that Sass can be a foundational tool 21 | for the future of design systems tooling -- 22 | and there are many more features to consider along those lines. 23 | For example: importing & exporting JSON data, 24 | such as [design token files][]. 25 | 26 | [design token files]: https://github.com/design-tokens/community-group 27 | -------------------------------------------------------------------------------- /src/_data/status.yaml: -------------------------------------------------------------------------------- 1 | progress: 2 | draft: 3 | icon: 📝 4 | description: research stage, or unofficial draft proposal 5 | adopted: 6 | icon: 👍 7 | description: proceeding on a standards track 8 | specified: 9 | icon: 🚀 10 | description: implementation underway, beginning to ship 11 | implemented: 12 | icon: ✅ 13 | description: implemented, shipped, and complete 14 | abandoned: 15 | icon: ❌ 16 | description: rejected or abandoned 17 | archive: 18 | abandoned: > 19 | ❌ 20 | This feature has been abandoned. 21 | Our notes are likely out-of-date. 22 | shipped: > 23 | ✅ 24 | This feature has shipped in browsers. 25 | Our notes are likely out-of-date. 26 | moved: > 27 | 🚚 28 | This content 29 | is being maintained elsewhere. 30 | Our notes are likely out-of-date. 31 | inactive: > 32 | 🤷🏻‍♀️ 33 | Not much active in here at the moment… 34 | -------------------------------------------------------------------------------- /src/_includes/base/list.macros.njk: -------------------------------------------------------------------------------- 1 | {%- macro all(pages, collections) -%} 2 | {%- if pages | length > 0 -%} 3 | 28 | {%- endif -%} 29 | {%- endmacro -%} 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Miriam's CSS Sandbox 2 | 3 | This is a scratch site for 4 | [Miriam Suzanne](https://oddbird.net/authors/miriam/) 5 | to take notes & document ideas 6 | related to the 7 | [CSS Working Group](https://github.com/w3c/csswg-drafts/) 8 | and CSS Specifications. 9 | 10 | I like to work in the open, 11 | and make my notes available -- 12 | you are welcome to explore, 13 | and even [open issues or pull-requests][gh] -- 14 | but **this is my own personal notebook, 15 | and not a replacement for CSSWG issue threads**. 16 | 17 | ## Development Scripts 18 | 19 | This static site is built using 20 | [Eleventy](https://11ty.dev/), 21 | based on a [skeleton template](https://11ty.rocks/) 22 | developed by [@5t3ph](https://twitter.com/5t3ph). 23 | 24 | **`npm install`** 25 | 26 | > Install everything needed to build/start the static site 27 | 28 | **`npm start`** 29 | 30 | > Run 11ty with hot reload at localhost:8080, including reload based on Sass changes 31 | 32 | **`npm run build`** 33 | 34 | > Production build includes minified, autoprefixed CSS 35 | -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: OddBird CSS Sandbox 3 | created: 2020-11-09 4 | --- 5 | 6 | This is a sandbox for 7 | [Miriam Suzanne](https://oddbird.net/authors/miriam/) 8 | and [OddBird](https://oddbird.net/) 9 | to document our notes 10 | related to 11 | [CSS Working Group](https://github.com/w3c/csswg-drafts/), 12 | [Sass language](https://sass-lang.com/), 13 | and related web platform features. 14 | Everything here is un-official and incomplete, 15 | as we do our thinking in public. 16 | 17 | [gh]: https://github.com/oddbird/css-sandbox 18 | [drafts]: https://github.com/w3c/csswg-drafts/issues 19 | 20 | [Links & Resources »](/resources/) 21 | 22 | {% import "base/list.macros.njk" as list %} 23 | 24 | ## Proposals & Explainers 25 | 26 | {{ list.all(collections.explainer, collections) }} 27 | 28 | {% note 'progress emoji' %} 29 | {% for name, stage in status.progress -%} 30 | - {{ stage.icon }} ({{ name }}): {{ stage.description }} 31 | {% endfor %} 32 | {% endnote %} 33 | 34 | ## Research Topics 35 | 36 | {{ list.all(collections.index, collections) }} 37 | -------------------------------------------------------------------------------- /src/_includes/embed.njk: -------------------------------------------------------------------------------- 1 | {% import "utility.njk" as utility %} 2 | 3 | {% macro codepen( 4 | id, 5 | title, 6 | edit=true, 7 | user='miriamsuzanne', 8 | tab='result', 9 | height=500, 10 | theme='39098', 11 | preview=none, 12 | attrs=none 13 | ) %} 14 | {%- set base_attrs = { 15 | 'class': 'codepen', 16 | 'data-editable': edit, 17 | 'data-height': height, 18 | 'data-theme-id': theme, 19 | 'data-user': user, 20 | 'data-slug-hash': id, 21 | 'data-default-tab': tab, 22 | 'data-embed-version': "2", 23 | "data-preview": preview 24 | } -%} 25 | {%- set attrs = base_attrs | merge(attrs) if attrs else base_attrs -%} 26 |

See the Pen {{ utility.link_if( 27 | content=title, 28 | url=('http://codepen.io/' + user + '/pen/' + id) 29 | ) }} by {{ utility.link_if( 30 | content='@' + user, 31 | url='http://codepen.io/' + user 32 | ) }} on {{ utility.link_if( 33 | content='CodePen', 34 | url='http://codepen.io' 35 | ) }}.

36 | {% endmacro %} 37 | -------------------------------------------------------------------------------- /src/layers/link-supports.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Import Conditions in the HTML Link Tag 3 | progress: draft 4 | tags: 5 | - explainer 6 | draft: 2024-06-17 7 | archive: false 8 | --- 9 | 10 | ## Authors 11 | 12 | Miriam Suzanne 13 | 14 | ## Participate 15 | 16 | There are discussion threads 17 | on both the WHATWG and CSSWG 18 | github repos 19 | that relate to this proposal: 20 | 21 | - (WHATWG #7540) 22 | [Allow authors to apply new css features (like cascade layers) while linking stylesheets](https://github.com/whatwg/html/issues/7540) 23 | - (CSSWG #5853) 24 | [Provide an attribute for assigning a `` to a cascade layer](https://github.com/w3c/csswg-drafts/issues/5853) 25 | 26 | ## Introduction 27 | 28 | 29 | 30 | ## Goals 31 | 32 | 33 | ## Non-goals 34 | 35 | 36 | ## Proposed solution: the `conditions` attribute 37 | 38 | 39 | ## Key scenarios 40 | 41 | 42 | ## Detailed design discussion 43 | 44 | ### Similar attributes 45 | 46 | ### Support conditions 47 | 48 | ## Considered alternatives 49 | 50 | 51 | 52 | ## Stakeholder Feedback / Opposition 53 | 54 | 55 | 56 | ## References & acknowledgements 57 | 58 | Many thanks for valuable feedback and advice from: 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/layers/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Cascade Layers 3 | created: 2020-11-12 4 | index: layers 5 | links: 6 | spec: css-cascade-5 7 | project: 15 8 | mdn: '@layer' 9 | caniuse: css-cascade-layers 10 | tag: 597 11 | wpt: css-cascade/?q=layer 12 | changes: 13 | - time: 2021-09-16 14 | log: Article and tests for Cascade Layers 15 | - time: 2021-10-05T16:12:53-06:00 16 | log: Update Chrome feature flag 17 | --- 18 | 19 | While Cascade Origins help to balance styling concerns across stakeholders -- 20 | layering browser defaults, user preferences, and document styles -- 21 | it can be useful to have similar _layering of concerns_ within a single origin. 22 | Author styles often start with browser normalization or resets, 23 | then layer in default typography, 24 | broad patterns (sometimes from design systems or frameworks), 25 | and more specific component styles. 26 | 27 | Currently that layering has to be achieved with careful management of selector-specificity, 28 | or over-use of `!important` flags -- both resulting in unwanted side-effects. 29 | Cascade Layers would allow authors to define their own layering scheme 30 | and avoid specificity or source-order conflicts across concerns. 31 | -------------------------------------------------------------------------------- /filters/time.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { DateTime } = require('luxon'); 4 | 5 | const getDateObj = (date) => { 6 | if (!date) { 7 | return DateTime.now(); 8 | } 9 | 10 | return typeof date === 'string' 11 | ? DateTime.fromISO(date, { zone: 'UTC' }) 12 | : DateTime.fromJSDate(date, { zone: 'UTC' }); 13 | }; 14 | 15 | const date = (dateObj, format) => { 16 | const obj = getDateObj(dateObj); 17 | 18 | const formats = { 19 | short: DateTime.DATE_MED, 20 | long: DateTime.DATE_FULL, 21 | range: { month: 'long', year: 'numeric' }, 22 | month: { month: 'long' }, 23 | year: { year: 'numeric' }, 24 | day: { day: 'numeric' }, 25 | }; 26 | 27 | const knownFormat = formats[format] || DateTime[format]; 28 | 29 | if (format === 'rss') { 30 | return obj.toRFC2822(); 31 | } else if (format === 'iso') { 32 | return obj.toISO(); 33 | } else if (format && !knownFormat) { 34 | const custom = { 35 | url: "yyyy'/'MM'/'dd", 36 | 'no-month': "dd',' yyyy", 37 | }; 38 | return obj.toFormat(custom[format] || format); 39 | } 40 | 41 | return obj.toLocaleString(knownFormat || DateTime.DATE_MED); 42 | }; 43 | 44 | module.exports = { 45 | date, 46 | }; 47 | -------------------------------------------------------------------------------- /filters/get.js: -------------------------------------------------------------------------------- 1 | const getDate = (page) => page.data.changes 2 | ? page.data.changes.sort((a, b) => b.time - a.time).at(0).time 3 | : page.data.draft || page.data.created || page.date; 4 | 5 | const byDate = (collection) => collection 6 | .sort((a, b) => getDate(b) - getDate(a)); 7 | 8 | const latest = (collection) => { 9 | return getDate(byDate(collection).at(0)); 10 | }; 11 | 12 | const noSelf = (collection, self) => 13 | collection.filter((page) => page.url !== self.url); 14 | 15 | const getIndex = (collection, tag) => 16 | collection.find((page) => page.data.index === tag); 17 | 18 | const getPage = (collection, page) => 19 | collection.find((item) => item.url === page.url); 20 | 21 | module.exports = function (eleventyConfig) { 22 | eleventyConfig.addFilter('getDate', getDate); 23 | eleventyConfig.addFilter('byDate', byDate); 24 | eleventyConfig.addFilter('latest', latest); 25 | eleventyConfig.addFilter('noSelf', noSelf); 26 | eleventyConfig.addFilter('getIndex', getIndex); 27 | eleventyConfig.addFilter('getPage', getPage); 28 | 29 | eleventyConfig.addCollection("index", function(collectionApi) { 30 | const collect = collectionApi 31 | .getAll() 32 | .filter((page) => page.data.index); 33 | 34 | return byDate(collect); 35 | }); 36 | }; 37 | -------------------------------------------------------------------------------- /src/scope/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Scope & Encapsulation 3 | created: 2020-11-10 4 | changes: 5 | - time: 2025-03-25T12:59:52-06:00 6 | log: > 7 | Scope is part of 8 | Interop 2025 9 | - time: 2021-09-11 10 | log: Scope spec draft moved to Cascade-6 11 | index: scope 12 | links: 13 | spec: css-cascade-6 14 | project: 21 15 | caniuse: css-cascade-scope 16 | tag: 593 17 | wpt: css-cascade?q=scope 18 | --- 19 | 20 | {% note 'progress' %} 21 | Scope is shipping 22 | as part of [Interop 2025](https://wpt.fyi/interop-2025). 23 | {% endnote %} 24 | 25 | Authors often complain that CSS is "globally scoped" -- 26 | so that every selector is compared against every DOM element. 27 | 28 | There are several overlapping concerns here, 29 | based on a wide range of use-cases -- 30 | and they can quickly become confused. 31 | That has lead to a wide array of proposals 32 | that are sometimes working towards different goals. 33 | 34 | Both shadow-DOM 35 | and the abandoned "scope" specification 36 | were focused around strong isolation. 37 | Shadow-DOM in particular creates persistent DOM-defined boundaries, 38 | that impact all style rules. 39 | 40 | Meanwhile, 41 | most of the user-land "scope" tools for CSS 42 | have a much lighter touch. 43 | I've been mainly interested in those low-isolation, 44 | namespacing problems. 45 | -------------------------------------------------------------------------------- /src/sass/color-spaces/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Sass Color Spaces 3 | created: 2021-12-06 4 | changes: 5 | - time: 2022-01-11T14:57:36-07:00 6 | log: More detail, with rough Sass suggestions 7 | - time: 2022-01-24T16:01:45-07:00 8 | log: Document css-color-4 functions and browser support 9 | index: sass-color-spaces 10 | parent: sass 11 | --- 12 | 13 | Historically 14 | CSS has been limited to a single color model (RGB) 15 | and gamut (`sRGB`). 16 | Authors have various formats to describe colors in that gamut -- 17 | using cubic hex notation `#rgb`/`#rrggbb`/`#rrggbbaa` 18 | and functions `rgb()`/`rgba()`, 19 | or cylindrical/polar-angle functions `hsl()`/`hwb()`. 20 | 21 | Unfortunately, `sRGB` is a relatively narrow _color gamut_, 22 | and RGB isn't a _perceptually uniform_ model. 23 | Many monitors now support wider color gamuts 24 | (such as the popular `display-p3`), 25 | and there has also been significant progress 26 | in developing more perceptually uniform color spaces 27 | such as CIE `LAB`/`okLAB`. 28 | 29 | The CSS Colors level 4 specification 30 | describes how CSS authors can access these newer gamuts & formats -- 31 | with `okLAB` as the default space for color-mixing. 32 | We want to provide support for this in Sass: 33 | with server-side tools to manage colors across spaces, 34 | and convert colors between spaces where appropriate. 35 | -------------------------------------------------------------------------------- /src/layers/resources.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cascade Layer Resources 3 | created: 2022-01-25T11:58:34-07:00 4 | tags: 5 | - resources 6 | --- 7 | 8 | - [OddBird Resources](https://www.oddbird.net/tags/cascade-layers/) 9 | - [A Complete Guide to Cascade Layers](https://css-tricks.com/css-cascade-layers/) 10 | - [Layers CodePen collection](https://codepen.io/collection/BNjmma) 11 | 12 | ## Talks & Podcasts 13 | 14 | - [CSSWG Proposals](https://slides.oddbird.net/csswg/) 15 | - [Styling the Intrinsic Web](https://www.oddbird.net/talks/intrinsic-web/) 16 | ([slides](https://slides.oddbird.net/css-next/)) 17 | - [Front End Nerdery](https://www.oddbird.net/2021/08/15/fe-nerdery-10/) 18 | - [Container Queries & The Future of CSS](https://www.oddbird.net/talks/responsive-components/) 19 | ([slides](https://slides.oddbird.net/css-next/)) 20 | - [Syntax.fm](https://www.oddbird.net/2021/06/16/syntaxfm-362/) 21 | - [Word Wrap Show](https://www.oddbird.net/2021/05/17/word-wrap-11/) 22 | - [The F-Word](https://www.oddbird.net/2021/05/06/f-word-11/) 23 | - [Smashing Podcast](https://www.oddbird.net/2021/05/04/smashing-36/) 24 | 25 | ## Articles & Demos 26 | 27 | - [The Future of CSS: Cascade Layers (CSS @layer)](https://www.bram.us/2021/09/15/the-future-of-css-cascade-layers-css-at-layer/) 28 | by **Bramus Van Damme** 29 | - [Getting Started With CSS Cascade Layers](https://www.smashingmagazine.com/2022/01/introduction-css-cascade-layers/) 30 | by **Stephanie Eckles** 31 | -------------------------------------------------------------------------------- /src/styles/patterns/_colors.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:color'; 2 | 3 | @mixin light-mode { 4 | --bg: var(--contrast-light); 5 | --callout: var(--contrast-light-ish); 6 | --text: var(--contrast-dark); 7 | --neutral: var(--neutral-dark); 8 | --action: var(--prime-dark); 9 | --focus: var(--accent-dark); 10 | --mark: var(--accent-light); 11 | } 12 | 13 | @mixin dark-mode { 14 | --bg: var(--contrast-dark); 15 | --callout: var(--contrast-dark-ish); 16 | --text: var(--contrast-light); 17 | --neutral: var(--neutral-light); 18 | --action: var(--prime-light); 19 | --focus: var(--accent-light); 20 | --mark: var(--accent-dark); 21 | } 22 | 23 | html { 24 | color-scheme: var(--mode, var(--os-mode, light)); 25 | 26 | // palette 27 | --contrast-light: snow; 28 | --contrast-light-ish: mistyrose; 29 | --contrast-dark: #{color.mix(darkslategray, black, 25%)}; 30 | --contrast-dark-ish: #{color.mix(darkslategray, black, 50%)}; 31 | --neutral-light: lightslategray; 32 | --neutral-dark: slategray; 33 | --prime-light: powderblue; 34 | --prime-dark: teal; 35 | --accent-light: hotpink; 36 | --accent-dark: #{color.mix(mediumvioletred, black, 75%)}; 37 | 38 | @include light-mode; 39 | 40 | @media (prefers-color-scheme: dark) { 41 | @include dark-mode; 42 | --os-mode: dark; 43 | } 44 | 45 | background: var(--bg); 46 | color: var(--text); 47 | } 48 | 49 | [data-mode='light'] { 50 | @include light-mode; 51 | --mode: light; 52 | } 53 | 54 | [data-mode='dark'] { 55 | @include dark-mode; 56 | --mode: dark; 57 | } 58 | -------------------------------------------------------------------------------- /filters/type.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const typogr = require('typogr'); 4 | const ghSlug = require('github-slugger').slug; 5 | 6 | const mdown = require('markdown-it')({ 7 | html: true, 8 | breaks: false, 9 | linkify: true, 10 | typographer: true, 11 | }) 12 | .disable('code') 13 | .use(require('markdown-it-mark')) 14 | .use(require('markdown-it-footnote')) 15 | .use(require('markdown-it-anchor'), { 16 | slugify: ghSlug, 17 | permalink: true, 18 | }); 19 | 20 | const amp = (s) => { 21 | const r = '&'; 22 | return s ? s.replace(/&/g, '&').replace(/&/g, r) : s; 23 | }; 24 | 25 | const set = (content) => (content ? typogr.typogrify(content) : content); 26 | const render = (content, type = true) => 27 | type ? set(mdown.render(content)) : mdown.render(content); 28 | const inline = (content, type = true) => 29 | type ? set(mdown.renderInline(content)) : mdown.renderInline(content); 30 | 31 | const note = (content, label, close) => { 32 | return `
33 | ${label || 'Note'}: 34 |
${render(content.trim())}
35 |
`; 36 | } 37 | 38 | const warn = (content, label, close) => { 39 | return `
40 | ${label || 'Warning'}: 41 |
${render(content.trim())}
42 |
`; 43 | } 44 | 45 | module.exports = { 46 | mdown, 47 | amp, 48 | set, 49 | render, 50 | inline, 51 | warn, 52 | note, 53 | }; 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oddbird-css", 3 | "version": "1.1.0", 4 | "description": "A public scratch-pad for OddBird to work on CSS & Sass", 5 | "main": "index.html", 6 | "scripts": { 7 | "watch:sass": "sass --no-source-map --watch src/styles:public/css", 8 | "watch:eleventy": "eleventy --serve", 9 | "build:sass": "sass --no-source-map src/styles:public/css", 10 | "build:eleventy": "eleventy", 11 | "postbuild": "postcss public/css/*.css -u autoprefixer cssnano -r", 12 | "start": "npm-run-all build:sass --parallel watch:*", 13 | "build": "npm-run-all build:sass build:eleventy" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/oddbird/css-sandbox" 18 | }, 19 | "author": "OddBird", 20 | "license": "ISC", 21 | "dependencies": { 22 | "autoprefixer": "^10.4.2", 23 | "cross-env": "^7.0.2", 24 | "cssnano": "^5.0.12", 25 | "cssremedy": "0.1.0-beta.2", 26 | "eleventy-plugin-toc": "^1.1.0", 27 | "github-slugger": "^1.3.0", 28 | "js-yaml": "^3.14.0", 29 | "markdown-it": "^12.0.2", 30 | "markdown-it-anchor": "^6.0.0", 31 | "markdown-it-footnote": "^3.0.2", 32 | "markdown-it-mark": "^3.0.0", 33 | "npm-run-all": "^4.1.5", 34 | "postcss-cli": "^8.1.0", 35 | "prism-themes": "^1.5.0" 36 | }, 37 | "browserslist": [ 38 | "last 2 versions" 39 | ], 40 | "devDependencies": { 41 | "@11ty/eleventy": "^2.0.0-beta.2", 42 | "@11ty/eleventy-navigation": "^0.3.2", 43 | "@11ty/eleventy-plugin-rss": "^1.1.2", 44 | "@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0", 45 | "lodash": "^4.17.21", 46 | "luxon": "^3.2.1", 47 | "sass": "^1.50.1", 48 | "typogr": "^0.6.8" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/resources.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: W3C & Browser Resources 3 | created: 2022-03-04 4 | tags: 5 | - resources 6 | --- 7 | 8 | ## Github Repos 9 | 10 | - [CSS Working Group](https://github.com/w3c/csswg-drafts/) 11 | - [W3C TAG Review](https://github.com/w3ctag/design-reviews/) 12 | - [WHATWG HTML Spec](https://github.com/whatwg/html/) 13 | - [Open UI](https://github.com/openui/open-ui/) 14 | - [Sass Language](https://github.com/sass/sass/) 15 | 16 | ## Web Platform Tests 17 | 18 | - [wpt info](https://wpt.fyi/) 19 | (includes yearly interop) 20 | - [live tests](https://wpt.live/) 21 | 22 | ## Browser Issues / Status 23 | 24 | Gecko: 25 | - [Firefox core issues](https://bugzilla.mozilla.org/buglist.cgi?product=Core&bug_status=__open__&list_id=16012662) 26 | - [Firefox experimental features](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Experimental_features) 27 | - [Firefox release notes](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases) 28 | - [Firefox release calendar](https://wiki.mozilla.org/Release_Management/Calendar) 29 | - [Mozilla standards positions](https://mozilla.github.io/standards-positions/) 30 | 31 | WebKit: 32 | - [WebKit CSS issues](https://bugs.webkit.org/buglist.cgi?bug_status=__open__&component=CSS&list_id=7970035&product=WebKit) 33 | - [WebKit release notes](https://webkit.org/blog/) 34 | - [Safari release notes](https://developer.apple.com/documentation/safari-release-notes) 35 | - [Safari standards positions](https://webkit.org/standards-positions/) 36 | 37 | Chromium/Blink: 38 | - [Blink CSS issues](https://bugs.chromium.org/p/chromium/issues/list?q=component:Blink%3ECSS) 39 | - [Chromium release notes](https://blog.chromium.org/) 40 | - [Chrome platform status](https://chromestatus.com/features) 41 | - [Chrome release schedule](https://chromiumdash.appspot.com/schedule) 42 | - [Chrome release notes](https://developer.chrome.com/) 43 | - [Edge release notes](https://docs.microsoft.com/en-us/deployedge/microsoft-edge-relnote-stable-channel) 44 | -------------------------------------------------------------------------------- /src/styles/patterns/_layout.scss: -------------------------------------------------------------------------------- 1 | body { 2 | display: grid; 3 | grid-gap: 1em; 4 | grid-template: 5 | '. nav .' auto 6 | '. control .' auto 7 | '. header .' auto 8 | '. main .' 1fr 9 | / minmax(0, 1fr) minmax(0, 40em) minmax(0, 1fr) 10 | ; 11 | max-width: 100%; 12 | min-height: 100%; 13 | padding-block-start: 1em; 14 | 15 | @media (min-width: 50em) { 16 | --controls: end; 17 | grid-template: 18 | '. nav control' auto 19 | '. header .' auto 20 | '. main .' 1fr 21 | / minmax(auto, 1fr) minmax(0, 40em) minmax(auto, 1fr) 22 | ; 23 | } 24 | 25 | > * { grid-column: main; } 26 | } 27 | 28 | header, 29 | [id='toc-details'], 30 | footer { 31 | font-size: 0.8rem; 32 | } 33 | 34 | // header 35 | nav { 36 | grid-area: nav; 37 | } 38 | 39 | .controls { 40 | justify-self: var(--controls, start); 41 | grid-area: control; 42 | padding-right: 1em; 43 | } 44 | 45 | header { 46 | grid-area: header; 47 | 48 | [datetime] { 49 | display: block; 50 | font-style: italic; 51 | margin-top: 0.5rem; 52 | } 53 | } 54 | 55 | // toc 56 | #toc-details { 57 | margin-top: 0.5rem; 58 | } 59 | 60 | .toc-summary { 61 | font-style: italic; 62 | } 63 | 64 | // main 65 | main { 66 | grid-area: main; 67 | } 68 | 69 | // support 70 | #support { 71 | background-color: light-dark(white, black); 72 | border-block: thin solid var(--neutral); 73 | display: grid; 74 | grid-column: 1 / -1; 75 | grid-template-columns: inherit; 76 | padding-block: 2em; 77 | 78 | > h2 { 79 | border: unset; 80 | margin: unset; 81 | } 82 | 83 | > * { grid-column: 2; } 84 | + footer { border: unset; } 85 | } 86 | 87 | // footer 88 | footer { 89 | border-top: medium solid var(--neutral); 90 | padding: 1em; 91 | 92 | @media (min-width: 50em) { 93 | margin-inline: -1em; 94 | } 95 | 96 | p { 97 | margin-block: 0.25rem; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/styles/patterns/_type.scss: -------------------------------------------------------------------------------- 1 | :focus-visible { 2 | outline-offset: 0.25em; 3 | } 4 | 5 | time { 6 | font-style: italic; 7 | } 8 | 9 | // headings 10 | 11 | h1 { 12 | margin: 0.5em 0 0; 13 | } 14 | 15 | h1, h2, h3, h4, h5, h6 { 16 | font-family: var(--system-fonts); 17 | line-height: 1.2; 18 | position: relative; 19 | } 20 | 21 | h2 { 22 | border-top: medium dotted var(--neutral); 23 | margin: 2em 0 1em; 24 | padding-top: 0.25rem; 25 | } 26 | 27 | h3, h4 { 28 | margin: 1.5em 0 0.5em; 29 | } 30 | 31 | // lists 32 | :is(ol, ul) { 33 | &, 34 | & &, 35 | [data-alert] & { 36 | padding-left: 1.5em; 37 | } 38 | 39 | @media (min-width: 50em) { 40 | padding-left: 0; 41 | } 42 | } 43 | 44 | // quotes 45 | 46 | blockquote { 47 | border-inline-start: 0.5em solid var(--mark); 48 | font-style: italic; 49 | margin-inline: 0; 50 | padding-inline: 0.5em; 51 | 52 | @media (min-width: 50em) { 53 | margin-inline: -1.5em; 54 | padding-inline: 1em; 55 | } 56 | 57 | em, i { 58 | font-style: normal; 59 | } 60 | } 61 | 62 | // markers & code 63 | 64 | code, 65 | mark { 66 | background: var(--mark); 67 | color: var(--text); 68 | display: inline-block; 69 | padding: 0 0.25em; 70 | } 71 | 72 | code { 73 | background: var(--callout); 74 | font-family: var(--code-fonts); 75 | font-size: 0.8em; 76 | 77 | pre:not([class*="language-"]) & { 78 | display: block; 79 | padding: 1em; 80 | } 81 | } 82 | 83 | pre[class*="language-"] { 84 | @media (min-width: 50em) { 85 | margin-inline: -1em; 86 | } 87 | 88 | code { 89 | background: unset; 90 | color: unset; 91 | display: unset; 92 | padding: unset; 93 | } 94 | } 95 | 96 | // amp 97 | 98 | .amp { 99 | font-family: Garamond,Baskerville,Baskerville Old Face,Hoefler Text,Times New Roman,serif; 100 | font-style: italic; 101 | font-weight: normal; 102 | } 103 | 104 | // summary 105 | summary { 106 | cursor: pointer; 107 | } 108 | 109 | // tables 110 | table { 111 | border-collapse: collapse; 112 | display: block; 113 | max-width: 100%; 114 | width: max-content; 115 | overflow: auto; 116 | } 117 | 118 | td, th { 119 | border: thin solid var(--neutral); 120 | padding: 0 0.5em; 121 | text-align: left; 122 | } 123 | -------------------------------------------------------------------------------- /src/logical/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Logical Shorthands 3 | created: 2025-03-25 4 | index: logical 5 | --- 6 | 7 | The CSS Working Group recently resolved 8 | to add a `size` shorthand 9 | for setting both the `width` and `height` of an element. 10 | Many people asked about using it to set the ‘logical’ 11 | `inline-size` and `block-size` properties instead. 12 | But ‘logical shorthands’ have been 13 | stalled in the working group for years. 14 | _Can we get them unstuck?_ 15 | 16 | [You can support our efforts](https://opencollective.com/oddbird-open-source/contribute/css-logical-shorthands-86141) 17 | 18 | ## Next steps 19 | 20 | 1. Research what properties would be impacted 21 | 2. Choose syntax for individual properties 22 | 3. Develop lexical toggle to allow default-logical styles 23 | 24 | ## CSS Working Group discussion 25 | 26 | - Specification: [CSS Logical Properties](https://www.w3.org/TR/css-logical/) 27 | 28 | Fantasai opened the original issue in 2017, 29 | when publishing the [First Public Working Draft](https://www.w3.org/TR/2017/WD-css-logical-1-20170518/) 30 | of CSS Logical Properties: 31 | [[css-logical] Flow-relative syntax for margin-like shorthands](https://github.com/w3c/csswg-drafts/issues/1282#issue-223656679). 32 | Here are some key comments: 33 | 34 | - [2021 proposed solution](https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-952428897) 35 | by [Fantasai & Miriam & Jen Simmons](https://css.oddbird.net/elsewhere/21-brooklyn/) 36 | - [2022 TPAC discussion](https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-1249685175) 37 | with [Internationalization Working Group](https://www.w3.org/groups/wg/i18n-core/) (I18n) -- 38 | [Tab summarizes the decision to be made](https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-1249822796), 39 | but the next step is 40 | _making a list of impacted properties_ 41 | - [2023 update for I18n WG](https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-1719113776) -- 42 | _still waiting on the research_ 43 | - [2024 update for I18n WG](https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-2372647118) -- 44 | _still waiting on research_ 45 | 46 | ## Other resources 47 | 48 | - Jeremy Keith, 2022: [Let's get logical](https://adactio.com/journal/19457) 49 | - Miriam, 2022: [A long-term plan for logical shorthands?](https://www.miriamsuzanne.com/2022/09/16/tpac-logical/) 50 | - OddBird, 2025: [Support logical shorthands in CSS](https://www.oddbird.net/2025/03/20/logical-shorthand/) 51 | -------------------------------------------------------------------------------- /src/logical/research.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Logical shorthand notes & side quests 3 | created: 2025-03-26 4 | --- 5 | 6 | ## Why `inline-size` but `padding-inline`? 7 | 8 | This is a question from 9 | [@johanwestling on Mastodon](https://mastodon.social/@johanwestling/114220721222033597): 10 | 11 | > But why the opposite property naming order? 12 | > I mean `padding`, `padding-block`, `padding-inline` for example. 13 | 14 | I wasn't in the CSS Working Group 15 | when this decision was made, 16 | but here's what I've found so far. 17 | 18 | - December 2010 19 | Writing Modes spec defines terms 20 | `length` (logical `height`) 21 | and `measure` (logical `width`) 22 | https://www.w3.org/TR/2010/WD-css3-writing-modes-20101202/#dimensions 23 | - March 2014 24 | Writing-Modes spec uses 25 | `extent` (block) & `measure` (inline): 26 | https://www.w3.org/TR/2014/CR-css-writing-modes-3-20140320/#abstract-dimensions 27 | - March 2014 28 | CSSWG resolves to use 29 | `inline-(something)` and `block-(something)` instead: 30 | https://lists.w3.org/Archives/Public/www-style/2014Mar/0255.html 31 | - March 2014 The discussion is mostly about 32 | what `(something)` should be, 33 | and agreeing that a hyphen makes 34 | `block-size` more clear than `block size` 35 | (the 2D size of a block?): 36 | https://lists.w3.org/Archives/Public/www-style/2014Mar/0479.html 37 | - July 2014 first commit to Logical Properties spec 38 | includes `length` and `measure` as the property names: 39 | https://github.com/w3c/csswg-drafts/blob/156b081188738ea7ecd1aa6a168e4347d339b19f/css-logical-props/Overview.bs 40 | - October 2014 the properties are updated to 41 | `inline-size` and `block-size`: 42 | https://github.com/w3c/csswg-drafts/commit/0a24110043cb3f3033fb22661297046a54465eda 43 | - December 2015 44 | Writing Modes spec uses `inline-size` and `block-size`: https://www.w3.org/TR/2015/CR-css-writing-modes-3-20151215/#abstract-axes 45 | - May 2017 46 | First Public Working Draft of Logical Properties: 47 | https://www.w3.org/TR/2017/WD-css-logical-1-20170518/ 48 | 49 | [Github issues only go back to late 2015](https://github.com/w3c/csswg-drafts/issues?q=is%3Aissue%20&page=377), 50 | after the names seem to be settled, 51 | so I can't find any discussion there. 52 | 53 | Many of the people participating in those conversations 54 | are still involved with the CSSWG today, 55 | so I can ask around for more information -- 56 | but it seems to me that the likely answer is: 57 | 58 | - The logical `margin`, `padding`, and `border` properties 59 | were added as longhand versions of existing properties, 60 | with the well established `-` syntax. 61 | - At the time, `width` and `height` were not longhand properties 62 | with a shared shorthand base-property, 63 | and so the logical alternatives were not designed 64 | as longhand sub-properties. 65 | - `inline-size` and `block-size` already existed as conceptual terms, 66 | and they read better than the flipped `size-inline` and `size-block`. 67 | Without a shorthand property to base the names off, 68 | there's little reason to change them. 69 | - Now that we are adding a `size` shorthand, 70 | the pattern seems inconsistent -- 71 | but it wasn't even a consideration previously. 72 | -------------------------------------------------------------------------------- /src/sass/color-spaces/proposal.11tydata.yaml: -------------------------------------------------------------------------------- 1 | title: Sass Color Spaces Proposal 2 | created: 2022-03-11 3 | progress: implemented 4 | tags: [explainer] 5 | changes: 6 | - time: 2022-04-04T15:56:51-06:00 7 | log: Defining color terms, procedures, and functions 8 | - time: 2022-05-25T13:47:45-06:00 9 | log: | 10 | Define color parsing, missing/powerless components, 11 | and channel boundaries 12 | - time: 2022-06-01T13:35:32-06:00 13 | log: Define gamut-mapping, and allow spaces to represent gamuts 14 | - time: 2022-06-06T17:10:38-06:00 15 | log: | 16 | Improve parsing logic, and flesh out hwb() function 17 | based on [sample code](https://github.com/oddbird/sass-colors-sample) 18 | - time: 2022-06-28T17:34:49-06:00 19 | log: | 20 | Define hwb, (ok)lab, and (ok)lch functions, 21 | and update todo lists. 22 | - time: 2022-07-03T12:31:55-06:00 23 | log: Add support for color-spaces in color component parsing 24 | - time: 2022-07-08T18:13:39-06:00 25 | log: Parser support for color() syntax, and all new functions defined 26 | - time: 2022-08-09T17:10:33-06:00 27 | log: | 28 | - Finalize color interpolation logic, and `color.mix()` function 29 | - Note potential issues with missing (`none`) channels in conversion 30 | - Deprecate individual channel inspection functions in favor of 31 | `color.channel()` 32 | - Organize global and color-module function groups 33 | - Complete specification of global `hwb()` function, 34 | and deprecate `color.hwb()` functions 35 | - Specify updates to global `rgb()` functions 36 | - time: 2022-08-10T14:45:22-06:00 37 | log: | 38 | - Organize and document open issues 39 | - Define `hsl()`/`hsla()` functions 40 | - Remove any out-of-gamut channel clamping and adjustments 41 | - Ensure channels are returned as-specified when inspecting 42 | - time: 2022-08-19T17:59:57-06:00 43 | log: Define logic for `color.alpha()` and `color.change()`. 44 | - time: 2022-08-22T18:16:56-06:00 45 | log: | 46 | - Define color spaces and channels more clearly, 47 | and update to reflect latest spec. 48 | - Define 'channel normalization' in a reusable procedure, 49 | and include is as part of the color component parsing procedure. 50 | - Use channel normalization to simplify color function overloads. 51 | - Define logic for `color.adjust()` and `color.scale()`, treating 52 | the `none` keyword as a value of `0`. 53 | - time: 2022-08-24T17:44:03-06:00 54 | log: | 55 | This is a complete first draft of the color proposal, including all the 56 | proposed new & modified functions. However, there are still some 57 | questions to resolve in the editing & review process. 58 | 59 | - Draft logic for `color.complement()`, `color.invert()`, and 60 | `color.ie-hex-string()`. 61 | - Update logic for `color.mix()` and color interpolation to better 62 | match standards in CSS Colors 4 and 5. 63 | - time: 2022-09-05T16:58:31-06:00 64 | log: | 65 | Update this document to reflect 66 | the latest changes in the 67 | [Sass Pull Request](https://github.com/sass/sass/pull/2832), 68 | and add a deprecation notice. 69 | All future updates will be made 70 | in the Sass repository. 71 | -------------------------------------------------------------------------------- /.eleventy.js: -------------------------------------------------------------------------------- 1 | const nav = require('@11ty/eleventy-navigation'); 2 | const hljs = require('@11ty/eleventy-plugin-syntaxhighlight'); 3 | const pluginRss = require("@11ty/eleventy-plugin-rss"); 4 | const toc = require('eleventy-plugin-toc'); 5 | const yaml = require('js-yaml'); 6 | const ghSlug = require('github-slugger').slug; 7 | 8 | const time = require('./filters/time'); 9 | const type = require('./filters/type'); 10 | const get = require('./filters/get'); 11 | 12 | module.exports = function (eleventyConfig) { 13 | eleventyConfig.addPlugin(hljs); 14 | eleventyConfig.addPlugin(nav); 15 | eleventyConfig.addPlugin(toc); 16 | eleventyConfig.addPlugin(pluginRss); 17 | 18 | eleventyConfig.addPlugin(get); 19 | 20 | eleventyConfig.addWatchTarget('./src/styles/'); 21 | eleventyConfig.addPassthroughCopy('./src/css'); 22 | eleventyConfig.addPassthroughCopy("./src/**/*.svg"); 23 | 24 | // filters 25 | eleventyConfig.addFilter('amp', type.amp); 26 | eleventyConfig.addFilter('typogr', type.set); 27 | eleventyConfig.addFilter('md', type.render); 28 | eleventyConfig.addFilter('mdInline', type.inline); 29 | 30 | eleventyConfig.addFilter('date', time.date); 31 | 32 | // Get the first `n` elements of a collection. 33 | eleventyConfig.addFilter('slice', (array, n) => { 34 | if (n < 0) { 35 | return array.slice(n); 36 | } 37 | 38 | return array.slice(0, n); 39 | }); 40 | 41 | // config 42 | eleventyConfig.setLibrary('md', type.mdown); 43 | eleventyConfig.addDataExtension('yaml', yaml.safeLoad); 44 | eleventyConfig.setQuietMode(true); 45 | eleventyConfig.setDataDeepMerge(true); 46 | 47 | // shortcodes 48 | eleventyConfig.addPairedShortcode('md', type.render); 49 | eleventyConfig.addPairedShortcode('mdInline', type.inline); 50 | eleventyConfig.addPairedShortcode('typogr', type.set); 51 | eleventyConfig.addPairedShortcode('note', type.note); 52 | eleventyConfig.addPairedShortcode('warn', type.warn); 53 | 54 | eleventyConfig.addCollection("changes", function(collectionApi) { 55 | const all = collectionApi.getAll(); 56 | const changes = []; 57 | 58 | all.forEach((post) => { 59 | if (post.data.changes) { 60 | post.data.changes 61 | .sort((a, b) => b.time - a.time) 62 | .forEach((change, i) => { 63 | const date = change.time; 64 | changes.push({ 65 | post, 66 | date, 67 | url: post.url, 68 | log: change.log, 69 | latest: i === 0, 70 | }); 71 | }); 72 | } 73 | 74 | if (!post.data.draft) { 75 | const date = post.data.created || post.date; 76 | changes.push({ 77 | post, 78 | date, 79 | log: 'New page added', 80 | latest: post.data.changes ? false : true, 81 | creation: true, 82 | }); 83 | } 84 | }); 85 | 86 | return changes.map((item) => { 87 | item.url = `/changelog${item.post.url}${ghSlug(time.date(item.date, 'iso'))}/`; 88 | item.date_group = time.date(item.date, 'long'); 89 | return item; 90 | }).sort((a, b) => b.date - a.date); 91 | }); 92 | 93 | return { 94 | markdownTemplateEngine: 'njk', 95 | dir: { 96 | input: 'src', 97 | output: 'public', 98 | layouts: '_layouts', 99 | }, 100 | }; 101 | }; 102 | -------------------------------------------------------------------------------- /src/_layouts/base.njk: -------------------------------------------------------------------------------- 1 | --- 2 | date: Last Modified 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ title }} 11 | 12 | 13 | 14 | {% if redirect -%} 15 | 16 | 17 | {%- endif %} 18 | 19 | 20 | {% include "base/nav.njk" %} 21 | 22 |
23 |

{{ title | mdInline | safe }}

24 | 25 | {% if tags %} 26 | {% set updated = collections[index] | latest 27 | if index 28 | else collections.all | getPage(page) | getDate 29 | %} 30 | 33 | {% endif %} 34 | 35 | {% if content | toc %} 36 |
37 | Table of Contents 38 | {{ content | toc | safe }} 39 |
40 | {% endif %} 41 |
42 | 43 |
44 | {{ content | typogr | safe }} 45 |
46 | 47 | {% include "base/support.njk" %} 48 | {% include "base/changes.njk" %} 49 | 50 |
51 | {% include "base/footer.njk" %} 52 |
53 | 54 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /src/_layouts/feed.njk: -------------------------------------------------------------------------------- 1 | {%- set changes = collections.changes | slice(15) -%} 2 | 3 | 4 | {{ feed.title }} 5 | {{ feed.subtitle }} 6 | {{ feed.url }} 7 | 8 | 9 | {{ changes[0].date | dateToRfc3339 }} 10 | © {{ none | date('year') }} {{ feed.author.name }} 11 | {{ '/favicon.svg' | absoluteUrl(feed.url) }} 12 | Eleventy 13 | 14 | {{ feed.author.name }} 15 | {{ feed.author.email }} 16 | 17 | {%- for change in changes -%} 18 | {%- set absolutePostUrl = (change.post.url if change.creation else change.url) | absoluteUrl(feed.url) -%} 19 | 20 | 21 | {{ change.date | dateToRfc3339 }} 22 | {{ absolutePostUrl }} 23 | 24 | {%- if change.creation -%} 25 | 26 | New page: {{ change.post.data.title }} 27 | 28 | {%- else -%} 29 | 30 | Changes to: {{ change.post.data.title }} 31 | 32 | {%- endif -%} 33 | 34 | {%- set feedSummary -%} 35 |
36 | {{ change.log | md | safe }} 37 |
38 | 39 |

40 | 41 | {{ change.post.data.title or 'See latest' }} » 42 | 43 |

44 | {%- endset -%} 45 | 46 | {%- set feedContent -%} 47 | {%- if change.latest -%} 48 | {{- change.post.templateContent | safe -}} 49 | {%- else -%} 50 |

This page has more recent changes available. For more details, see:

51 | 56 | {%- endif -%} 57 | {%- endset -%} 58 | 59 | 60 | {{- feedSummary | htmlToAbsoluteUrls(absolutePostUrl) -}} 61 | 62 | 63 | 64 | {{- feedSummary | htmlToAbsoluteUrls(absolutePostUrl) -}} 65 | {{ '
' }} 66 | {{- feedContent | htmlToAbsoluteUrls(absolutePostUrl) -}} 67 |
68 |
69 | {%- endfor %} 70 |
71 | 72 | {# 73 | 74 | {%- for change in collections.changes %} 75 | {%- set post = change.post %} 76 | {% set absolutePostUrl %}{{ post.url | url | absoluteUrl(feed.url) }}{% endset %} 77 | 78 | {{ post.data.title }} | {{ change.log }} 79 | 80 | {{ change.date | dateToRfc3339 }} 81 | {{ absolutePostUrl }} 82 | {%- set feedContent -%} 83 | {%- if change.latest -%} 84 | {{ post.templateContent }} 85 | {%- else -%} 86 |

This page has more recent changes available. For more details, see:

87 | 92 | {%- endif -%} 93 | {%- endset -%} 94 | {{ feedContent | htmlToAbsoluteUrls(absolutePostUrl) | safe }}
95 |
96 | {%- endfor %} 97 |
#} 98 | -------------------------------------------------------------------------------- /src/rwd/query/resources.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Container Query Resources 3 | created: 2021-05-12 4 | changes: 5 | - time: 2021-09-23T10:50:59-04:00 6 | log: Articles about container query units 7 | tags: 8 | - resources 9 | --- 10 | 11 | - WICG: [Use Cases and Requirements](https://wicg.github.io/cq-usecases/) 12 | - Chris Coyier: [Let's Not Forget About Container Queries](https://css-tricks.com/lets-not-forget-about-container-queries/) 13 | - Chris Coyier: [Container Query Discussion](https://css-tricks.com/container-query-discussion/) 14 | - Zach Leatherman: [The Origin Story of Container Queries](https://www.zachleat.com/web/origin-container-queries/) 15 | 16 | [_Who is Working on Container Queries_](http://whoisworkingoncontainerqueries.com/) 17 | contains a long list of existing JS plugins. 18 | 19 | There are also some interesting CSS custom-property solutions. 20 | These all work one-property-at-a-time, 21 | much like the [`switch()` proposal](switch/)… 22 | 23 | - Heydon Pickering: [Flexbox Holy Albatros](https://heydonworks.com/article/the-flexbox-holy-albatross/) 24 | - Xiao Zhuo Jia: [Unholy Albatross](http://www.miragecraft.com/articles/unholy_albatross.html) 25 | - Mathias Hülsbusch: [The Raven Technique](https://css-tricks.com/the-raven-technique-one-step-closer-to-container-queries/) 26 | 27 | ## Talks & Podcasts 28 | 29 | - [CSSWG Proposals](https://slides.oddbird.net/csswg/) 30 | - [Styling the Intrinsic Web](https://www.oddbird.net/talks/intrinsic-web/) 31 | ([slides](https://slides.oddbird.net/css-next/)) 32 | - [Front End Nerdery](https://www.oddbird.net/2021/08/15/fe-nerdery-10/) 33 | - [Container Queries & The Future of CSS](https://www.oddbird.net/talks/responsive-components/) 34 | ([slides](https://slides.oddbird.net/css-next/)) 35 | - [Syntax.fm](https://www.oddbird.net/2021/06/16/syntaxfm-362/) 36 | - [Word Wrap Show](https://www.oddbird.net/2021/05/17/word-wrap-11/) 37 | - [The F-Word](https://www.oddbird.net/2021/05/06/f-word-11/) 38 | - [Smashing Podcast](https://www.oddbird.net/2021/05/04/smashing-36/) 39 | 40 | ## Articles & Demos 41 | 42 | - [OddBird Resources](https://www.oddbird.net/tags/container-queries/) 43 | - [Container Queries: a Quick Start Guide](https://www.oddbird.net/2021/04/05/containerqueries/) 44 | by **David Herron** 45 | - [A Primer On CSS Container Queries](https://www.smashingmagazine.com/2021/05/complete-guide-css-container-queries/) 46 | by **Stephanie Eckles** 47 | - [Say Hello To CSS Container Queries](https://ishadeed.com/article/say-hello-to-css-container-queries/) 48 | by **Ahmad Shadeed** 49 | ([annotated on CSS Tricks](https://css-tricks.com/say-hello-to-css-container-queries/) 50 | by **Robin Rendle**) 51 | - [CSS Container Queries For Designers](https://ishadeed.com/article/container-queries-for-designers/) 52 | by **Ahmad Shadeed** 53 | - [Container Queries in Web Components](https://mxb.dev/blog/container-queries-web-components/) 54 | by **Max Böck** 55 | - [Container Queries are actually coming](https://piccalil.li/blog/container-queries-are-actually-coming) 56 | by **Andy Bell** 57 | - [CSS Container Queries: A First Look + Demo](https://www.bram.us/2021/03/28/css-container-queries-a-first-look-and-demo/) 58 | by **Bramus Van Damme** 59 | - [Next Gen CSS: @container](https://css-tricks.com/next-gen-css-container/) 60 | by **Una Kravets** 61 | - [CSS Container Queries: Use-Cases And Migration Strategies](https://www.smashingmagazine.com/2021/05/css-container-queries-use-cases-migration-strategies/) 62 | by **Adrian Bece** 63 | - [Twitch live-stream highlights](https://www.twitch.tv/collections/8k9OzUpxdxb9VA) 64 | & [summary](https://www.twitch.tv/videos/993981213?collection=8k9OzUpxdxb9VA) 65 | by **Stephanie Eckles** 66 | - [My CodePen collection of demos](https://codepen.io/collection/XQrgJo) 67 | 68 | Query Units: 69 | 70 | - [CSS Container Query Units](https://ishadeed.com/article/container-query-units/) 71 | by **Ahmad Shadeed** 72 | - [Container Units Should Be Pretty Handy](https://css-tricks.com/container-units-should-be-pretty-handy/) 73 | by **Chris Coyier** 74 | 75 | See Also: 76 | 77 | - [Awesome-Container-Queries](https://github.com/sturobson/Awesome-Container-Queries) 78 | by **Stuart Robson** 79 | 80 | ## Proposals 81 | 82 | - 2020 [`@container` proposal](https://github.com/dbaron/container-queries-implementability) 83 | by **David Baron** 84 | - 2020 [`switch()` proposal](https://bkardell.com/blog/AllThemSwitches.html) 85 | by **Brian Kardell** 86 | -------------------------------------------------------------------------------- /src/rwd/interpolation/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS Interpolated Values 3 | index: interpolation 4 | created: 2020-11-13 5 | changes: 6 | - time: 2021-09-22T00:35:28-04:00 7 | log: Brief notes on @timeline and interpolation function 8 | - time: 2021-09-23T00:11:02-04:00 9 | log: Link to fantasai/mia proposal for interpolation & timelines 10 | --- 11 | 12 | Breakpoints only get you so far. 13 | In many cases it would be better to have units 14 | and values that can respond more fluidly to context. 15 | We can do some of that with relative units 16 | (several JS plugins provide container-relative units), 17 | but that approach comes with a number of limitations. 18 | 19 | [Scott Kellum](https://twitter.com/ScottKellum) 20 | has been doing interesting work in this area -- 21 | what he calls "Intrinsic Typography" -- 22 | applying animation/transition concepts 23 | like "easing" and "keyframes" 24 | to responsive type. 25 | 26 | ## Proposal 27 | 28 | Fantasai and I worked on a proposal to address & unify 29 | a number of related use-cases around interpolation & timelines: 30 | 31 | Timelines can be defined in relation to: 32 | - how far a scroll-container has scrolled 33 | - how long an element is "in-view" while being scrolled 34 | - media and container-query features that have a range value 35 | 36 | Some timelines can be used to control animations 37 | (aka scroll-linked animations), 38 | but we also propose some form of interpolation function 39 | (currently called `mix()`) 40 | that can apply a timeline and easing function 41 | to a single propery. 42 | 43 | There's more to the proposal. 44 | Check it out: 45 | 46 | https://wiki.csswg.org/ideas/timelines 47 | 48 | ## Resources 49 | 50 | From Scott: 51 | - [Typetura Docs](https://docs.typetura.com/) 52 | & [Demos](http://demos.Typetura.com) 53 | - [Intrinsic Typography, CSS Tricks Article](https://css-tricks.com/intrinsic-typography-is-the-future-of-styling-text-on-the-web/) 54 | - [Query Interpolation proposal](https://gist.github.com/scottkellum/0c29c4722394c72d311c5045a30398e5) 55 | 56 | CSSWG issues: 57 | - [Interpolate values between breakpoints](https://github.com/w3c/csswg-drafts/issues/6245) 58 | - [Split CSS event bindings from application](https://github.com/w3c/csswg-drafts/issues/4343) 59 | - [Higher level CSS interpolation module](https://github.com/w3c/csswg-drafts/issues/5617) 60 | - [Need method to interpolate variable font settings](https://github.com/w3c/csswg-drafts/issues/5635) 61 | - [Native interpolation function in CSS](https://github.com/w3c/csswg-drafts/issues/581) 62 | 63 | ## Notes 64 | 65 | A few notes from my conversations with Scott: 66 | 67 | - The most common use-case 68 | is that each property has a start-value and end-value 69 | aligned to particular container sizes, 70 | and an easing curve to interpolate. 71 | This is more like a transition than a keyframe animation. 72 | - While it's rare for a single property 73 | to have additional/intermediate "stops" defined, 74 | it is useful to define multiple properties in the same place, 75 | even with different start/end points. 76 | A keyframe animation with multiple stops 77 | makes that possible in Typetura. 78 | 79 | ### Overlap with Scroll Animations 80 | 81 | This reminds me of the proposed 82 | [`@scroll-timeline`](https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule) -- 83 | and I see Scott had the same thought: 84 | 85 | [Split CSS event bindings from application](https://github.com/w3c/csswg-drafts/issues/4343) 86 | 87 | I think the syntax could use some finesse, 88 | but that direction _feels right_ to me -- 89 | building on current animation/transition syntax, 90 | to make it work with inputs other than "time" 91 | (like scrolling, or container-width). 92 | 93 | I think there's potential here for a 94 | shared `@timeline` at-rule 95 | that could be used for: 96 | 97 | - scroll timelines 98 | - container-size timelines 99 | - media-size timelines 100 | 101 | (I also think this can all be done 102 | without the `selector()` function, 103 | but I need to look into it more.) 104 | 105 | ### Interpolation Function 106 | 107 | The CSSWG resolved at one point 108 | to add an interpolation function -- 109 | though the syntax/details are TBD. 110 | 111 | That would require: 112 | 113 | - an easing function 114 | - a percentage that represents current interpolated position 115 | (potentially provided by a timeline) 116 | - a list of values to interpolate 117 | -------------------------------------------------------------------------------- /src/scope/prior-art.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Prior Art 3 | created: 2021-10-05 4 | --- 5 | 6 | ## Existing Specifications 7 | 8 | ### [CSS Selectors - Level 4](https://www.w3.org/TR/selectors-4/) 9 | 10 | - [Scoped Selectors](https://www.w3.org/TR/selectors-4/#scoping) 11 | that only refer to a subtree or fragment of the document 12 | 13 | > When a selector is scoped, it matches an element 14 | > only if the element is a descendant of the scoping root. 15 | > (The rest of the selector can match unrestricted; 16 | > it’s only the final matched elements that must be within the scope.) 17 | 18 | - [Reference Element](https://www.w3.org/TR/selectors-4/#the-scope-pseudo) 19 | (`:scope`) pseudo-class 20 | (broad [browser support](https://developer.mozilla.org/en-US/docs/Web/CSS/:scope)) 21 | 22 | In CSS, this is the same as `:root`, since there is no way to scope elements. However, it is used by JS APIs to refer to the base element of e.g. `element.querySelector()` 23 | 24 | > “Specifications intending for this pseudo-class to match specific elements 25 | > rather than the document’s root element 26 | > must define either a scoping root (if using scoped selectors) 27 | > or an explicit set of :scope elements.” 28 | 29 | ### [CSS Scoping - Level 1](https://drafts.csswg.org/css-scoping/) 30 | 31 | The latest draft is primarily concerned 32 | with Custom Elements & Shadow DOM. 33 | 34 | The [First Public Working Draft](https://www.w3.org/TR/css-scoping-1/) 35 | had more scoping features that have since been removed: 36 | 37 | A `