├── README.md ├── common ├── default.css ├── prism.css └── prism.js ├── construct-stylesheets ├── index.bs └── index.html ├── css-aliases ├── index.bs └── index.html ├── css-anchor-position ├── index.bs └── index.html ├── css-apply-rule ├── index.bs └── index.html ├── css-cascade-control ├── index.bs └── index.html ├── css-color ├── images │ └── color-picker.png ├── index.bs └── index.html ├── css-content-size ├── index.bs └── index.html ├── css-extend-rule ├── index.bs └── index.html ├── css-filter-rule ├── index.bs └── index.html ├── css-font-display ├── index.bs └── index.html ├── css-masonry ├── index.bs └── index.html ├── css-nesting ├── index.bs └── index.html ├── css-shadow-parts ├── index.bs └── index.html ├── css-shared-element-transitions ├── index.bs └── index.html ├── css-stacking-context-1 ├── index.bs └── index.html ├── css-sticky-scrollbars ├── index.bs └── index.html ├── css-toggle-states ├── index.bs └── index.html ├── css-when-else ├── index.bs └── index.html ├── css-will-change ├── index.bs └── index.html ├── css2-chapters └── index.html ├── index.html ├── layout-transitions ├── index.bs └── index.html ├── qrcode ├── index.bs └── index.html ├── respimg ├── images │ ├── difimages.jpg │ └── viewport_selection_mob_first.jpg ├── index.bs └── index.html ├── svg-params ├── index.bs └── index.html └── unit-problems ├── index.bs └── index.html /README.md: -------------------------------------------------------------------------------- 1 | specs 2 | ===== 3 | 4 | Spec proposals that aren't yet approved by the relevant Working Group. Everything in here is my own work and not endorsed by the relevant Working Group. (Unless I'm working on a new version of an existing spec, in which case existing parts of it might not be my own work.) 5 | 6 | Live copies of the specs: 7 | 8 | * [CSS Toggle States Level 1](http://tabatkins.github.io/specs/css-toggle-states/) 9 | * [CSS Nesting](http://tabatkins.github.io/specs/css-nesting/) 10 | * [CSS Aliases (custom stuff)](http://tabatkins.github.io/specs/css-aliases) 11 | * [Layout Transitions](http://tabatkins.github.io/specs/layout-transitions) 12 | * [@extend](http://tabatkins.github.io/specs/css-extend-rule) 13 | * [Constructable Stylesheets](http://tabatkins.github.io/specs/construct-stylesheets) 14 | * [SVG Parameters](http://tabatkins.github.io/specs/svg-params) 15 | * [CSS Cascade Control](https://tabatkins.github.io/specs/css-cascade-control/) 16 | * [@when/@else](https://tabatkins.github.io/specs/css-when-else/) 17 | * [CSS Stacking Context](https://tabatkins.github.io/specs/css-stacking-context-1/) 18 | * [CSS Anchor Positioning](https://tabatkins.github.io/specs/css-anchor-position/) 19 | * [CSS Masonry Layout alt proposal](https://tabatkins.github.io/specs/css-masonry/) 20 | -------------------------------------------------------------------------------- /common/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Style sheet for the CSS3 specification, 3 | * to be used in addition to http://www.w3.org/StyleSheets/TR/W3C-{WD,PR,REC} 4 | */ 5 | 6 | @media print { 7 | html { margin: 0 !important } 8 | body { font-family: serif } 9 | th, td { font-family: inherit } 10 | a { color: inherit !important } 11 | .example:before { font-family: serif !important } 12 | a:link, a:visited { text-decoration: none !important } 13 | a:link:after, a:visited:after { /* create a cross-ref "see..." */ } 14 | } 15 | @page { 16 | margin: 1.5cm 1.1cm; 17 | } 18 | 19 | body { 20 | counter-reset: exampleno figure issue; 21 | max-width: 50em; 22 | margin: 0 auto !important; 23 | } 24 | 25 | /* Pagination */ 26 | h1, h2, h3, h4, h5, h6 { page-break-after: avoid } 27 | figure, div.figure, div.sidefigure, pre, table.propdef, table.propdef-extra, 28 | .example { page-break-inside: avoid } 29 | dt { page-break-after: avoid } 30 | 31 | span.id {float: right; font-weight: bold} 32 | 33 | /* General Structural Markup */ 34 | h2, h3, h5, h6 { margin-top: 3em; } 35 | 36 | h1 + h2 { margin-top: 0; } 37 | 38 | h4 { margin-top: 4em; } 39 | 40 | h2 + h3, h3 + h4, h4 + h5, h5 + h6 { margin-top: 1.2em } 41 | 42 | p, div.note, div.issue, details.why { 43 | margin-top: 1em; 44 | margin-bottom: 1em; 45 | } 46 | 47 | dd > p:first-child, li > p:first-child, .note > p:first-child, .issue > p:first-child { 48 | margin-top: 0 49 | } 50 | 51 | pre { 52 | margin-top: 1em; 53 | margin-bottom: 1em; 54 | } 55 | 56 | pre, code { 57 | font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace; 58 | font-size: .9em; 59 | } 60 | 61 | img { 62 | border-style: none; 63 | color: white; 64 | } 65 | .toc { 66 | } 67 | 68 | body { 69 | line-height: 1.5; 70 | } 71 | 72 | a:link, a:visited { 73 | border-bottom: 1px solid silver; 74 | color: inherit; 75 | text-decoration: none; 76 | } 77 | 78 | a.logo:link, a.logo:visited { 79 | padding: 0; 80 | border-style: none; 81 | } 82 | 83 | dl dd { margin: 0 0 1em 2em } 84 | .head dd { margin-bottom: 0; } 85 | ul, ol { margin-left: 0; padding-left: 2em; } 86 | li { margin: 0.25em 2em 0.5em 0; padding-left: 0 } 87 | 88 | ul.indexlist { margin-left: 0; columns: 13em; } 89 | ul.indexlist li { margin-left: 0; list-style: none } 90 | ul.indexlist li li { margin-left: 1em } 91 | ul.indexlist a { font-weight: bold; } 92 | ul.indexlist ul, ul.indexlist dl { font-size: smaller; } 93 | ul.indexlist dl { margin-top: 0; } 94 | ul.indexlist dt { margin: .2em 0 .2em 20px;} 95 | ul.indexlist dd { margin: .2em 0 .2em 40px;} 96 | 97 | /* .self-link is a link to the element */ 98 | .heading, .issue, .note, .example, li, dt { position: relative; } 99 | a.self-link { 100 | position: absolute; 101 | top: 0; 102 | left: -2.5em; 103 | width: 2em; 104 | height: 2em; 105 | text-align: center; 106 | border: none; 107 | transition: opacity .2s; 108 | opacity: .5; 109 | } 110 | a.self-link:hover { 111 | opacity: 1; 112 | } 113 | .heading > a.self-link { 114 | font-size: 83%; 115 | } 116 | li > a.self-link { 117 | left: -3.5em; 118 | } 119 | dfn > a.self-link { 120 | top: auto; 121 | left: auto; 122 | opacity: 0; 123 | width: 1.5em; 124 | height: 1.5em; 125 | background: gray; 126 | color: white; 127 | font-style: normal; 128 | transition: opacity .2s, background-color .2s, color .2s; 129 | } 130 | dfn:hover > a.self-link { 131 | opacity: 1; 132 | } 133 | dfn > a.self-link:hover { 134 | color: black; 135 | } 136 | 137 | a.self-link::before { content: "¶"; } 138 | .heading > a.self-link::before { content: "§"; } 139 | dfn > a.self-link::before { content: "#"; } 140 | 141 | /* Examples */ 142 | 143 | .example { 144 | counter-increment: exampleno; 145 | } 146 | .example:before { 147 | content: "Example"; 148 | content: "Example " counter(exampleno); 149 | min-width: 7.5em; 150 | text-transform: uppercase; 151 | display: block; 152 | } 153 | div.illegal-example:before, pre.illegal-example:before { 154 | content: "Invalid Example"; 155 | content: "Invalid Example" counter(exampleno); 156 | } 157 | .example, .illegal-example, div.html, div.illegal-html, div.xml, 158 | div.illegal-xml, pre.html, 159 | pre.illegal-html, pre.xml, pre.illegal-xml { 160 | padding: 0.5em; 161 | margin: 1em 0; 162 | position: relative; 163 | clear: both; 164 | } 165 | pre.example, pre.illegal-example, pre.html, 166 | pre.illegal-html, pre.xml, pre.illegal-xml { 167 | padding-top: 1.5em; 168 | } 169 | pre.illegal-example { color: red } 170 | div.illegal-example { color: red } 171 | div.illegal-example p { color: black } 172 | 173 | div.html { color: #600 } 174 | pre.html { color: #600 } 175 | pre.illegal-html { color: red } 176 | div.illegal-html { color: red } 177 | div.illegal-html p { color: black } 178 | pre.deprecated-html { color: red } 179 | div.deprecated-html { color: red } 180 | div.deprecated-html p { color: black } 181 | 182 | div.xml { color: #600 } 183 | pre.xml { color: #600 } 184 | pre.illegal-xml { color: red } 185 | div.illegal-xml { color: red } 186 | div.illegal-xml p { color: black } 187 | 188 | .css, .property { color: #005a9c } /* inline CSS code (SPAN/CODE) */ 189 | code.css { font-family: inherit; font-size: 100% } 190 | code.html { color: #600 } /* inline HTML */ 191 | code.xml { color: #600 } /* inline XML */ 192 | .property { font: inherit; white-space: nowrap; } /* name of a CSS property (SPAN) */ 193 | .descriptor { } /* name of a CSS descriptor (SPAN) */ 194 | .type { font-style: italic } /* A value for a property */ 195 | 196 | /* Autolinks produced using Tab's preprocessor. */ 197 | [data-link-type="property"]::before, 198 | [data-link-type="propdesc"]::before, 199 | [data-link-type="descriptor"]::before, 200 | [data-link-type="value"]::before, 201 | [data-link-type="function"]::before, 202 | [data-link-type="at-rule"]::before, 203 | [data-link-type="selector"]::before, 204 | [data-link-type="maybe"]::before {content: "\2018";} 205 | [data-link-type="property"]::after, 206 | [data-link-type="propdesc"]::after, 207 | [data-link-type="descriptor"]::after, 208 | [data-link-type="value"]::after, 209 | [data-link-type="function"]::after, 210 | [data-link-type="at-rule"]::after, 211 | [data-link-type="selector"]::after, 212 | [data-link-type="maybe"]::after {content: "\2019";} 213 | [data-link-type].production::before, 214 | [data-link-type].production::after { content: ""; } 215 | 216 | dfn { font-weight: bolder; } 217 | a > i { font-style: normal; } /* Instance of term */ 218 | 219 | .issue, .note, .example, .why { 220 | padding: .5em; 221 | /* padding: .5rem; /* proposed unit in css3-values */ 222 | border-left-width: .5em; 223 | /* border-left-width: .5rem; /* proposed unit in css3-values */ 224 | border-left-style: solid; 225 | } 226 | span.note, span.issue { padding: .1em .5em .15em; } 227 | 228 | /* Open issue / editorial remark; not intended for a final publication */ 229 | .issue { 230 | border-color: #E05252; 231 | background: #FBE9E9; 232 | counter-increment: issue; 233 | } 234 | 235 | .issue:before { 236 | content: "Issue " counter(issue); 237 | padding-right: 1em; 238 | text-transform: uppercase; 239 | color: #E05252; 240 | } 241 | 242 | /* Class note is a non-normative note. May be inline or a P or DIV */ 243 | .note, .why { 244 | border-color: #52E052; 245 | background: #E9FBE9; 246 | } 247 | 248 | .normref { color: red } 249 | .informref { color: green } 250 | 251 | /* Example box */ 252 | .example { 253 | border-color: #E0CB52; 254 | background: #FCFAEE; 255 | } 256 | 257 | .example:before { 258 | color: #B9AB2D; 259 | font-family: sans-serif; 260 | } 261 | 262 | details.why { 263 | border-color: #52E052; 264 | background: #E9FBE9; 265 | } 266 | 267 | details.why > summary { 268 | font-style: italic; 269 | } 270 | 271 | details.why[open] > summary { 272 | border-bottom: 1px silver solid; 273 | } 274 | 275 | /* ToC not indented, but font style shows hierarchy */ 276 | ul.toc {margin: 1em 0; padding: 0; line-height: 1.3; font-weight: bold; /*text-transform: uppercase;*/ } 277 | ul.toc ul {margin: 0; padding: 0; font-weight: normal; text-transform: none; } 278 | ul.toc ul ul {margin: 0 0 0 2em; font-style: italic; } 279 | ul.toc ul ul ul {margin: 0} 280 | ul.toc > li {margin: 1.5em 0; padding: 0; } 281 | ul.toc ul.toc li { margin: 0.3em 0 0 0; } 282 | ul.toc a { text-decoration: none; border-bottom-style: none; } 283 | ul.toc a:hover, ul.toc a:focus { border-bottom-style: solid; } 284 | /* 285 | ul.toc li li li, ul.toc li li li ul {margin-left: 0; display: inline} 286 | ul.toc li li li ul, ul.toc li li li ul li {margin-left: 0; display: inline} 287 | */ 288 | 289 | /* Section numbers in a column of their own */ 290 | ul.toc span.secno {float: left; width: 4em; margin-left: -5em} 291 | ul.toc ul ul span.secno { margin-left: -7em; } 292 | /*ul.toc span.secno {text-align: right}*/ 293 | ul.toc li {clear: both} 294 | ul.toc {margin-left: 5em} 295 | /* If we had 'tab', floats would not be needed here: 296 | ul.toc span.secno {tab: 5em right; margin-right: 1em} 297 | ul.toc li {text-indent: 5em hanging} 298 | The second line in case items wrap 299 | */ 300 | 301 | ul.index { 302 | list-style: none; 303 | } 304 | 305 | s, del {text-decoration: line-through; color: red} 306 | u, ins {text-decoration: underline; background: #bfa} 307 | 308 | div.figure, p.figure, div.sidefigure, figure { 309 | text-align: center; 310 | margin: 2.5em 0; 311 | } 312 | div.figure pre, div.sidefigure pre, figure pre { 313 | text-align: left; 314 | display: table; 315 | margin: 1em auto; 316 | } 317 | .figure table, figure table { 318 | margin: auto; 319 | } 320 | div.sidefigure, figure.sidefigure { 321 | float: right; 322 | width: 50%; 323 | margin: 0 0 0.5em 0.5em 324 | } 325 | div.figure img, div.sidefigure img, figure img, 326 | div.figure object, div.sidefigure object, figure object { 327 | display: block; 328 | margin: auto; 329 | max-width: 100% 330 | } 331 | p.caption, figcaption, caption { 332 | text-align: center; 333 | font-style: italic; 334 | font-size: 90%; 335 | } 336 | p.caption:before, figcaption:before { 337 | content: "Figure " counter(figure) ". "; 338 | font-weight: bold; 339 | } 340 | p.caption, figcaption { 341 | counter-increment: figure; 342 | } 343 | 344 | /* DL list is indented, but figure inside it is not */ 345 | dd { margin-left: 2em } 346 | dd div.figure, dd figure { margin-left: -2em } 347 | 348 | sup { 349 | vertical-align: super; 350 | font-size: 80% 351 | } 352 | 353 | /* "Equations" (not real MathML, but simple HTML) are put in a 354 | blockquote and may have an equation number. We make sure the 355 | blockquote has enough margin on the right and then put the equation 356 | number there. */ 357 | 358 | blockquote { 359 | margin: 0.5em 4em 0.5em 2em; 360 | text-indent: 0; 361 | } 362 | .eqno { 363 | text-align: right; 364 | float: right; 365 | width: 3em; 366 | margin: 0 -4em 0 0; 367 | font-weight: bold; 368 | /* background: silver; color: black; padding: 0.1em */ 369 | } 370 | 371 | table.equiv-table { border-spacing: 0; margin: 0.5em 0 } 372 | table.equiv-table th, table.equiv-table td { padding: 0.3em } 373 | table.equiv-table th { text-align: left } 374 | /* table.equiv-table th:first-child { text-align: right } */ 375 | table.equiv-table td, table.equiv-table th { border-bottom: thin solid #666 } 376 | table.equiv-table { border-bottom: hidden } 377 | table.equiv-table { empty-cells: show } 378 | table.equiv-table caption { margin: 0.5em 0 0 0 } 379 | 380 | /* Style for table of properties */ 381 | table.proptable { 382 | font-size: small; 383 | border-collapse: collapse; 384 | border-spacing: 0; 385 | text-align: left; 386 | margin: 1em 0; 387 | } 388 | 389 | table.proptable td, table.proptable th { 390 | padding: 0.4em; 391 | text-align: center; 392 | } 393 | 394 | table.proptable tr:hover td { 395 | background: #DEF; 396 | } 397 | 398 | 399 | /* Style for table that defines a property or a descriptor */ 400 | table.propdef, table.propdef-extra, table.descdef, table.definition-table { 401 | border-spacing: 0; 402 | padding: 0 1em 0.5em; 403 | width: 100%; 404 | table-layout: fixed; 405 | background: #DEF; 406 | margin: 1.2em 0; 407 | border-left: 0.5em solid #8CCBF2; 408 | } 409 | 410 | table.propdef td, table.propdef-extra td, table.descdef td, table.definition-table td, 411 | table.propdef th, table.propdef-extra th, table.descdef th, table.definition-table th { 412 | padding: 0.5em; 413 | vertical-align: baseline; 414 | border-bottom: 1px solid #bbd7e9; 415 | } 416 | /* 417 | table.propdef dfn, table.propdef-extra dfn, table.descdef dfn { 418 | font-weight: bold; 419 | font-style: normal 420 | } 421 | */ 422 | 423 | table.propdef td:first-child, 424 | table.propdef-extra td:first-child, 425 | table.descdef td:first-child, 426 | table.definition-table td:first-child, 427 | table.propdef th:first-child, 428 | table.propdef-extra th:first-child, 429 | table.descdef th:first-child, 430 | table.definition-table th:first-child { 431 | font-style: italic; 432 | font-weight: normal; 433 | width: 8.3em; 434 | padding-left: 1em; 435 | } 436 | table.propdef td[colspan]:first-child, 437 | table.propdef-extra td[colspan]:first-child, 438 | table.descdef td[colspan]:first-child, 439 | table.definition-table td[colspan]:first-child, 440 | table.propdef th[colspan]:first-child, 441 | table.propdef-extra th[colspan]:first-child, 442 | table.descdef th[colspan]:first-child, 443 | table.definition-table th[colspan]:first-child { 444 | font-style: inherit 445 | } 446 | table.propdef tr:first-child, 447 | table.propdef-extra tr:first-child, 448 | table.descdef tr:first-child, 449 | table.definition-table tr:first-child { 450 | 451 | } 452 | 453 | table.propdef > tbody > tr:last-child th, 454 | table.propdef-extra > tbody > tr:last-child th, 455 | table.descdef > tbody > tr:last-child th, 456 | table.definition-table > tbody > tr:last-child th, 457 | table.propdef > tbody > tr:last-child td, 458 | table.propdef-extra > tbody > tr:last-child td, 459 | table.descdef > tbody > tr:last-child td, 460 | table.definition-table > tbody > tr:last-child td { 461 | border-bottom: 0; 462 | } 463 | 464 | table.propdef tr:first-child th, 465 | table.propdef-extra tr:first-child th, 466 | table.descdef tr:first-child th, 467 | table.definition-table tr:first-child th, 468 | table.propdef tr:first-child td, 469 | table.propdef-extra tr:first-child td, 470 | table.descdef tr:first-child td, 471 | table.definition-table tr:first-child td { 472 | padding-top: 1em; 473 | } 474 | 475 | /* For when values are extra-complex and need formatting for readability */ 476 | table td.pre { 477 | white-space: pre-wrap; 478 | } 479 | 480 | /* A footnote at the bottom of a propdef */ 481 | table.propdef td.footnote, 482 | table.propdef-extra td.footnote, 483 | table.descdef td.footnote, 484 | table.definition-table td.footnote { 485 | padding-top: 0.6em; 486 | width: auto 487 | } 488 | table.propdef td.footnote:before, 489 | table.propdef-extra td.footnote:before, 490 | table.descdef td.footnote:before, 491 | table.definition-table td.footnote:before { 492 | content: " "; 493 | display: block; 494 | height: 0.6em; 495 | width: 4em; 496 | border-top: thin solid; 497 | } 498 | 499 | /* I don't know what this is for */ 500 | table.proptable td .property { 501 | display: block; 502 | text-align: left; 503 | font-weight: bold; 504 | } 505 | 506 | 507 | /* Styling for IDL fragments */ 508 | 509 | pre.idl { 510 | padding: .5em 1em; 511 | background: #DEF; 512 | margin: 1.2em 0; 513 | border-left: 0.5em solid #8CCBF2; 514 | } 515 | pre.idl :link, pre.idl :visited { 516 | color:inherit; 517 | background:transparent; 518 | } 519 | 520 | 521 | /* CSS modules typically don't use MUST, SHOULD etc. from RFC 2119, 522 | or, if they do, they don't put them in uppercase. But the following 523 | class is provided in case a spec wants to use RFC 2119 terms in 524 | uppercase in the source. */ 525 | 526 | em.rfc2119 { 527 | text-transform: lowercase; 528 | font-variant: small-caps; 529 | font-style: normal 530 | } 531 | 532 | /* In Profile specs, a table of required features: */ 533 | 534 | table.features th { 535 | background: #00589f; 536 | color: #fff; 537 | text-align: left; 538 | padding: 0.2em 0.2em 0.2em 0.5em; 539 | } 540 | table.features td { 541 | vertical-align: top; 542 | border-bottom: 1px solid #ccc; 543 | padding: 0.3em 0.3em 0.3em 0.7em; 544 | } 545 | 546 | 547 | /* Style for data tables (and properly marked-up proptables) */ 548 | 549 | .data, .proptable { 550 | margin: 1em auto; 551 | border-collapse: collapse; 552 | width: 100%; 553 | border: hidden; 554 | } 555 | .data { 556 | text-align: center; 557 | } 558 | .data caption { 559 | width: 100%; 560 | } 561 | 562 | .data td, .data th, 563 | .proptable td, .proptable th { 564 | padding: 0.5em; 565 | border-top: 1px silver solid; 566 | } 567 | 568 | .data thead td:empty { 569 | padding: 0; 570 | border: 0; 571 | } 572 | 573 | .data thead th[scope="row"], 574 | .proptable thead th[scope="row"] { 575 | text-align: right; 576 | color: inherit; 577 | } 578 | 579 | .data thead, 580 | .proptable thead, 581 | .data tbody, 582 | .proptable tbody { 583 | color: inherit; 584 | border-bottom: 2px solid; 585 | } 586 | 587 | .data colgroup { 588 | border-left: 2px solid; 589 | } 590 | 591 | .data tbody th:first-child, 592 | .proptable tbody th:first-child , 593 | .data tbody td[scope="row"]:first-child, 594 | .proptable tbody td[scope="row"]:first-child { 595 | text-align: right; 596 | color: inherit; 597 | border-right: 2px solid; 598 | border-top: 1px solid silver; 599 | padding-right: 1em; 600 | } 601 | .data.define td:last-child { 602 | text-align: left; 603 | } 604 | 605 | .data tbody th[rowspan], 606 | .proptable tbody th[rowspan], 607 | .data tbody td[rowspan], 608 | .proptable tbody td[rowspan]{ 609 | border-left: 1px solid silver; 610 | } 611 | 612 | .data tbody th[rowspan]:first-child, 613 | .proptable tbody th[rowspan]:first-child, 614 | .data tbody td[rowspan]:first-child, 615 | .proptable tbody td[rowspan]:first-child{ 616 | border-left: 0; 617 | border-right: 1px solid silver; 618 | } 619 | 620 | .complex.data th, 621 | .complex.data td { 622 | border: 1px solid silver; 623 | } 624 | 625 | .data td.long { 626 | vertical-align: baseline; 627 | text-align: left; 628 | } 629 | 630 | .data img { 631 | vertical-align: middle; 632 | } 633 | 634 | table.propdef { 635 | table-layout: auto; 636 | } 637 | .propdef th { 638 | font-style: italic; 639 | font-weight: normal; 640 | text-align: left; 641 | width: 3em; 642 | } 643 | dt dfn code { 644 | font-size: inherit; 645 | } 646 | 647 | /* Style for switch/case
s */ 648 | dl.switch { 649 | padding-left: 2em; 650 | } 651 | dl.switch > dt { 652 | text-indent: -1.5em; 653 | } 654 | dl.switch > dt:before { 655 | content: '\21AA'; 656 | padding: 0 0.5em 0 0; 657 | display: inline-block; 658 | width: 1em; 659 | text-align: right; 660 | line-height: 0.5em; 661 | } 662 | 663 | 664 | /* Style for At Risk features (intended as editorial aid, not intended for publishing) */ 665 | .atrisk::before { 666 | position: absolute; 667 | margin-left: -5em; 668 | margin-top: -2px; 669 | padding: 4px; 670 | border: 1px solid; 671 | content: 'At risk'; 672 | font-size: small; 673 | background-color: white; 674 | color: gray; 675 | border-radius: 1em; 676 | text-align: center; 677 | } 678 | 679 | .toc .atrisk::before { content:none } 680 | 681 | 682 | /* This is mostly to make the list inside the CR exit criteria more compact. */ 683 | ol.inline, ol.inline li {display: inline; padding: 0; margin: 0} 684 | ol.inline {counter-reset: list-item} 685 | ol.inline li {counter-increment: list-item} 686 | ol.inline li:before {content: "(" counter(list-item) ") "; font-weight: bold} 687 | 688 | /* This styles the obsoletion notice on some of our older/abandoned specs. */ 689 | details.annoying-warning[open] { 690 | background: #fdd; 691 | color: red; 692 | font-weight: bold; 693 | text-align: center; 694 | padding: .5em; 695 | border: thick solid red; 696 | border-radius: 1em; 697 | position: fixed; 698 | left: 1em; 699 | right: 1em; 700 | bottom: 1em; 701 | z-index: 1000; 702 | } 703 | 704 | details.annoying-warning:not([open]) > summary { 705 | background: #fdd; 706 | color: red; 707 | font-weight: bold; 708 | text-align: center; 709 | padding: .5em; 710 | } 711 | -------------------------------------------------------------------------------- /common/prism.css: -------------------------------------------------------------------------------- 1 | /** 2 | * prism.js default theme for JavaScript, CSS and HTML 3 | * Based on dabblet (http://dabblet.com) 4 | * @author Lea Verou 5 | */ 6 | 7 | code[class*="language-"], 8 | pre[class*="language-"] { 9 | color: black; 10 | text-shadow: 0 1px white; 11 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 12 | direction: ltr; 13 | text-align: left; 14 | white-space: pre; 15 | word-spacing: normal; 16 | 17 | -moz-tab-size: 4; 18 | -o-tab-size: 4; 19 | tab-size: 4; 20 | 21 | -webkit-hyphens: none; 22 | -moz-hyphens: none; 23 | -ms-hyphens: none; 24 | hyphens: none; 25 | } 26 | 27 | @media print { 28 | code[class*="language-"], 29 | pre[class*="language-"] { 30 | text-shadow: none; 31 | } 32 | } 33 | 34 | /* Code blocks */ 35 | pre[class*="language-"] { 36 | padding: 1em; 37 | margin: .5em 0; 38 | overflow: auto; 39 | } 40 | 41 | :not(pre) > code[class*="language-"], 42 | pre[class*="language-"] { 43 | background: #f5f2f0; 44 | } 45 | 46 | /* Inline code */ 47 | :not(pre) > code[class*="language-"] { 48 | padding: .1em; 49 | border-radius: .3em; 50 | } 51 | 52 | .token.comment, 53 | .token.prolog, 54 | .token.doctype, 55 | .token.cdata { 56 | color: slategray; 57 | } 58 | 59 | .token.punctuation { 60 | color: #999; 61 | } 62 | 63 | .namespace { 64 | opacity: .7; 65 | } 66 | 67 | .token.property, 68 | .token.tag, 69 | .token.boolean, 70 | .token.number { 71 | color: #905; 72 | } 73 | 74 | .token.selector, 75 | .token.attr-name, 76 | .token.string { 77 | color: #690; 78 | } 79 | 80 | .token.operator, 81 | .token.entity, 82 | .token.url, 83 | .language-css .token.string, 84 | .style .token.string { 85 | color: #a67f59; 86 | background: hsla(0,0%,100%,.5); 87 | } 88 | 89 | .token.atrule, 90 | .token.attr-value, 91 | .token.keyword { 92 | color: #07a; 93 | } 94 | 95 | 96 | .token.regex, 97 | .token.important { 98 | color: #e90; 99 | } 100 | 101 | .token.important { 102 | font-weight: bold; 103 | } 104 | 105 | .token.entity { 106 | cursor: help; 107 | } 108 | pre[data-line] { 109 | position: relative; 110 | padding: 1em 0 1em 3em; 111 | } 112 | 113 | .line-highlight { 114 | position: absolute; 115 | left: 0; 116 | right: 0; 117 | padding: inherit 0; 118 | margin-top: 1em; /* Same as .prism’s padding-top */ 119 | 120 | background: hsla(24, 20%, 50%,.08); 121 | background: -moz-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); 122 | background: -webkit-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); 123 | background: -o-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); 124 | background: linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); 125 | 126 | pointer-events: none; 127 | 128 | line-height: inherit; 129 | white-space: pre; 130 | } 131 | 132 | .line-highlight:before, 133 | .line-highlight[data-end]:after { 134 | content: attr(data-start); 135 | position: absolute; 136 | top: .4em; 137 | left: .6em; 138 | min-width: 1em; 139 | padding: 0 .5em; 140 | background-color: hsla(24, 20%, 50%,.4); 141 | color: hsl(24, 20%, 95%); 142 | font: bold 65%/1.5 sans-serif; 143 | text-align: center; 144 | vertical-align: .3em; 145 | border-radius: 999px; 146 | text-shadow: none; 147 | box-shadow: 0 1px white; 148 | } 149 | 150 | .line-highlight[data-end]:after { 151 | content: attr(data-end); 152 | top: auto; 153 | bottom: .4em; 154 | } -------------------------------------------------------------------------------- /common/prism.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Prism: Lightweight, robust, elegant syntax highlighting 3 | * MIT license http://www.opensource.org/licenses/mit-license.php/ 4 | * @author Lea Verou http://lea.verou.me 5 | */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var i in e)e.hasOwnProperty(i)&&(r[i]=t.util.clone(e[i]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var i in n)r[i]=n[i];return r},insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);t.util.type(e)==="Object"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent;if(!f)return;f=f.replace(/&/g,"&").replace(//g,">").replace(/\u00a0/g," ");var l={element:r,language:o,grammar:u,code:f};t.hooks.run("before-highlight",l);if(i&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){l.highlightedCode=n.stringify(JSON.parse(e.data));l.element.innerHTML=l.highlightedCode;s&&s.call(l.element);t.hooks.run("after-highlight",l)};c.postMessage(JSON.stringify({language:l.language,code:l.code}))}else{l.highlightedCode=t.highlight(l.code,l.grammar);l.element.innerHTML=l.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",l)}},highlight:function(e,r){return n.stringify(t.tokenize(e,r))},tokenize:function(e,n){var r=t.Token,i=[e],s=n.rest;if(s){for(var o in s)n[o]=s[o];delete n.rest}e:for(var o in n){if(!n.hasOwnProperty(o)||!n[o])continue;var u=n[o],a=u.inside,f=!!u.lookbehind||0;u=u.pattern||u;for(var l=0;le.length)break e;if(c instanceof r)continue;u.lastIndex=0;var h=u.exec(c);if(h){f&&(f=h[1].length);var p=h.index-1+f,h=h[0].slice(f),d=h.length,v=p+d,m=c.slice(0,p+1),g=c.slice(v+1),y=[l,1];m&&y.push(m);var b=new r(o,a?t.tokenize(h,a):h);y.push(b);g&&y.push(g);Array.prototype.splice.apply(i,y)}}}return i},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]")return e.map(n.stringify).join("");var r={type:e.type,content:n.stringify(e.content),tag:"span",classes:["token",e.type],attributes:{}};r.type=="comment"&&(r.attributes.spellcheck="true");t.hooks.run("wrap",r);var i="";for(var s in r.attributes)i+=s+'="'+(r.attributes[s]||"")+'"';return"<"+r.tag+' class="'+r.classes.join(" ")+'" '+i+">"+r.content+""};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();; 6 | Prism.languages.markup={comment:/<!--[\w\W]*?--(>|>)/g,prolog:/<\?.+?\?>/,doctype:/<!DOCTYPE.+?>/,cdata:/<!\[CDATA\[[\w\W]+?]]>/i,tag:{pattern:/<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi,inside:{tag:{pattern:/^<\/?[\w:-]+/i,inside:{punctuation:/^<\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|>|"/g}},punctuation:/\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&/,"&"))});; 7 | Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:/@[\w-]+?(\s+[^;{]+)?(?=\s*{|\s*;)/gi,url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\}]*(?=\s*\{)/g,property:/(\b|\B)[a-z-]+(?=\s*:)/ig,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig,inside:{tag:{pattern:/(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});; 8 | Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|[^:]\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,number:/\b-?(0x)?\d*\.?[\da-f]+\b/g,operator:/[-+]{1,2}|!|=?<|=?>|={1,2}|(&){1,2}|\|?\||\?|\*|\//g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; 9 | Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|catch|finally|null|break|continue)\b/g,number:/\b(-?(0x)?\d*\.?[\da-f]+|NaN|-?Infinity)\b/g});Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}});Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig,inside:{tag:{pattern:/(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});; 10 | (function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function n(e,t,n){var r=t.replace(/\s+/g,"").split(","),i=+e.getAttribute("data-line-offset")||0,s=parseFloat(getComputedStyle(e).lineHeight);for(var o=0,u;u=r[o++];){u=u.split("-");var a=+u[0],f=+u[1]||a,l=document.createElement("div");l.textContent=Array(f-a+2).join(" \r\n");l.className=(n||"")+" line-highlight";l.setAttribute("data-start",a);f>a&&l.setAttribute("data-end",f);l.style.top=(a-i-1)*s+"px";(e.querySelector("code")||e).appendChild(l)}}function r(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var r=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(!r||document.getElementById(t))return;var i=t.slice(0,t.lastIndexOf(".")),s=document.getElementById(i);if(!s)return;s.hasAttribute("data-line")||s.setAttribute("data-line","");n(s,r,"temporary ");document.querySelector(".temporary.line-highlight").scrollIntoView()}if(!window.Prism)return;var t=crlf=/\r?\n|\r/g,i=0;Prism.hooks.add("after-highlight",function(t){var s=t.element.parentNode,o=s&&s.getAttribute("data-line");if(!s||!o||!/pre/i.test(s.nodeName))return;clearTimeout(i);e(".line-highlight",s).forEach(function(e){e.parentNode.removeChild(e)});n(s,o);i=setTimeout(r,1)});addEventListener("hashchange",r)})();; -------------------------------------------------------------------------------- /construct-stylesheets/index.bs: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | 17 | Adding Stylesheets In Script {#adding-stylesheets} 18 | ================================= 19 | 20 |
 21 | [Constructor(DOMString text, optional CSSStyleSheetInit options)]
 22 | partial interface CSSStyleSheet {
 23 | };
 24 | 
 25 | dictionary CSSStyleSheetInit {
 26 | 	(MediaList or DOMString) media = "";
 27 | 	DOMString title = "";
 28 | 	boolean alternate = false;
 29 | 	boolean disabled = false;
 30 | };
 31 | 
 32 | interface TreeScope {
 33 | 	attribute StyleSheetList moreStyleSheets;
 34 | };
 35 | Document implements TreeScope;
 36 | ShadowRoot implements TreeScope;
 37 | 
38 | 39 |
40 |
CSSStyleSheet(text, options) 41 |
42 | When called, execute these steps: 43 | 44 | 1. Construct a new {{CSSStyleSheet}} object sheet, 45 | with location set to null, 46 | no parent CSS style sheet, 47 | no owner node, 48 | no owner CSS rule, 49 | and a title set to the {{CSSStyleSheetInit/title}} attribute of options. 50 | Set sheet’s origin-clean flag. 51 | 2. If the {{CSSStyleSheetInit/media}} attribute of options is a string, 52 | create a MediaList object from the string 53 | and assign it as sheet’s media. 54 | Otherwise, assign the value of the attribute as sheet’s media. 55 | 3. If the {{CSSStyleSheetInit/alternate}} attribute of options is true, 56 | set sheet’s alternate flag. 57 | 4. If the {{CSSStyleSheetInit/disabled}} attribute of options is true, 58 | set sheet’s disabled flag. 59 | 5. Parse a stylesheet from {{text}}. 60 | If it returned a list of rules, 61 | assign the list as sheet’s CSS rules; 62 | otherwise, 63 | set sheet’s CSS rules to an empty list. 64 | 6. Return sheet. 65 | 66 |
moreStyleSheets 67 |
68 | Style sheets assigned to this attribute are part of the document CSS style sheets. 69 | They are ordered after the stylesheets in {{Document/styleSheets}}. 70 | 71 | Issue: Better name. 72 | 73 | Issue: Or do we want to include manually-added sheets in document.styleSheets, 74 | similar to how document.fonts mixes OM-created and manually-created fonts? 75 | Big difference is that ordering matters here, 76 | which makes dealing with the invariants much more annoying. 77 | (What happens if you manually add a sheet between two <link> sheets, 78 | then insert another <link> in the document between them? 79 | Does it go before or after your manually-added one? 80 | Or do we just make it illegal to manually add a sheet before an automatic sheet?) 81 |
82 | 83 | Applying Styles In All Contexts {#styles-in-all-contexts} 84 | =================== 85 | 86 |
87 | One of the major "misuses" of the ''>>>'' combinator 88 | is to apply "default styles" to a component wherever it lives in the tree, 89 | no matter how deeply nested it is inside of components. 90 | The use-case for this is to provide the equivalent of the user-agent stylesheet, 91 | but for custom elements 92 | (thus, the styles by necessity must come from the author). 93 | 94 | Unfortunately, this is extremely slow, 95 | and there's not a whole lot that can be done about that-- 96 | ''>>>'' combinators are slow by their nature. 97 | Note, though, that the UA and user stylesheets automatically apply in all shadows; 98 | it's only the author stylesheet that is limited to the context it's created in. 99 | 100 | (At this point, one might point out that this is already handled by just setting up styles during element construction. 101 | This doesn't help for cases where a component is purposely authored to be styled by the end-user; 102 | forcing users of components to go muck around in their components' source code is a non-starter.) 103 | 104 | One possible solution here is to add another origin, 105 | the "author default" origin, 106 | which sits between "user" and "author", 107 | and applies in all shadow roots automatically. 108 | We can add a list for these stylesheets, 109 | akin to document.styleSheets, 110 | and allow you to insert constructed stylesheets into it. 111 | Or maybe add an .origin attribute to CSSStyleSheet, defaulting to "author"? 112 | 113 | Maybe it only applies to the context you're in and descendant contexts? 114 | Need to investigate; 115 | probably bad to let a component apply automatic styles to the outer page via this mechanism. 116 |
117 | -------------------------------------------------------------------------------- /css-aliases/index.bs: -------------------------------------------------------------------------------- 1 |

CSS Extensions

2 | 12 | 13 | 16 | 17 |

18 | Introduction

19 | 20 | When authoring CSS, 21 | one often encounters significant repetition in certain features. 22 | For example, a given media query might be repeated in several places, 23 | or a selector meant to apply to all heading elements 24 | requires specifying '':matches(h1, h2, h3, h4, h5, h6)'' in every location that uses it. 25 | 26 | This repetition makes stylesheets more verbose and difficult to read, 27 | and also affects maintenance, 28 | as the author has to keep each repetition in sync when making any changes. 29 | 30 | This specification defines methods for extending several CSS features 31 | so that a long or repeatedly-used value can be given a short, memorable name instead, 32 | or a feature can be given a more complex definition controlled by a scripting language. 33 | This makes stylesheets easier to read, 34 | and more powerful in general, 35 | as authors can extend the feature-set of CSS themselves 36 | rather than waiting for standards bodies to define new features for them. 37 | 38 |

39 | Extension Names

40 | 41 | All extensions defined in this specification use a common syntax for defining their ”names”: 42 | the <> production. 43 | An <extension-name> is any identifier that starts with two dashes (U+002D HYPHEN-MINUS), 44 | like ''--foo'', or even exotic names like ''--'' or ''------''. 45 | The CSS language will never use identifiers of this form for any language-defined purpose, 46 | so it's safe to use them for author-defined purposes 47 | without ever having to worry about colliding with CSS-defined names. 48 | 49 |

50 | Custom Selectors

51 | 52 | A custom selector is defined with the ''@custom-selector'' rule: 53 | 54 |
@custom-selector = @custom-selector <> <> ;
55 | 56 | This defines a custom selector which is written as a pseudo-class with the given <>, 57 | and represents a '':matches()'' selector using the provided <> as its argument. 58 | 59 |
60 | For example, if an author wanted to easily refer to all heading elements in their HTML document, 61 | they could create an alias: 62 | 63 |
 64 | 			@custom-selector :--heading h1, h2, h3, h4, h5, h6;
 65 | 
 66 | 			:--heading { /* styles for all headings */ }
 67 | 			:--heading + p { /* more styles */ }
 68 | 			/* etc */
 69 | 		
70 |
71 | 72 |

73 | Script-based Custom Selectors

74 | 75 |
76 | This one's more complicated than MQs. 77 | Brian Kardell came up with a good proposal for evaluating selectors as JS functions that return a boolean, 78 | which had decent performance characteristics by specifying the qualities of the element it was based on 79 | (which determined when it would be called). 80 | 81 |
 82 | 		<script>
 83 | 		CSS.customSelector.set("_foo",
 84 | 			                   {"predicate": function(el){...},
 85 | 			                   	"matches": "a"});
 86 | 		</script>
 87 | 		
88 | 89 | "matches" is an optional selector specifying what subset of elements the custom selector is valid for. 90 | The selector is automatically false for elements that don't match, 91 | and the predicate isn't called. 92 | 93 | By default, the predicate is called whenever there's a mutation in an element that matches the "matches" selector, 94 | or one of its descendants. 95 | 96 | You should be able to suppress the auto-calling, 97 | and be able to trigger the predicate to run manually. 98 | That way you can use mutation listeners manually to only call the predicate when necessary. 99 | 100 | We should probably offer some sugar for filtering the list of mutations that trigger the predicate to be called. 101 | Maybe just a list of attributes that you'll be caring about? And/or tagnames? 102 | 103 | Maybe let the pseudo-class also accept an argument, 104 | and pass it (as a serialized string) as a second argument to the predicate. 105 | '':_foo'' would pass null, 106 | while '':_foo()'' would pass "". 107 |
108 | 109 |

110 | CSSOM

111 | 112 |

113 | Fill in. 114 | 115 |

116 | Custom Functions

117 | 118 |
119 | Interesting possibilities here. 120 | Definitely need some way to define custom functions in CSS. 121 | This would, for example, let people define whatever color function they want, 122 | such as implementing the HUSL color space. 123 | 124 | Definitely need a JS interface. 125 | What options are needed? 126 | 127 | Call time/frequency: 128 | 129 |
    130 |
  • 131 | Default should probably treat the function as a preprocessor, 132 | calling the JS function once per instance in the stylesheet 133 | and substituting in the returned value. 134 | 135 |
  • 136 | Should probably have an option to allow calling per element/instance combo, too. 137 | Gets called more as match results change. 138 |
139 | 140 | We can take some cues from my thoughts on a random() function. 141 | It needs per-instance, 142 | per-element&instance, 143 | and per "identifier", so you can reuse the same value in multiple spots. 144 | That last one can probably be handled manually by the JS, 145 | so we don't have to privilege a particular argument as an identifier. 146 | 147 | We'd need to provide the context in which it's used. 148 | Which property, for example. 149 | Should we allow them to be used in other places, 150 | or should we just define more contextual locations as we go? 151 | That is, should we allow custom-defined functions in @supports with this API, 152 | or should we add a .customSupports map? 153 | I suspect that individual cases will have their own useful contextual information, 154 | so it's better to specialize each instance of custom functions. 155 | 156 | How much can we do in pure CSS? 157 | Being able to substitute values depending on MQs or support queries would be useful. 158 | To get *real* use out of it, though, I suspect we'd need fuller support for conditionals, 159 | likely in the form of SASS's ''@if'' or something similar. 160 |
161 | 162 |

163 | Custom Selector Combinators

164 | 165 |
166 | Selectors are made of two pieces: 167 | simple selectors, 168 | and combinators. 169 | We should allow custom combinators too. 170 | 171 | This is JS-only, because it's transforming elements, not filtering them, 172 | and you can't express any useful transformations in pure CSS. 173 | 174 | You provide a function which, 175 | when given an element, 176 | produces a list of zero or more elements. 177 | 178 | For examples, with ''div /--foo/ span'', 179 | the CSS engine will match the first part of the selector 180 | and find all the div elements. 181 | It passes that list to the function registered for the --foo combinator, 182 | and expects to get a new list of elements returned. 183 | It then continues on its way, 184 | filtering that list to include only span elements, etc. 185 | 186 | A child combinator would be something like: 187 | 188 |
189 | 		CSS.customCombinator.set("--child", function(el) {
190 | 				return el.children;
191 | 			});
192 | 		
193 | 194 | Then ''div /--child/ span'' would be identical to ''div > span''. 195 | 196 | If we generalize a selector with a custom combinator to ''A /--custom/ B'', 197 | then the UA would automatically call the --custom function 198 | whenever new elements match ''A''. 199 | If elements stop matching ''A'', 200 | it won't bother; 201 | it'll just drop them from the result. 202 | 203 | Alternately, the function could take a list of elements 204 | (all the elements matching ''A'') 205 | and return a new list of elements. 206 | This would be a bit more complicated for the author, 207 | but would allow more variety in the types of combinators that could be defined, 208 | as you could define things that depend on the entire set of matched elements. 209 | For example, you could define ''A /nth 1/ B'' 210 | to give only the first element from the set of ''A'' matches. 211 | 212 | (Maybe we allow both variants, 213 | since the per-element one is easier to optimize and program against, 214 | but the per-set one allows some useful stuff.) 215 | 216 | Similarly to custom pseudo-classes, 217 | we'd allow arguments, 218 | with them parsed eagerly per-instance 219 | and passed to the combinator function. 220 | 221 | If we do the per-element combinator function, 222 | we could potentially cache the results, 223 | so that it never needs to be called again for the same element. 224 | Possibly have a flag that turns off this behavior, 225 | so that you're guaranteed to be called again. 226 |
227 | 228 |

229 | Custom At-Rules

230 | 231 |
232 | This one's even less developed, 233 | but it would be interesting to allow custom at-rules as well. 234 | It's definitely pure-JS as well. 235 | 236 | Unsure exactly what's best here. 237 | Possibly register a callback per rule, 238 | which is called with the prelude/contents of the at-rule? 239 | 240 | Should we do the callback approach, 241 | or just maintain a list of custom at-rules 242 | and let scripts parse them themselves? 243 | Unfortunately, the latter means we'd have to have a special mechanism to alert scripts 244 | when new at-rules get added or removed. 245 | 246 | For a lot of these at-rules, we may want a way to know when they're "applied"-- 247 | when, according to the built-in at-rules like @media and @supports, 248 | the rule would be applied. 249 |
250 | -------------------------------------------------------------------------------- /css-anchor-position/index.bs: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /css-apply-rule/index.bs: -------------------------------------------------------------------------------- 1 | 17 | 18 | 21 | 22 | Introduction {#intro} 23 | ===================== 24 | 25 | CSS custom properties enable authors to define reusable values, 26 | give them names, 27 | then invoke them throughout the stylesheet. 28 | This makes it easy to keep a page's theme consistent when changes are made, 29 | because the theming values are defined in a central place. 30 | 31 | But custom properties can hold more than just values-- 32 | they can also be used to hold sets of declarations. 33 | The ''@apply'' rule takes these sets of declarations and inlines them in another style rule, 34 | serving a purpose analogous to what the ''var()'' function does for individual values. 35 | 36 |
37 | 38 | There are many ways to apply sets of declarations to an element. 39 | In particular, the common way is to just create a style rule, 40 | and apply it to the desired elements via a selector. 41 | However, this requires the elements you wish to target to already have the right features for a selector, 42 | or else you have to alter your markup, 43 | or write a complex selector that targets them precisely with their varied features 44 | (and which needs to be maintained as you alter the page markup and change the selectors targetting those elements). 45 | This also requires careful management of specificity, 46 | as the rule has to interact with the existing rules styling the elements. 47 | 48 | The ''@apply'' rule allows this reuse to be inlined into the existing selectors you're already using, 49 | reducing the amount of effort required to keep your stylesheet consistent as things change in the page. 50 | It also avoids the need to manage specificity any more than you already do, 51 | as the properties are inlined alongside the existing properties, 52 | in your existing style rules. 53 |
54 | 55 | 56 | Defining Custom Sets of Properties {#defining} 57 | ============================================== 58 | 59 | To define a custom property set for use with ''@apply'', 60 | you simply use a custom property 61 | with a value of a {}-wrapped block of properties. 62 | 63 |
64 | For example, one might define a toolbar theme as a custom property set on the root element of the document, 65 | and use it on your toolbars: 66 | 67 |
 68 | 		:root {
 69 | 			--toolbar-theme: {
 70 | 				background-color: hsl(120, 70%, 95%);
 71 | 				border-radius: 4px;
 72 | 				border: 1px solid var(--theme-color late);
 73 | 			};
 74 | 			--toolbar-title-theme: {
 75 | 				color: green;
 76 | 			};
 77 | 		}
 78 | 
 79 | 		.toolbar {
 80 | 			@apply --toolbar-theme;
 81 | 		}
 82 | 		.toolbar > .title {
 83 | 			@apply --toolbar-title-theme;
 84 | 		}
 85 | 	
86 | 87 | Then, we can override the theme for toolbars inside of "warning" elements: 88 | 89 |
 90 | 		.warning {
 91 | 			--toolbar-title-theme: {
 92 | 				color: red;
 93 | 				font-weight: bold;
 94 | 			};
 95 | 		}
 96 | 	
97 | 98 | We don't have to worry about the internal structure of the toolbars, 99 | or precisely what internal elements use the styles. 100 | Simply overriding the custom property will automatically do the right thing. 101 |
102 | 103 |
104 | Note that custom property sets override each other wholly, 105 | rather than cascading together like colliding style rules do. 106 | 107 | For example, if these two style rules applied to the same element: 108 | 109 |
110 | 		.foo {
111 | 			color: red;
112 | 			background: white;
113 | 		}
114 | 		#bar {
115 | 			color: blue;
116 | 		}
117 | 	
118 | 119 | The ''#bar'' rule will win due to having a higher specificity, 120 | so its ''color:blue'' rule will apply to the element, 121 | but the ''background:white'' rule from the ''.foo'' rule also applies, 122 | since the ''#bar'' rule did not override 'background'. 123 | 124 | However, if these were instead defined as custom property sets: 125 | 126 |
127 | 		.foo {
128 | 			--my-theme: {
129 | 				color: red;
130 | 				background: white;
131 | 			};
132 | 		}
133 | 		#bar {
134 | 			--my-theme: {
135 | 				color: blue;
136 | 			};
137 | 		}
138 | 	
139 | 140 | Then when an element uses the '--my-theme' custom property set, 141 | it will receive only the ''color:blue'' declaration. 142 | The ''background:white'' declaration from the ''.foo'' rule is ignored completely, 143 | as its rule lost the specificity battle. 144 |
145 | 146 | Issue: Need some way to let you opt into cascading when you want it. 147 | 148 | Changes to Custom Property Processing {#processing-change} 149 | ---------------------------------------------------------- 150 | 151 | If the value of a custom property contains an ''@apply'' rule, 152 | the ''@apply'' rule must be valid according to the specified ''@apply'' grammar. 153 | If not, the custom property is invalid and must be ignored. 154 | 155 | ''@apply'' rules in custom property values are substituted at computed value time, 156 | identically to ''var()'' functions. 157 | 158 | For this purpose, an ''@apply'' rule is composed of a sequence of tokens 159 | starting with the ''@apply'' token, 160 | and ending at (and including) the first same-level semicolon, 161 | the end of the simple block the ''@apply'' token is in, 162 | or the end of the custom property's value. 163 | 164 | The computed value of a custom property 165 | 166 | Using Custom Sets of Properties: the ''@apply'' rule {#using} 167 | ============================================================= 168 | 169 | Once a custom property set has been declared, 170 | the ''@apply'' rule inlines it into a style rule. 171 | It's syntax is: 172 | 173 |
174 | 		@apply = @apply <> ;
175 | 	
176 | 177 | The ''@apply'' rule is only valid inside of a style rule. 178 | Using it outside of a style rule, 179 | or inside any other rule, 180 | is invalid and causes the ''@apply'' to be ignored. 181 | 182 |
183 | Here's a valid example of ''@apply'' usage: 184 | 185 |
186 | 		.foo {
187 | 			color: blue;
188 | 			@apply --foo-styles;
189 | 		}
190 | 	
191 | 192 | Here's several invalid example of ''@apply'' usage: 193 | 194 |
195 | 		.foo {
196 | 			color: blue;
197 | 		}
198 | 
199 | 		@apply --top-level-is-invalid;
200 | 	
201 | 202 |
203 | 		@keyframes foo {
204 | 			from { color: red; }
205 | 			to { color: blue; }
206 | 			@apply --this-is-not-a-style-rule;
207 | 		}
208 | 	
209 |
210 | 211 | For the purposes of the cascade, 212 | the ''@apply'' rule must be treated as if it were replaced by the properties 213 | in the custom property set that is the value of the custom property it references. 214 | 215 | Note: Within the CSSOM, the ''@apply'' rule is not replaced; 216 | examining the style rule will show it as having the ''@apply'' rule in its .childRules attribute, 217 | and the properties in the custom property set will not be visible in any way. 218 | 219 | If the custom property that the ''@apply'' rule references 220 | does not define a valid custom property set, 221 | the ''@apply'' rule is treated, for the purposes of the cascade, as if it were replaced with nothing. 222 | It is not invalid, however. 223 | (For example, it is not dropped from the CSSOM.) 224 | 225 | Processing ''@apply'' Rules {#processing} 226 | ========================================= 227 | 228 | To process ''@apply'' rules: 229 | 230 | 1. Inherit as normal. 231 | 2. Do var() substitution into custom properties only. 232 | 3. Do @apply substitution. 233 | 4. Re-do var() substitutions based on new property info. 234 | 235 | 236 | 237 | 238 | CSSOM {#cssom} 239 | ============== 240 | 241 |
242 | interface CSSApplyRule : CSSRule {
243 | 	attribute DOMString referencedProperty;
244 | };
245 | 
246 | 247 |
248 |
referencedProperty 249 |
250 | The custom property that the ''@apply'' rule is referencing. 251 | 252 | Upon setting, if the value is not a valid <>, 253 | ignore the set and throw a {{SyntaxError}}. 254 |
255 | 256 | Issue: Also, switch {{CSSStyleRule}} to inherit from {{CSSGroupingRule}}. 257 | -------------------------------------------------------------------------------- /css-cascade-control/index.bs: -------------------------------------------------------------------------------- 1 | 12 | 13 | Introduction {#intro} 14 | ===================== 15 | 16 | A number of CSS properties are list-valued (background, transition, etc) or set-valued (will-change, etc). 17 | These can be difficult to manage in an application written by several authors 18 | (or partially styled by indepedent libraries), 19 | or even when there's only a single author 20 | that just wants to style an element in multiple independent ways. 21 | 22 | For example, 23 | a particular class might do some 'transform' work, 24 | and thus want to set ''will-change: transform'', 25 | while another class does some 'opacity' changes, 26 | and thus wants to set ''will-change: opacity''. 27 | Done naively, if these two classes get set at the same time, 28 | one will win over the other, 29 | and 'will-change' will only reflect one of the values. 30 | 31 | Currently, the only way to get around this is to explicitly handle the collision, 32 | manually applying ''will-change: transform, opacity'' when the element matches both classes. 33 | This sort of explicit collision-handling is unmaintainable, 34 | and can quickly grow out of control if more cases are added, 35 | as each one increases the number of combinations to be handled combinatorially. 36 | (A third class means you need to explicitly handle the 1+2, 1+3, 2+3, and 1+2+3 cases. 37 | A fourth class means handling 11 different combinations!) 38 | 39 | In this spec we propose a few possible mechanisms to handle these situations more elegantly. 40 | 41 | Cascade Declarations 42 | ==================== 43 | 44 | During the cascade process, 45 | multiple declarations of the same property on a given element 46 | are sorted in specificity order 47 | to produce the output of the cascade, 48 | and then only the last value 49 | (the one with highest specificity) 50 | is actually used as the value of that property on the element. 51 | 52 | A cascade modifier is a modifier on a property name 53 | that makes the property's value depend partially on the 54 | previous cascaded value: 55 | the value for that property that comes before the current value 56 | (that is, is lower specificity) 57 | in the output of the cascade. 58 | 59 | For any set-valued property with a name 'set-prop', 60 | the following cascade modifiers exist: 61 | 62 | : set-prop+ 63 | :: Represents the union of its value with the previous cascaded value. 64 | : set-prop- 65 | :: Represents the difference of the previous cascaded value with its value. 66 | (That is, the previous cascaded value, 67 | minus the current values.) 68 | : set-prop{} 69 | :: Represents the intersection its value with the previous cascaded value. 70 | 71 | Issue: This involves defining the "unit" of each set-valued property 72 | (for example, in 'will-change' each keyword is a "unit"), 73 | and ensuring that all of them have a "null" value 74 | (like ''will-change/none''). 75 | 76 | For any list-valued property with a name 'list-prop', 77 | the following cascade modifiers exist: 78 | 79 | : list-prop+ 80 | :: Represents the current value appended to the end of the previous cascaded value. 81 | : +list-prop 82 | :: Represents the current value prepended to the start of the previous cascade value. 83 | 84 | Issue: The "unit" of list-valued properties are much easier to define; 85 | for all but some legacy properties like 'counter-reset', 86 | it's just splitting on commas. 87 | 88 |
89 | Define that, for all of these, 90 | we interpret the property as normal first, 91 | then split it into units for merging; 92 | this isn't variable-style concatenation. 93 | 94 | That is, the following does not define a 2px-offset blue shadow: 95 | 96 |
 97 | 	.foo {
 98 | 		box-shadow+: 2px 2px;
 99 | 	}
100 | 	.foo {
101 | 		box-shadow+: blue;
102 | 	}
103 | 	
104 | 105 | As each property is still interpreted as a property, 106 | the first is interpreted the same as ''box-shadow: 2px 2px;'' 107 | (specifying a single drop-shadow set to ''currentcolor''), 108 | while the second is simply invalid. 109 |
110 | 111 | Managing Order Explicitly with Variables 112 | ---------------------------------------- 113 | 114 | Using cascade modifiers directly can achieve a number of useful, simple effects, 115 | but direct usage doesn't allow a number of common use-cases. 116 | For example, you can't override a particular cascade modifier with a more specific rule. 117 | 118 |
119 | For example, take the following: 120 | 121 |
122 | 	div {
123 | 		background-image: url(base.jpg);
124 | 	}
125 | 	div.foo {
126 | 		+background-image: url(one.jpg);
127 | 	}
128 | 	div.foo.bar {
129 | 		+background-image: url(two.jpg);
130 | 	}
131 | 	
132 | 133 | This does *not* override the ''one.jpg'' with ''two.jpg''; 134 | for an element matching all three rules, 135 | it produces an equivalent effect to ''background-image: url(two.jpg), url(one.jpg), url(base.jpg);''. 136 | 137 | In other words, so long as the element matches the ''div.foo'' rule, 138 | the value will contain ''url(one.jpg)''. 139 | 140 | (You can override the entire thing 141 | with a higher-specificity declaration 142 | that doesn't use a cascade modifier, 143 | but that overrides the ''base.jpg'' too. 144 | There's no way to directly override just 145 | one of the modified declarations.) 146 |
147 | 148 | The preferred pattern to achieve this is to use a custom property: 149 | 150 |
151 | To fix the previous example, 152 | so ''base.jpg'' always applies 153 | but ''one.jpg'' and ''two.jpg'' apply based on specificity, 154 | you can write: 155 | 156 |
157 | 	div {
158 | 		background-image: url(base.jpg);
159 | 		+background-image: var(--upper-background) !important;
160 | 	}
161 | 	div.foo {
162 | 		--upper-background: url(one.jpg);
163 | 	}
164 | 	div.foo.bar {
165 | 		--upper-background: url(two.jpg);
166 | 	}
167 | 	
168 |
169 | 170 |
171 | Why not just use variables by themselves? Why the extra complexity? 172 | 173 | The above example could instead be written only using variables, 174 | with no cascade controls: 175 | 176 |
177 | 	div {
178 | 		background-image: var(--upper-background, none), url(base.jpg);
179 | 	}
180 | 	div.foo {
181 | 		--upper-background: url(one.jpg);
182 | 	}
183 | 	div.foo.bar {
184 | 		--upper-background: url(two.jpg);
185 | 	}
186 | 	
187 | 188 | While this works in simple situations, 189 | it's less useful as more things interact. 190 | It requires that 'background-image' never be disturbed; 191 | if anything else attempts to set background-image, 192 | it'll wipe out the variable use. 193 | The cascade modifier approach, 194 | on the other hand, 195 | maintains the images set by the variables 196 | even if other code sets the 'background-image' property. 197 |
198 | 199 | cascade() Function 200 | ================== 201 | 202 |
203 | More directly but slightly more complex, 204 | we could add a cascade() function 205 | that's accepted by all set-valued and list-values properties 206 | as a whole "unit". 207 | By default it subs in the previous cascaded value for itself, 208 | but for set-valued things it needs to offer more functionality to do difference/intersection. 209 |
210 | -------------------------------------------------------------------------------- /css-color/images/color-picker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tabatkins/specs/c492931b1458ff5dc84a814805093763fcf3e3bd/css-color/images/color-picker.png -------------------------------------------------------------------------------- /css-content-size/index.bs: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | 22 | Introduction {#intro} 23 | ===================== 24 | 25 | When [=size containment=] is applied to an element, 26 | it lays out as if it were completely empty, 27 | ignoring any child content it might have. 28 | This directive lets the layout engine "scope" sizing-related layout changes; 29 | the UA knows, for 100% certain, 30 | that no changes in the contents of the element 31 | will have any effect on the element's own size, 32 | and so the UA can immediately skip redoing layout for the element or its ancestors 33 | without having to rely on heuristics. 34 | 35 | However, making the element completely empty isn't always desirable; 36 | it can allow the element to shrink down to zero size. 37 | Setting an explicit 'width'/'height' (or 'min-width'/'min-height') on the element can prevent this, 38 | but that can have its own possibly unwanted implications on layout, 39 | making it act differently than an ordinary element with children would in the same situation. 40 | 41 | The 'content-size' property, 42 | when set on an element with [=size containment=], 43 | causes the element to pretend to have a single, fixed-size child of the specified size, 44 | rather than pretending to be completely empty. 45 | This accomplishes the same "hiding" of layout dirtying that [=size containment=] normally does, 46 | but allows the author to provide a more useful "default size" for the element, 47 | and avoid accidentally letting the element shrink down to a useless size. 48 | 49 | 50 | The 'content-size' Property {#content-size} 51 | =========================================== 52 | 53 |
54 | Name: content-size
55 | Value: none | <>{1,2}
56 | Initial: none
57 | Applies To: elements with [=size containment=]
58 | Inherited: no
59 | Computed Value: the specified keyword, or a pair of absolutized <>s
60 | 
61 | 62 | The 'content-size' property specifies whether a container with [=size containment=] 63 | should pretend to be empty for layout purposes, 64 | or pretend to have a single child of the specified size. 65 | Its values are: 66 | 67 |
68 | : none 69 | :: If the element has [=size containment=] 70 | and is a non-replaced element, 71 | it lays out as if it were empty. 72 | 73 | If the element is a replaced element, 74 | its intrinsic width and height are both zero. 75 | 76 | : <>{1,2} 77 | :: If the element has [=size containment=] 78 | and is a non-replaced element, 79 | it lays out as if it had a single child element, 80 | with the child‘s 'width' property set to the first <>, 81 | and its 'height' property set to the second <> 82 | (defaulting to the first if only one is specified). 83 | 84 | If the element is a replaced element, 85 | its intrinsic width is the first <>, 86 | and its intrinsic height is the second <> 87 | (defaulting to the first if only one is specified). 88 |
89 | 90 | If the element does not have [=size containment=], 91 | this property has no effect. 92 | 93 | Issue: Currently this takes only <>s, 94 | because afaict % width/height on the pretend child 95 | will either resolve to zero, 96 | or have no effect on the container's size anyway. 97 | Are there any exceptions that would justify <>? -------------------------------------------------------------------------------- /css-extend-rule/index.bs: -------------------------------------------------------------------------------- 1 | 14 | 15 | 18 | 19 | Introduction {#intro} 20 | ===================== 21 | 22 | Sometimes, when designing a page, 23 | an author might create some styles for a given type of element, 24 | such as "error" messages. 25 | Later, they might realize they need to create a "subclass" of the first type, 26 | such as a "serious error" message, 27 | which is styled the same way as "error", 28 | but with a few tweaks to make it more distinctive. 29 | Currently, CSS does not have a good way to handle this. 30 | 31 | If the author has control over the HTML, 32 | they can declare that every element with a class of "serious-error" 33 | must also have a class of "error". 34 | This, however, is error-prone-- 35 | it's easy to forget to add the "error" class to an element, 36 | causing confusing styling issues, 37 | and any scripting that creates or manipulates error elements 38 | has to know to maintain the states properly 39 | (for example, any time they remove the "error" class, 40 | they have to remember to check for and remove "serious-error" as well). 41 | 42 | Alternately, this can be handled in the CSS-- 43 | every time a style rule contains a ''.error'' selector, 44 | the selector can be duplicated with ''.serious-error'' replacing it. 45 | This, too, is error-prone: 46 | it's easy for typos or inattention to cause the duplicated selectors to drift apart, 47 | and it's easy, when adding new ''.error'' rules, 48 | to forget to duplicate the selector. 49 | 50 | The ''@extend'' rule, defined in this specification, 51 | fixes this common issue. 52 | It allows an author to declare that certain elements, 53 | such as everything matching ''.serious-error'', 54 | must act as if they had the necessary features to match another selector, 55 | such as ''.error''. 56 | 57 |
58 | For example, the following code declares that ''.serious-error'' elements should act as if they were ''.error'' elements as well: 59 | 60 |
 61 | 	.error {
 62 | 		color: red;
 63 | 		border: thick dotted red;
 64 | 	}
 65 | 
 66 | 	.serious-error {
 67 | 		@extend .error;
 68 | 		font-weight: bold;
 69 | 	}
 70 | 	
71 | 72 | Now an element like <div class=serious-error> will have red text and border, 73 | just like elements with class=error, 74 | but will also use bold text. 75 |
76 | 77 | This allows authors to write simple HTML, 78 | applying either class=error or class=serious-error to elements as appropriate, 79 | and write simple CSS, 80 | creating style rules that just mention ''.error'' or ''.serious-error'', 81 | secure in the knowledge that the former rules will also apply to serious errors. 82 | 83 | The ''@extend'' Rule {#extend-rule} 84 | =================================== 85 | 86 | The @extend rule declares 87 | that a matched element must act as if it had the necessary qualities to match another specified selector. 88 | Its syntax is: 89 | 90 |
@extend <>;
91 | 92 | The ''@extend'' rule is only allowed inside of style rules. 93 | In any other context, an ''@extend'' rule is invalid. 94 | An ''@extend'' rule modifies the way that selector matching works 95 | for the elements matched by the style rule the ''@extend'' selector is inside of, 96 | known as the extended elements for that rule. 97 | 98 | The argument to ''@extend'' is the extension selector. 99 | The rule's extended elements must, 100 | for the purpose of determining if selectors match them, 101 | act as if they had the necessary features/state/etc to match the extension selector, 102 | in addition to their pre-existing features/state/etc. 103 | 104 |
105 | For example, in the following code: 106 | 107 |
108 | 	.serious-error {
109 | 		@extend .error;
110 | 	}
111 | 	
112 | 113 | All elements matching the ''.serious-error'' selector 114 | must act as if they also had an "error" class 115 | for the purpose of matching selectors, 116 | regardless of what their actual set of classes is. 117 |
118 | 119 | Issue: Should this only affect selectors in CSS, 120 | or should it affect all APIs using selectors? 121 | Dunno which is saner for browsers; 122 | probably all selector-based APIs. 123 | Do other query APIs, like {{getElementsByTagName()}}, 124 | rely on the same machinery? 125 | If so, should we generalize this to allow host languages to declare arbitrary querying APIs to be "selector-ish"? 126 | 127 | The ''@extend'' rule only affects the extended elements 128 | as long as the rule it's inside of matches them. 129 | 130 |
131 | For example, if the rule containing ''@extend'' is in an ''@media'' block: 132 | 133 |
134 | 	.error {
135 | 		color: red;
136 | 	}
137 | 
138 | 	@media (width > 600px) {
139 | 		.serious-error {
140 | 			@extend .error;
141 | 			font-weight: bold;
142 | 		}
143 | 
144 | 		.error {
145 | 			width: 100%;
146 | 		}
147 | 	}
148 | 	
149 | 150 | Then the ''.serious-error'' elements only act as if they have an error class 151 | when the page's width is greater than ''600px''. 152 |
153 | 154 |
155 | Note that the extension selector can specify more than classes. 156 | For example, in the following code: 157 | 158 |
159 | 	.my-button {
160 | 		@extend button;
161 | 	}
162 | 	
163 | 164 | Any elements with class=my-button receive the same styling as actual button elements, 165 | as if they had a tagname of button in addition to their normal tagname. 166 | 167 | Similarly, in the following code: 168 | 169 |
170 | 	.perma-pressed-button {
171 | 		@extend .button:active;
172 | 	}
173 | 	
174 | 175 | Any ''.perma-pressed'' elements are styled as if they were '':active'', 176 | so that any styling applied to "pressed" buttons via '':active'' rules applies to them as well. 177 |
178 | 179 |
180 | The ''@extend'' rule effectively adds qualities to an element, 181 | so that it matches other rules. 182 | The selector used to apply the ''@extend'' rule has no effect on this. 183 | For example, in the following code: 184 | 185 |
186 | 	.red-text { color: red; }
187 | 	.blue-text { color: blue; }
188 | 
189 | 	#sidebar { @extend .red-text; }
190 | 	div { @extend .blue-text; }
191 | 	
192 | 193 | A naive author looking at the code and wondering how a <div id=sidebar> element would be styled 194 | might assume that it gets red text, 195 | as an ID selector is used to ''@extend'' the ''.red-text'' class, 196 | versus a much less specific tagname selector. 197 | However, this is wrong-- 198 | the element gets blue text, 199 | as the ''.red-text'' and ''.blue-text'' rules have equal specificity, 200 | and the ''.blue-text'' rule appears later in the stylesheet. 201 | The specificity of the rules that caused the element to match ''.red-text'' or ''.blue-text'' are irrelevant here. 202 | 203 | While this may in some cases be confusing, 204 | it can also be a great benefit in some cases. 205 | For example, 206 | an author can define a lot of styles with simple, one-class (or one placeholder selector) rules, 207 | effectively ignoring specificity entirely, 208 | then apply them via longer, much more specific selectors, 209 | using ''@extend'' to invoke the behavior of the simpler rules. 210 | This can allow an author to avoid many of the specificity problems of using IDs in rules, for example. 211 |
212 | 213 | ''@extend'' Chaining {#extend-chaining} 214 | --------------------------------------- 215 | 216 | Multiple ''@extend'' rules can be "chained", 217 | with one rule adding certain qualities to an element, 218 | which cause another style rule containing an ''@extend'' to match. 219 | 220 | Note: This falls out of the definition automatically. 221 | It is called out separately for clarity, 222 | not because it's a separate feature that needs to be specifically defined. 223 | 224 |
225 | For example, 226 | the following code using ''@extend'': 227 | 228 |
229 | 	.error {
230 | 		color: red;
231 | 	}
232 | 
233 | 	.serious-error {
234 | 		@extend .error;
235 | 		font-weight: bold;
236 | 	}
237 | 
238 | 	.super-serious-error {
239 | 		@extend .serious-error;
240 | 		animation: flashing 1s infinite;
241 | 	}
242 | 	
243 | 244 | is equivalent to the following code without ''@extend'': 245 | 246 |
247 | 	.error, .serious-error, .super-serious-error {
248 | 		color: red;
249 | 	}
250 | 
251 | 	.serious-error, .super-serious-error {
252 | 		font-weight: bold;
253 | 	}
254 | 
255 | 	.super-serious-error {
256 | 		animation: flashing 1s infinite;
257 | 	}
258 | 	
259 |
260 | 261 | 262 | The Placeholder Selector ''%foo'' {#placeholder} 263 | ================================================ 264 | 265 | The ''@extend'' rule originates in CSS preprocessors, such as SASS. 266 | Experience with those tools shows that it's often useful to define generic, "functional" sets of styles 267 | that don't apply to any elements directly, 268 | then use ''@extend'' to give that behavior to semantic classnames 269 | which are more meaningful within their project. 270 | 271 |
272 | For example, the "media block" is a common functional sort of styling, 273 | originating from OOCSS, 274 | that describes a box with a picture on one side and text on the other. 275 | It might be used like the following: 276 | 277 |
278 | 	.media-block {
279 | 		overflow: auto;
280 | 	}
281 | 	.media-block > img {
282 | 		float: left;
283 | 	}
284 | 	...
285 | 
286 | 	.image-post {
287 | 		@extend .media-block;
288 | 		... /* additional styles to tweak the display */
289 | 	}
290 | 	
291 |
292 | 293 | However, this also carries the possibility of confusion. 294 | In the above example, ''.media-block'' is just used to give a name to the pattern, 295 | so that other rules can ''@extend'' it. 296 | It's not meant to be used in a document-- 297 | there shouldn't be any elements with class=media-block-- 298 | but this isn't obvious from the code. 299 | It's easy for later maintainers of the file to accidentally use ''.media-block'' directly on an element, 300 | and modify it for their own uses 301 | (after all, if they search the codebase, they'll find no elements on the page using it!), 302 | perhaps accidentally breaking elements using it in ''@extend''. 303 | 304 | To avoid situations like this, 305 | and make it more clear that one is developing a "generic"/"functional"/"structural" set of styles, 306 | the placeholder selector can be used. 307 | Its syntax is similar to a class selector, 308 | but is prefixed by a ''%'' (U+0025 PERCENT SIGN) 309 | rather than a period. 310 | 311 |
312 | The previous example could be more clearly written using a placeholder selector: 313 | 314 |
315 | 	%media-block {
316 | 		overflow: auto;
317 | 	}
318 | 	%media-block > img {
319 | 		float: left;
320 | 	}
321 | 	...
322 | 
323 | 	.image-post {
324 | 		@extend %media-block;
325 | 	}
326 | 	
327 |
328 | 329 | Host languages must not provide any way for an element to match a placeholder selector; 330 | the only way for an element to match one is by using an ''@extend'' rule. 331 | This ensures that no element will ever directly match the styles using one, 332 | even by accident, 333 | and it can't be accidentally reused for an element directly. 334 | 335 | Placeholder selectors have the same specificity as class selectors. 336 | 337 | Issue: Or should they have slightly less, so concrete classes can reliably override? 338 | This would mean putting a fourth number into the specificity 3-tuple. 339 | 340 | Acknowledgements {#acks} 341 | ======================== 342 | 343 | The editor would like to thank the following people: 344 | 345 | * Nicole Sullivan for first coming up with the idea for @extend. 346 | * Chris Eppstein and Natalie Weizenbaum 347 | for developing and programming the modern incarnation of ''@extend'' in Sass. 348 | * The Sass community, for using ''@extend'' so extensively that its lack in CSS couldn't be ignored. 349 | -------------------------------------------------------------------------------- /css-filter-rule/index.bs: -------------------------------------------------------------------------------- 1 | 12 | 13 | Introduction {#intro} 14 | ===================== 15 | 16 | This spec is a very rough draft. I'm not gonna try for precise wording here; you'll get the gist. Details can be nailed down when we take this seriously. 17 | 18 | Defining Complex Filters in CSS: the ''@filter'' rule {#filter-rule} 19 | ==================================================================== 20 | 21 | The syntax of an ''@filter'' rule is: 22 | 23 |
 24 | @filter = @filter <> { <> }
 25 | 
26 | 27 | The ''@filter'' rule accepts a handful of descriptors, 28 | described in later subsections, 29 | but is mostly filled by other filter primitive rules, 30 | such as ''@blend''. 31 | The presense of unknown descriptors, 32 | or at-rules other than filter primitive rules, 33 | are invalid and cause those descriptors/rules to be ignored, 34 | but do not make the ''@filter'' rule invalid. 35 | 36 | Note: Equivalents of filterUnits and primitiveUnits are intentionally not included. 37 | The *Units properties are a weird SVG-ism caused by the fact that they only have two units - integers and percentages. 38 | CSS doesn't need this. 39 | 40 | Filter Errors {#filter-errors} 41 | ------------------------------ 42 | 43 | Some mistakes in defining a ''@filter'' rule or its contents can cause a filter error. 44 | When a ''@filter'' rule or its contents cause a filter error, 45 | the ''@filter'' rule represents the null filter, 46 | regardless of what else it specifies. 47 | 48 | The null filter has no effect-- 49 | its output is exactly equivalent to its input. 50 | 51 | Referring to ''@filter'' Rules {#refs} 52 | -------------------------------------- 53 | 54 | Issue: I'm currently requiring filter names to be <>s - can we just accept that as an ident in the 'filter' property? 55 | Or maybe we can relax that and just prevent filter names from being "none" or the global keywords, 56 | like ''@counter-style'' does, ugh. 57 | 58 | Sizing the Filter Region: the '@filter/position' and '@filter/size' descriptors {#filter-size} 59 | ---------------------------------------------------------------------------------------- 60 | 61 |
 62 | Name: position
 63 | For: @filter
 64 | Value: <>
 65 | Initial: -10% -10%
 66 | 
67 | 68 |
 69 | Name: size
 70 | For: @filter
 71 | Value: <<'background-size'>>
 72 | Initial: 120% 120%
 73 | 
74 | 75 | Controlling the Resolution of a Filter: the '@filter/resolution' descriptor {#filter-resolution} 76 | ----------------------------------------------------------------------------------------------- 77 | 78 |
 79 | Name: resolution
 80 | For: @filter
 81 | Value: auto | <>{1,2}
 82 | Initial: auto
 83 | 
84 | 85 | 86 | Using Variable References in ''@filter'' Descriptors {#vars} 87 | ============================================================ 88 | 89 | All of the at-rules defined in this specification allow variable references 90 | (the ''var()'' function) 91 | in their descriptors, 92 | in addition to whatever else their syntax states. 93 | During parsing, these are interpreted identically to the use of ''var()'' in CSS properties-- 94 | they "turn off" syntax validation during parsing, 95 | reverting the descriptor to containing an arbitrary token stream. 96 | 97 | Variables are substituted at time-of-use, 98 | based on the values of custom properties on the element referencing the ''@filter'' rule. 99 | 100 | Note: Thus, a single ''@filter'' rule can have its variables filled in with multiple different values, 101 | if it's referenced by multiple different elements. 102 | Each reference is a separate "instance" for this purpose. 103 | 104 | Note: This should also work for ''@apply'' in the same way. 105 | Need to generalize/define the concept of "variable reference" to include that. 106 | 107 | 108 | Filter Primitive Rules {#filter-primitive} 109 | ========================================== 110 | 111 | The filter primitive rules are a set of at-rules that define the behavior of a filter. 112 | They're only valid within the top-level of an ''@filter'' rule; 113 | if found anywhere else, they're invalid and must be ignored. 114 | 115 | Common Descriptors {#common} 116 | ---------------------------- 117 | 118 | All filter primitive rules accept the following descriptors, 119 | and interpret them in the same way: 120 | 121 |
122 | Name: position
123 | For: @blend
124 | Value: <>
125 | Initial: -10% -10%
126 | 
127 | 128 |
129 | Name: size
130 | For: @blend
131 | Value: <<'background-size'>>
132 | Initial: 120% 120%
133 | 
134 | 135 | These two are interpreted the same as for ''@filter''. 136 | 137 |
138 | Name: in
139 | For: @blend
140 | Value: auto | source-graphic | source-alpha | background-image | background-alpha | fill-paint | stroke-paint | <>
141 | Initial: auto
142 | 
143 | 144 | The 'in' descriptor specifies what the input to the filter is. 145 | Values are defined as follows: 146 | 147 |
148 |
auto 149 |
150 | If this is specified on the first filter primitive rule in a ''@filter'' rule, 151 | it behaves as ''source-graphic''. 152 | 153 | Otherwise, the input is the output of the previous filter primitive rule in the ''@filter'' rule. 154 | 155 |
<> 156 |
157 | Refers to the nearest preceding filter primitive rule which specified the same string as its 'result' descriptor. 158 | 159 | If there is no such preceding filter primitive rule, 160 | this causes a filter error. 161 | 162 |
etc 163 |
164 | Same as SVG. 165 |
166 | 167 |
168 | Name: result
169 | For: @blend
170 | Value: none | <>
171 | Initial: none
172 | 
173 | 174 | The 'result' descriptor gives the output of a filter primitive rule a name, 175 | so it can be referred to by later filter primitive rules in the same ''@filter'' rule. 176 | 177 | Note: In most common cases it is not necessary to specify this, 178 | as the value of one filter primitive rule 179 | is fed directly into the following filter primitive rule by default. 180 | 181 | Compositing Two Images: the ''@blend'' filter primitive rule {#at-blend} 182 | ======================================================================== 183 | 184 | The @blend rule composites two inputs together into a single output. 185 | 186 |
187 | Name: in2
188 | For: @blend
189 | Value: <<'in'>>
190 | Initial: auto
191 | 
192 | 193 | The ''@blend'' rule requires two inputs. 194 | The '@blend/in2' descriptor specifies the second input. 195 | 196 |
197 | Name: mode
198 | For: @blend
199 | Value: normal | multiply | screen | darken | lighten
200 | Initial: normal
201 | 
202 | 203 | The '@blend/mode' descriptor specifies how the two inputs are to be blended together. 204 | The values are defined in the SVG spec. 205 | -------------------------------------------------------------------------------- /css-font-display/index.bs: -------------------------------------------------------------------------------- 1 | 14 | 15 | Introduction {#intro} 16 | ===================== 17 | 18 | When using downloadable webfonts via ''@font-face'', 19 | the user agent needs to know what to do while the font is actively loading. 20 | Most web browsers have adopted some form of timeout: 21 | 22 | 23 | 24 | 25 | 30 | 31 | 36 | 41 | 46 | 51 |
Browser 26 | Timeout 27 | Fallback 28 | Swap 29 |
Chrome 35+ 32 | 3 seconds 33 | yes 34 | yes 35 |
Opera 37 | 3 seconds 38 | yes 39 | yes 40 |
Firefox 42 | 3 seconds 43 | yes 44 | yes 45 |
Internet Explorer 47 | 0 seconds 48 | yes 49 | yes 50 |
Safari 52 | 3 seconds 53 | yes 54 | yes 55 |
56 | 57 | * Chrome and Firefox have a 3 second timeout after which the text is shown with the fallback font. 58 | Eventually, a swap occurs: 59 | the text is re-rendered with the intended font once it becomes available. 60 | * Internet Explorer has a 0 second timeout which results in immediate text rendering: 61 | if the requested font is not yet available, 62 | fallback is used, 63 | and text is rerendered later once the requested font becomes available. 64 | 65 | While these default behaviors are reasonable, 66 | they're unfortunately inconsistent across browsers. 67 | Worse, no single approach is sufficient to cover the range of use-cases 68 | required by modern user-experience– and performance–conscious applications. 69 | 70 | The Font Loading API [[CSS-FONT-LOADING-3]] allows a developer to override some of the above behaviors, 71 | but that requires scripting, 72 | a non-trivial amount of effort, 73 | and ultimately doesn't provide sufficient hooks to cover all reasonable cases. 74 | Additionally, 75 | the developer needs to either inline the loading script into their page 76 | or load an external library, 77 | introducing additional network latency before the fonts can be loaded 78 | and delaying text rendering. 79 | 80 | Design/performance-conscious web developers have a good sense for the relative importance of a given web font for the intended user experience. 81 | This specification provides them the ability to control font timeout and rendering behavior. 82 | Specifically, it lets developers: 83 | 84 | * Define the font display policy when text is ready to be painted: block, or paint with fallback. 85 | * Define the font display policy once the desired font is available: rerender text with the new font, or leave it with the fallback. 86 | * Define custom timeout values for each font. 87 | * Define custom display and timeout policies per element. 88 | 89 | The Font Display Timeline {#timeline} 90 | ===================================== 91 | 92 | At the moment the user agent first attempts to use a given downloaded font face on a page, 93 | the font face's font download timer is started. 94 | This timer advances through three periods of time associated with the font face-- 95 | the block period, the swap period, and the failure period-- 96 | which dictate the rendering behavior of any elements using the font face: 97 | 98 | * The first period is the font block period. 99 | During this period, 100 | if the font face is not loaded, 101 | any element attempting to use it must instead render with an invisible fallback font face. 102 | If the font face successfully loads during the block period, 103 | the font face is then used normally. 104 | * The second period, occuring immediately after the block period, 105 | is the font swap period. 106 | During this period, 107 | if the font face is not loaded, 108 | any element attempting to use it must instead render with a fallback font face. 109 | If the font face successfully loads during the swap period, 110 | the font face is then used normally. 111 | * The third period, occuring immediately after the swap period, 112 | is the font failure period. 113 | If the font face is not yet loaded when this period starts, 114 | it's marked as a failed load, 115 | causing normal font fallback. 116 | Otherwise, the font face is used normally. 117 | 118 | To render with a fallback font face for a given element, 119 | the user agent must find the first font face specified in the element's 'font-family!!property' list 120 | which is already loaded, 121 | and use that for rendering text. 122 | Doing this must not trigger loads of any of the fallback fonts. 123 | 124 | To render with an invisible fallback font face for a given element, 125 | find a font face as per "render with a fallback font face". 126 | Create an anonymous font face with the same metrics as the selected font face 127 | but with all glyphs "invisible" (containing no "ink"), 128 | and use that for rendering text. 129 | Doing this must not trigger loads of any of the fallback fonts. 130 | 131 | Issue: ''fallback'' and ''optional'' can result in some faces in a family being used 132 | while others are required to fallback, 133 | giving a "ransom note" look. 134 | Perhaps require that all fonts in a family have the same behavior (all swapped in, or all fallback)? 135 | See also the @font-feature-values for controlling the behavior on a font family basis. 136 | 137 | 138 | Controlling Font Display Per Font-Face: the ''@font-face/font-display'' descriptor {#font-display-desc} 139 | =========================== 140 | 141 | The '@font-face/font-display' descriptor for ''@font-face'' 142 | determines how a font face is displayed, 143 | based on whether and when it is downloaded and ready to use. 144 | 145 |
146 | Name: font-display
147 | Value: auto | block | swap | fallback | optional
148 | Initial: auto
149 | For: @font-face
150 | 
151 | 152 | Note: For all of these values, 153 | user agents may use slightly different durations, 154 | or more sophisticated behaviors that can't be directly expressed in the 'font-display' syntax, 155 | in order to provide more useful behavior for their users. 156 | They may also provide the ability for users to override author-chosen behavior 157 | with something more desirable; 158 | for example, forcing all fonts to have a ''0s'' block period. 159 | 160 |
161 |
auto 162 |
163 | The font display policy is user-agent-defined. 164 | 165 | Note: Many browsers have a default policy similar to that specified by ''block''. 166 | 167 |
block 168 |
169 | Gives the font face a short block period 170 | (''3s'' is recommended in most cases) 171 | and an infinite swap period. 172 | 173 | Note: In other words, the browser draws "invisible" text at first if it's not loaded, 174 | but swaps the font face in as soon as it loads. 175 | 176 | This value must only be used when rendering text in a particular font is required for the page to be usable. 177 | It must only be used for small pieces of text. 178 | 179 |
180 | For example, badly designed "icon fonts" might associate a "⎙" (print) icon 181 | with an unrelated character like "C", 182 | so if the text is displayed with a fallback font instead 183 | there will be confusing letters scattered around the page 184 | rather than the desired icon. 185 | In this case, temporary blank spots are better than using a fallback font. 186 | 187 | (However, the fallback font is used eventually, 188 | as having confusing letters scattered around the page 189 | is better than having links and such never show up at all.) 190 |
191 | 192 |
swap 193 |
194 | Gives the font face a ''0s'' block period 195 | and an infinite swap period. 196 | 197 | Note: In other words, the browser draws the text immediately with a fallback if the font face isn't loaded, 198 | but swaps the font face in as soon as it loads. 199 | 200 | This value should only be used when rendering text in a particular font is very important for the page, 201 | but rendering in any font will still get a correct message across. 202 | It should only be used for small pieces of text. 203 | 204 |
205 | For example, 206 | if a website has a custom font for rendering their logo, 207 | rendering that logo correctly is fairly important for branding purposes, 208 | but displaying the logo in any font will at least get the point across without confusion. 209 |
210 | 211 |
fallback 212 |
213 | Gives the font face an extremely small block period 214 | (''100ms'' or less is recommended in most cases) 215 | and a short swap period 216 | (''3s'' is recommended in most cases). 217 | 218 | Note: In other words, the font face is rendered with a fallback at first if it's not loaded, 219 | but it's swapped in as soon as it loads. 220 | However, if too much time passes, 221 | the fallback will be used for the rest of the page's lifetime instead. 222 | 223 | This value should be used for body text, 224 | or any other text where the use of the chosen font is useful and desired, 225 | but it's acceptable for the user to see the text in a fallback font. 226 | This value is appropriate to use for large pieces of text. 227 | 228 |
229 | For example, 230 | in large pieces of body text, 231 | it's most important just to get the text rendered quickly, 232 | so the user can begin to read as quickly as possible. 233 | Further, once the user has started reading, 234 | they shouldn't be disturbed by the text suddenly "shifting" 235 | as a new font is swapped in, 236 | as that's distracting and annoying to re-find where one was in the text. 237 |
238 | 239 |
optional 240 |
241 | Gives the font face an extremely small block period 242 | (''100ms'' or less is recommended in most cases) 243 | and a ''0s'' swap period. 244 | 245 | If the font is not retrieved before the two durations expire, 246 | the user agent may choose to abort the font download, 247 | or download it with a very low priority. 248 | If the user agent believes it would be useful for the user, 249 | it may avoid even starting the font download, 250 | and proceed immediately to using a fallback font. 251 | 252 | Note: In other words, the font is used if it's already downloaded and available, 253 | but otherwise a fallback is used for the rest of the page's lifetime instead. 254 | The font might download in the background and be available to future page loads, 255 | but if the user-agent detects that the user has very limited bandwidth, 256 | it might choose to simply never download and use the font. 257 | 258 | This value should be used for body text, 259 | or any other text where the chosen font is purely a decorative "nice-to-have". 260 | It should be used anytime it is more important that the web page render quickly on first visit, 261 | than it is that the user wait a longer time to see everything perfect immediately. 262 | 263 |
264 | For example, body text is perfectly readable in one of the browser default fonts, 265 | though a downloadable font face may be more attractive 266 | and mesh with the site's aesthetics better. 267 | First time visitors to a site generally care far more about the site being quickly usable 268 | than they do about the finer points of its display, 269 | and ''optional'' provides a good behavior for them. 270 | If they return later, 271 | the desired font faces might have finished downloading, 272 | giving them the "intended" experience without slowing down 273 | either their first or subsequent visits. 274 | 275 | Users on very slow connections might not ever receive the "intended" experience, 276 | but ''optional'' ensures they can actually use the site, 277 | rather than quitting and going elsewhere because the site takes too long to load. 278 |
279 |
280 | 281 | Controlling Font Display Per Font-Family via ''@font-feature-values'' 282 | =========================== 283 | The '@font-feature-values/font-display' descriptor for ''@font-feature-values'' determines how a font family is displayed, by setting the "default" font-display value for @font-face rules targeting the same font family. 284 | When font-display is omitted in an @font-face rule, the user agent uses the font-display value set via the @font-feature-values/font-display for the relevant font-family if one is set, and otherwise defaults to "font-display: auto". 285 | 286 | This mechanism can be used to set a default display policy for an entire font-family, and enables developers to set a display policy for @font-face rules that are not directly under their control. 287 | For example, when a font is served by a third-party font foundry, the developer does not control the @font-face rules but is still able to set a default font-display policy for the provided font-family. 288 | The ability to set a default policy for an entire font-family is also useful to avoid the ransom note effect (i.e. mismatched font faces) because the display policy is then applied to the entire font family. 289 | 290 |
291 | Name: font-display
292 | Value: auto | block | swap | fallback | optional
293 | Initial: auto
294 | For: @font-feature-values
295 | 
296 | 297 |
298 | These names aren't great. 299 | It would probably be better to use "intent" names 300 | that immediately capture the intended usage of each. 301 | Some suggestions: 302 | 303 | * required / important / preferable / optional 304 |
305 | 306 | 307 | Acknowledgements {#acks} 308 | ================ 309 | 310 | Special thanks to Ilya Grigorik and David Kuettel for their help in developing this specification. 311 | -------------------------------------------------------------------------------- /css-nesting/index.bs: -------------------------------------------------------------------------------- 1 |

CSS Nesting Module Level 3

2 | 12 | 13 |

14 | Introduction

15 | 16 | This section is not normative. 17 | 18 | This module describes support for nesting a style rule within another style rule, 19 | allowing the inner rule's selector to reference the elements matched by the outer rule. 20 | This feature allows related styles to be aggregated into a single structure within the CSS document, 21 | improving readability and maintainability. 22 | 23 |

24 | Module Interactions

25 | 26 | This module introduces new parser rules that extend the [[!CSS21]] parser model. 27 | This module introduces selectors that extend the [[SELECTORS4]] module. 28 | 29 |

30 | Values

31 | 32 | This specification does not define any new properties or values. 33 | 34 |

35 | Motivation

36 | 37 | CSS Rules for even moderately complicated web pages include lots of duplication for the purpose of styling related content. 38 | For example, here is a portion of the CSS markup for one version of the [[CSS3COLOR]] module: 39 | 40 |
41 |
 42 | 			table.colortable td {
 43 | 				text-align:center;
 44 | 			}
 45 | 			table.colortable td.c {
 46 | 				text-transform:uppercase;
 47 | 			}
 48 | 			table.colortable td:first-child, table.colortable td:first-child+td {
 49 | 				border:1px solid black;
 50 | 			}
 51 | 			table.colortable th {
 52 | 				text-align:center;
 53 | 				background:black;
 54 | 				color:white;
 55 | 			}
 56 | 		
57 |
58 | 59 | Nesting allow the grouping of related style rules, like this: 60 | 61 |
62 |
 63 | 			table.colortable {
 64 | 				& td {
 65 | 					text-align:center;
 66 | 					&.c { text-transform:uppercase }
 67 | 					&:first-child, &:first-child + td { border:1px solid black }
 68 | 				}
 69 | 				& th {
 70 | 					text-align:center;
 71 | 					background:black;
 72 | 					color:white;
 73 | 				}
 74 | 			}
 75 | 		
76 |
77 | 78 | Besides removing duplication, 79 | the grouping of related rules improves the readability and maintainability of the resulting CSS. 80 | 81 | Nesting Selector: the ''&'' selector {#nest-selector} 82 | ===================================================== 83 | 84 | When using a nested style rule, 85 | one must be able to refer to the elements matched by the parent rule; 86 | that is, after all, the entire point of nesting. 87 | To accomplish that, 88 | this specification defines a new selector, 89 | the nesting selector, 90 | written as an ASCII ampersand &. 91 | 92 | When used in the selector of a nested style rule, 93 | the nesting selector represents the elements matched by the parent rule. 94 | When used in any other context, 95 | it represents nothing. 96 | (That is, it's valid, but matches no elements.) 97 | 98 |
99 | The nesting selector can be desugared 100 | by replacing it with the parent style rule's selector, 101 | wrapped in a '':matches()'' selector. 102 | For example, 103 | 104 |
105 | 		a, b {
106 | 			& c { color: blue; }
107 | 		}
108 | 		
109 | 110 | is equivalent to 111 | 112 |
113 | 		:matches(a, b) c { color: blue; }
114 | 		
115 |
116 | 117 | The specificity of the nesting selector 118 | is equal to the largest specificity among the parent style rule's selector 119 | that match the given element. 120 | 121 |
122 | For example, given the following style rules: 123 | 124 |
125 | 		#a, .b {
126 | 			& c { color: blue; }
127 | 		}
128 | 		
129 | 130 | Then in a DOM structure like 131 | 132 |
133 | 			<div id=a>
134 | 				<c>foo</c>
135 | 			</div>
136 | 		
137 | 138 | the ''&'' selector has specificity [1,0,0] 139 | because it matches due to the ''#a'' selector, 140 | giving the entire ''color: blue'' rule a specificity of [1,0,1]. 141 |
142 | 143 | Note: This specificity is intentionally equivalent to that of the desugaring described above. 144 | 145 | The nesting selector is allowed anywhere in a compound selector, 146 | even before a type selector, 147 | violating the normal restrictions on ordering within a compound selector. 148 | 149 | Note: This is required to allow direct nesting. 150 | Also, the "type selectors must come first" has no intrinsic reason behind it; 151 | it exists because we need to be able to tell simple selectors apart unambiguously 152 | when they're directly appended together in a compound selector, 153 | and it's not clear from ''.foodiv'' that it should mean the same as ''div.foo''. 154 | An ampersand is unambiguously separable from an ident, tho, 155 | so there is no problem with it preceding a type selector, 156 | like ''&div''. 157 | 158 | Nesting Style Rules {#nesting} 159 | ============================== 160 | 161 | Nesting style rules naively inside of other style rules is, unfortunately, problematic-- 162 | the syntax of a selector is ambiguous with the syntax of a declaration, 163 | so an implementation requires unbounded lookahead 164 | to tell whether a given bit of text is a declaration or the start of a style rule. 165 | As CSS to date requires only a single token of lookahead in its parsing, 166 | this drawback is generally considered unacceptable among popular implementations of CSS. 167 | 168 | To get around this limitation, 169 | this specification defines two methods of nesting style rules inside of other style rules, 170 | both designed to be immediately unambiguous with the surrounding declarations. 171 | The first, direct nesting, 172 | has a somewhat restricted syntax, 173 | but imposes minimal additional "weight" in the form of disambiguating syntax, 174 | and is suitable for most purposes. 175 | The second, the ''@nest'' rule, 176 | imposes a small syntactic weight to disambiguate it from surrounding declarations, 177 | but has no restrictions on the makeup of the selector. 178 | The two are otherwise equivalent, 179 | and either can be used as desired by the stylesheet author. 180 | 181 | Direct Nesting {#direct} 182 | ------------------------ 183 | 184 | A style rule can be directly nested 185 | within another style rule if its selector is nest-prefixed. 186 | 187 | To be nest-prefixed, 188 | a nesting selector must be the first simple selector 189 | in the first compound selector 190 | of the selector. 191 | If the selector is a list of selectors, 192 | every complex selector in the list must be nest-prefixed 193 | for the selector as a whole to nest-prefixed. 194 | 195 |
196 | For example, the following nestings are valid: 197 | 198 |
199 | 		.foo {
200 | 			color: blue;
201 | 			& > .bar { color: red; }
202 | 		}
203 | 		/* equivalent to
204 | 		   .foo { color: blue; }
205 | 		   .foo > .bar { color: red; }
206 | 		 */
207 | 
208 | 		.foo {
209 | 			color: blue;
210 | 			&.bar { color: red; }
211 | 		}
212 | 		/* equivalent to
213 | 		   .foo { color: blue; }
214 | 		   .foo.bar { color: red; }
215 | 		 */
216 | 
217 | 		.foo, .bar {
218 | 			color: blue;
219 | 			& + .baz, &.qux { color: red; }
220 | 		}
221 | 		/* equivalent to
222 | 		   .foo, .bar { color: blue; }
223 | 		   :matches(.foo, .bar) + .baz,
224 | 		   :matches(.foo, .bar).qux { color: red; }
225 | 		 */
226 | 		
227 | 228 | But the following are invalid: 229 | 230 |
231 | 		.foo {
232 | 			color: red;
233 | 			.bar { color: blue; }
234 | 		}
235 | 		/* Invalid because there's no nesting selector */
236 | 
237 | 		.foo {
238 | 			color: red;
239 | 			.bar & { color:blue; }
240 | 		}
241 | 		/* Invalid because & isn't in the first compound selector */
242 | 
243 | 		.foo {
244 | 			color: red;
245 | 			&.bar, .baz { color: blue; }
246 | 		}
247 | 		/* Invalid because the second selector in the list doesn't
248 | 		   contain a nesting selector. */
249 | 		
250 |
251 | 252 | Note: The last invalid example is technically not ambiguous, 253 | but it's still invalid because allowing it would be an editting hazard. 254 | Later edits to the stylesheet might remove the first selector in the list, 255 | making the other one the new "first selector", 256 | and making the rule invalid. 257 | Turning an otherwise-innocuous action 258 | (like removing a selector from a list) 259 | into a possible error 260 | makes editting more complicated, 261 | and is author-hostile, 262 | so we disallow it as a possibility. 263 | 264 | The Nesting At-Rule: ''@nest'' {#at-nest} 265 | ----------------------------------------- 266 | 267 | While direct nesting looks nice, 268 | it is somewhat fragile. 269 | Some valid nesting selectors, 270 | like ''.foo &'', 271 | are disallowed, 272 | and editting the selector in certain ways can make the rule invalid unexpectedly. 273 | As well, 274 | some people find the nesting difficult to visually distinguish 275 | from the surrounding declarations. 276 | 277 | To aid in all these issues, 278 | this specification defines the ''@nest'' rule, 279 | which imposes less restrictions on how to validly nest style rules. 280 | Its syntax is: 281 | 282 |
283 | 		@nest = @nest <> { <> }
284 | 	
285 | 286 | The ''@nest'' rule functions identically to a style rule: 287 | it starts with a selector, 288 | and contains declarations that apply to the elements the selector matches. 289 | The only difference is that the selector used in a ''@nest'' rule 290 | must be nest-containing, 291 | which means it contains a nesting selector in it somewhere. 292 | A list of selectors is nest-containing if all of its individual complex selectors 293 | are nest-containing. 294 | 295 |
296 | For example, the following nestings are valid: 297 | 298 |
299 | 		.foo {
300 | 			color: red;
301 | 			@nest & > .bar {
302 | 				color: blue;
303 | 			}
304 | 		}
305 | 		/* equivalent to
306 | 		   .foo { color: red; }
307 | 		   .foo > .bar { color: blue; }
308 | 		 */
309 | 
310 | 		.foo {
311 | 			color: red;
312 | 			@nest .parent & {
313 | 				color: blue;
314 | 			}
315 | 		}
316 | 		/* equivalent to
317 | 		   .foo { color: red; }
318 | 		   .parent .foo { color: blue; }
319 | 		 */
320 | 
321 | 		.foo {
322 | 			color: red;
323 | 			@nest :not(&) {
324 | 				color: blue;
325 | 			}
326 | 		}
327 | 		/* equivalent to
328 | 		   .foo { color: red; }
329 | 		   :not(.foo) { color: blue; }
330 | 		 */
331 | 		
332 | 333 | But the following are invalid: 334 | 335 |
336 | 		.foo {
337 | 			color: red;
338 | 			@nest .bar {
339 | 				color: blue;
340 | 			}
341 | 		}
342 | 		/* Invalid because there's no nesting selector */
343 | 
344 | 		.foo {
345 | 			color: red;
346 | 			@nest & .bar, .baz {
347 | 				color: blue;
348 | 			}
349 | 		}
350 | 		/* Invalid because not all selectors in the list
351 | 		   contain a nesting selector */
352 | 		
353 | 354 | Mixing Nesting Rules and Declarations {#mixing} 355 | ----------------------------------------------- 356 | 357 | A style rule can have any number of nested style rules inside of it, 358 | of either type, 359 | intermixed with any number of declarations, 360 | in any order. 361 | 362 | The relative ordering of nested style rules and other declarations is important; 363 | it's possible for a given style rule and a nested style rule within it to match the same element, 364 | and if the specificity of the two rules is otherwise equivalent, 365 | the relative order in the stylesheet of the applicable declarations 366 | determines which declaration "wins" the cascade. 367 | 368 | 369 | CSS Object Model Modifications {#cssom} 370 | ======================================= 371 | 372 |
373 | 1. Add an interface for the @nest rule. 374 | 2. Tie into the general work needed to let rules be nested into style rules. 375 |
376 | -------------------------------------------------------------------------------- /css-shadow-parts/index.bs: -------------------------------------------------------------------------------- 1 | 13 | 14 | 21 | 22 | Introduction {#intro} 23 | ===================== 24 | 25 | Issue: This spec is intentionally a rough sketch at the moment. 26 | It should contain all the details necessary to evaluate the proposal, 27 | but is intentionally avoiding precise algorithms at the moment, 28 | to aid in easy comprehension 29 | and to, hopefully, discourage implementation from this sketch. 30 | 31 | Shadow DOM allows authors to separate their page into "components", 32 | subtrees of markup whose details are only relevant to the component itself, 33 | not the outside page. 34 | This reduces the chance of a style meant for one part of the page 35 | accidentally over-applying and making a different part of the page look wrong. 36 | However, this styling barrier also makes it harder for a page to interact with its components 37 | when it actually wants to do so. 38 | 39 | This specification defines the ''::part()'' and ''::theme()'' pseudo-elements, 40 | which allow an author to style specific, purposely exposed elements in a shadow tree 41 | from the outside page's context. 42 | In combination with custom properties, 43 | which let the outside page pass particular values 44 | (such as theme colors) 45 | into the component for it to do with as it will, 46 | these pseudo-elements allow components and the outside page 47 | to interact in safe, powerful ways, 48 | maintaining encapsulation 49 | without surrending all control. 50 | 51 | Motivation {#motivation} 52 | ------------------------ 53 | 54 | For obvious reasons, 55 | it's valuable to let the outside page style the internals of a shadow tree, 56 | at least in some limited ways. 57 | (The ubiquity of UA-specific pseudo-elements for the various input elements shows this.) 58 | 59 | The previous proposed method for doing so, 60 | the >>> combinator, 61 | turned out to be too powerful for its own good; 62 | it exposed too much of a component's internal structure to scrutiny, 63 | defeating some of the encapsulation benefits that using Shadow DOM brings. 64 | For this, 65 | and other performance-related reasons, 66 | the >>> combinator was eventually removed from the live profile. 67 | 68 | This left us with using custom properties as the only way to style into a shadow tree: 69 | the component would advertise that it uses certain custom properties to style its internals, 70 | and the outer page could then set those properties as it wished on the shadow host, 71 | letting inheritance push the values down to where they were needed. 72 | This works very well for many simple theming use-cases. 73 | 74 | However, there are some cases where this falls down. 75 | If a component wishes to allow arbitrary styling of something in its shadow tree, 76 | the only way to do so is to define hundreds of custom properties 77 | (one per CSS property they wish to allow control of), 78 | which is obviously ridiculous 79 | for both usability and performance reasons. 80 | The situation is compounded if authors wish to style the component differently 81 | based on pseudo-classes like '':hover''; 82 | the component needs to duplicate the custom properties used 83 | for each pseudo-class 84 | (and each combination, 85 | like '':hover:focus'', 86 | resulting in a combinatorial explosion). 87 | This makes the usability and performance problems even worse. 88 | 89 | We introduce ''::part()'' to handle this case much more elegantly and performantly. 90 | Rather than bundling everything into custom property names, 91 | the functionality lives in selectors and style rule syntax, 92 | like it's meant to. 93 | This is far more usable for both component authors 94 | and component users, 95 | should have much better performance, 96 | and allows for better encapsulation/API surface. 97 | 98 | Another interesting facet of using custom properties, 99 | however, 100 | is that inheritance doesn't stop at the first shadow tree. 101 | Unless explicitly blocked, 102 | a custom property inherits down thru nested trees, 103 | allowing authors to style deeply nested components 104 | as easily as they style directly-visible ones. 105 | The same considerations apply to this case, 106 | so we introduce ''::theme()'' to handle this. 107 | 108 | It's important to note that ''::part()'' and ''::theme()'' 109 | offer absolutely zero new theoretical power. 110 | They are not a rehash of the ''>>>'' combinator, 111 | they're simply a more convenient and consistent syntax 112 | for something authors can already do with custom properties. 113 | By separating out the explicitly "published" parts of an element 114 | (the shadow part map 115 | from the sub-parts that it merely happens to contain 116 | (the shadow theme map, 117 | it also helps with encapsulation, 118 | as authors can use ''::part()'' without fear of accidental over-styling. 119 | 120 | 121 | Exposing a Shadow Element: the <{html-global/part}> attribute {#part-attr} 122 | ============================================================= 123 | 124 | Any element in a shadow tree can have a part attribute. 125 | This is used to expose the element outside the shadow tree, 126 | and to "forward" sub-parts of the element 127 | (if it has its own shadow tree) 128 | to outside the shadow tree. 129 | 130 | The part attribute is parsed as a comma-separated list of part mappings. 131 | Each part mapping is one of: 132 | 133 |
134 | : ident 135 | :: Adds «[ ident → el ]» to the shadow root's shadow part map. 136 | 137 | : ident1 => ident2 138 | :: If el is a shadow host, 139 | and it's shadow root's shadow part map |partMap| [=map/contains=] ident1, 140 | then this adds «[ ident2 → |partMap|[ident1] ]» to the shadow root's shadow part map. 141 | 142 | : * => prefix* 143 | :: If el is a shadow host, 144 | then [=map/for each=] |ident| → |subEl| in el's shadow root's shadow part map, 145 | «[ prefix + |ident| → |subEl| ]» is added to the shadow root's shadow part map. 146 | 147 | : anything else 148 | :: Ignored for error-recovery / future compat. 149 |
150 | 151 | Note: It's okay to give a part multiple names, 152 | or map a sub-part to several names. 153 | The "part name" should be considered similar to a class, 154 | not an id or tagname. 155 | 156 | Each shadow root has a shadow part map 157 | and a shadow theme map, 158 | both of which are ordered maps. 159 | 160 | The shadow part map contains all the entries described by the elements in its shadow tree, 161 | as described above. 162 | 163 | If the shadow root's {{ShadowRoot/mode}} is {{ShadowRootMode/"closed"}}, 164 | the shadow theme map is identical to the shadow part map. 165 | Otherwise, 166 | it's the concatenation of the shadow part map 167 | with the shadow theme maps of every shadow host's shadow root in its shadow tree. 168 | 169 | Issue: TODO: Define a syntax or new attribute 170 | to prevent an element from adding things to its shadow root's shadow theme map. 171 | 172 | Selecting a Shadow Element: the ''::part()'' and ''::theme()'' pseudo-elements {#part-theme} 173 | ============================================================================================ 174 | 175 | The ::part() and ::theme() pseudo-elements 176 | (collectively, the shadow-part pseudo-elements) 177 | allow you to select elements that have been exposed via a <{html-global/part}> attribute. 178 | The syntaxes of them are: 179 | 180 |
181 |     ::part() = ::part( <> )
182 |     ::theme() = ::theme( <> )
183 | 
184 | 185 | The ''::part()'' pseudo-element only matches anything 186 | when the originating element is a shadow host. 187 | If the originating element's shadow root's shadow part map 188 | [=map/contains=] the specified <>, 189 | ''::part()'' matches the element or elements keyed to that <>. 190 | Otherwise, it matches nothing. 191 | 192 |
193 | For example, 194 | if you have a custom button 195 | that contains a "label" element that is exposed for styling 196 | (via part="label"), 197 | you can select it with 198 | ''#the-button::part(label)''. 199 |
200 | 201 | The ''::theme()'' pseudo-element is similar, 202 | except it can match regardless of whether the originating element 203 | is a shadow host or not. 204 | It matches the elements keyed to the specified <> 205 | in the shadow theme map of the shadow trees 206 | of the originating element or any descendants. 207 | 208 |
209 | For example, 210 | '':root::theme(label)'' matches any element with part="label" 211 | anywhere in the entire document, 212 | no matter how deeply nested into shadow trees they are. 213 |
214 | 215 | The shadow-part pseudo-elements can take additional pseudo-classes after them, 216 | such as ''x-button::part(label):hover'', 217 | but never match the structural pseudo-classes 218 | or any other pseudo-classes that match based on tree information 219 | rather than local element information. 220 | 221 | The shadow-part pseudo-elements also can take additional pseudo-elements after them, 222 | such as ''x-button::part(label)::before'', 223 | but never match additional shadow-part pseudo-elements. 224 | 225 |
226 | For example, 227 | ''x-panel::part(confirm-button)::part(label)'' 228 | never matches anything. 229 | This is because doing so would expose more structural information 230 | than is intended. 231 | 232 | One can still target the nested label with a selector like 233 | ''x-panel::theme(label)''. 234 | However, this will also select the labels of any other buttons in the panel. 235 | 236 | If the <x-panel>'s internal confirm button had used something like 237 | part="confirm-button, * => confirm-*" 238 | to forward the button's internal parts up into the panel's own shadow part map, 239 | then a selector like 240 | ''x-panel::part(confirm-label)'' 241 | would select just the one button's label, 242 | ignoring any other labels. 243 |
244 | -------------------------------------------------------------------------------- /css-stacking-context-1/index.bs: -------------------------------------------------------------------------------- 1 | 12 | 13 | 30 | 31 | 37 | 38 | Introduction {#intro} 39 | ===================== 40 | 41 | This section is not normative. 42 | 43 | Elements on a page can have many overlapping parts. 44 | This specification defines the precise order 45 | that every part of an element 46 | and the surrounding page 47 | is painted, 48 | so that things render above (or below) other things 49 | in a well-defined way. 50 | 51 | Painting Order {#order} 52 | ======================= 53 | 54 | The rendering structure of a document consists of 55 | a [=root canvas=], 56 | a [=document layer=] 57 | and any number of additional [=rendering layers=], 58 | and within each layer, 59 | a [=/list=] of one or more [=trees=] of [=CSS/boxes=] generated by [=CSS/elements=]. 60 | 61 | A canvas is a theoretically-infinite 2D field of color. 62 | The root canvas is the [=CSS/canvas=] 63 | upon which all of the document's content is rendered. 64 | Layers, and elements that generate stacking contexts, 65 | first render onto temporary [=CSS/canvases=] 66 | before being composited onto an ancestor canvas 67 | (ending with the [=root canvas=] for the document). 68 | 69 | A rendering layer 70 | is an ordered list of [=boxes=], 71 | where each layer is rendered fully atop all previous layers, 72 | and fully below all following layers. 73 | Within the layer, 74 | [=boxes=] and their descendants 75 | can potentially interweave their rendering with each other. 76 | The document layer is the layer 77 | containing the principal box of the document's root element; 78 | it is below all other [=rendering layers=]. 79 | 80 | In the following algorithms, 81 | a given box or fragment is only painted once, 82 | by whatever step attempts to paint it first. 83 | (This allows the algorithm to be written much simply, 84 | without elaborate guards to check against double-painting.) 85 | 86 | Issue: This is meant to be a reproduction and elaboration 87 | of the CSS2 "Elaborate Description of Stacking Contexts" algorithm, 88 | modified to account for where filter/clipping/compositing can happen, 89 | the existence of top layers, 90 | and the newer element/box/fragment hierarchy. 91 | Non-editorial changes beyond the above 92 | are unintentional and probably bugs. 93 | 94 | 95 |
96 | To paint a document: 97 | 98 | 1. If the document is being painted as part of another document 99 | (such as an <{iframe}>'s document), 100 | then the [=root canvas=] is initially [=transparent black=] everywhere. 101 | 102 | Otherwise, the [=root canvas=] is a UA-defined color everywhere. 103 | This can be affected by things such as, but not limited to, 104 | the 'color-scheme' property. 105 | 106 | Other specifications can define that the [=root canvas=] 107 | begins as another color in certain circumstances. 108 | 109 | 2. [=paint a layer|Paint the document layer=] onto the [=root canvas=]. 110 | 111 | 3. For each additional [=rendering layer=], in order from bottom to top, 112 | [=paint the layer=] onto the [=root canvas=]. 113 |
114 | 115 |
116 | To paint a layer |layer| onto a |root canvas|: 117 | 118 | 1. Let |canvas| be a fresh [=CSS/canvas=]. 119 | initially [=transparent black=] everywhere. 120 | 121 | 2. If |layer| is the [=document layer=], 122 | and the root element generates a [=box=], 123 | then the root element propagates its background 124 | to |canvas|: 125 | the root element's 'background' is painted onto |canvas|, 126 | using all of |canvas| as the [=background painting area=], 127 | but continuing to use the root element 128 | to determine the [=background positioning area=]. 129 | 130 | Issue: [[CSS-CONTAIN-3]] should, apparently, block propagation, 131 | but I can't find that in the spec. 132 | Figure out if I missed something, 133 | and make it block propagation here. 134 | 135 | 3. For each top-level [=box=] in |layer|, 136 | [=paint a stacking context=] of the box onto |canvas|. 137 | 138 | 4. If the implementation chose not to paint outlines 139 | while executing the previous step, 140 | paint the outlines of all boxes/fragments in |layer| to |canvas|. 141 | 142 | 5. Issue: Clipping/filtering/etc goes here. 143 | 144 | 6. Composite |canvas| onto |root canvas|. 145 | 146 | Issue: Does only the document layer have non-trivial whole-layer compositing? 147 |
148 | 149 |
150 | To paint a stacking context with a [=box=] |box| onto a [=CSS/canvas=] |root canvas|: 151 | 152 | 1. Let |canvas| be a fresh [=CSS/canvas=], 153 | initially [=transparent black=] everywhere. 154 | 155 | 2. 156 |
157 | : If |box| is a [=block-level=] box other than a [=table wrapper box=] 158 | :: 159 | If |box| did not [=propagate its background=], 160 | paint |box|’s background color onto |canvas|, 161 | then background image. 162 | 163 | In all cases, 164 | then paint |box|’s border onto |canvas|. 165 | 166 | : If |box| if a [=block-level=] [=table wrapper box=]: 167 | :: Paint the following onto |canvas|, in order: 168 | 169 | 1. If |box| did not [=propagate its background=], 170 | paint |box|’s backgrounds 171 | (color, then image) 172 | onto |canvas|. 173 | 174 | 2. Paint |box|’s column group’s backgrounds 175 | (color, then image) 176 | onto |canvas|. 177 | 178 | 3. Paint |box|’s column’s backgrounds 179 | (color, then image) 180 | onto |canvas|. 181 | 182 | 4. Paint |box|’s row group’s backgrounds 183 | (color, then image) 184 | onto |canvas|. 185 | 186 | 5. Paint |box|’s row’s backgrounds 187 | (color, then image) 188 | onto |canvas|. 189 | 190 | 6. Paint |box|’s cell’s backgrounds 191 | (color, then image) 192 | onto |canvas|. 193 | 194 | 7. Paint all of |box|’s table borders 195 | (in tree order, for separated borders) 196 | onto |canvas|. 197 | 198 | Issue: I think this needs more detail, 199 | and I think [[CSS-TABLES-3]] provides it. 200 |
201 | 202 | 3. For each [=stacking context=] descendant of |box| 203 | with strictly negative z-indexes, 204 | in z-index order 205 | (most negative first), 206 | then tree order, 207 | [=paint a stacking context=] for the descendant 208 | onto |canvas|. 209 | 210 | 4. For each in-flow, 211 | non-[=positioned=], 212 | [=block-level=] 213 | descendant of |box|, 214 | in tree order: 215 | 216 |
217 | : If the descendant is not a [=table wrapper box=] 218 | :: Paint its background color, 219 | then background image, 220 | then border 221 | onto |canvas|. 222 | 223 | : If the descendant is a [=table wrapper box=] 224 | :: 225 | 1. Paint its backgrounds 226 | (color, then image) 227 | onto |canvas|. 228 | 229 | 2. Paint its column group’s backgrounds 230 | (color, then image) 231 | onto |canvas|. 232 | 233 | 3. Paint its column’s backgrounds 234 | (color, then image) 235 | onto |canvas|. 236 | 237 | 4. Paint its row group’s backgrounds 238 | (color, then image) 239 | onto |canvas|. 240 | 241 | 5. Paint its row’s backgrounds 242 | (color, then image) 243 | onto |canvas|. 244 | 245 | 6. Paint its cell’s backgrounds 246 | (color, then image) 247 | onto |canvas|. 248 | 249 | 7. Paint all of |box|’s table borders 250 | (in tree order, for separated borders) 251 | onto |canvas|. 252 |
253 | 254 | 5. For each non-[=positioned=], 255 | [=floating=] 256 | descendant |d| of |box|, 257 | in tree order, 258 | [=paint a stacking context=] from |d| onto |canvas|, 259 | skipping any positioned descendants of |d| 260 | and any descendants of |d| 261 | that actually create new stacking contexts. 262 | (They are, instead, painted 263 | as part of |box| in other steps.) 264 | 265 | 6. If |box| is [=inline-level=] 266 | and generates a [=stacking context=], 267 | then for each [=line box=] that |box| is in, 268 | [=paint an inline run=] from |box|’s [=fragments=] in that [=line box=] 269 | onto |canvas|. 270 | 271 | 7. Otherwise 272 | (if it did not match Step 6's condition), 273 | then first for |box|, 274 | then for all its [=in-flow=], 275 | non-[=positioned=], 276 | [=block-level=] descendants |d|, 277 | in tree order: 278 | 279 | 1. If |d| is a [=block-level=] [=replaced=] element, 280 | paint the replaced content onto |canvas|, 281 | atomically. 282 | 283 | 2. Otherwise, for each [=line box=] of |d|, 284 | for each [=box=] child of |d| that generates [=fragments=] 285 | in that [=line box=], 286 | [=paint an inline run=] from those [=fragments=] 287 | onto |canvas|. 288 | 289 | 3. Optionally, if |d| is [=block-level=], 290 | paint the outline of |d| onto |canvas|. 291 | 292 | 8. For each [=positioned=] descendant |d| of |box| 293 | with zero or ''z-index/auto'' z-index, 294 | in tree order, 295 | [=paint a stacking context=] for |d| 296 | onto |canvas|. 297 | If |d| is ''z-index: auto'', 298 | skip any positioned descendants of |d| 299 | and any descendants of |d| 300 | that actually create new stacking contexts. 301 | (They are, instead, painted 302 | as part of |box|.) 303 | 304 | 9. For each [=stacking context=] descendant of |box| 305 | with strictly positive z-indexes, 306 | in z-index order 307 | (least positive first), 308 | then tree order, 309 | [=paint a stacking context=] for the descendant 310 | onto |canvas|. 311 | 312 | 10. Filter/clip/etc here 313 | 314 | 11. Composite |canvas| onto |root canvas|. 315 |
316 | 317 |
318 | To paint an inline run 319 | of a list of [=fragments=] |frags| 320 | that are all in the same [=line box=], 321 | onto a [=CSS/canvas=] |canvas|: 322 | 323 | 1. For each [=fragment=] |frag| of |frags|: 324 | 325 | 1. Paint the background color, 326 | then background image, 327 | then border of |frag| 328 | onto |canvas|. 329 | 330 | 2.
331 | : If |frag| was generated by an [=inline=] [=box=] 332 | :: 333 | For all descendant [=fragments=] of |frag| 334 | that were generated by an in-flow, 335 | non-positioned, 336 | [=inline-level=] box, 337 | or that were generated by a [=text run=]: 338 | 339 |
340 | : If the fragment was generated by a text run 341 | :: 342 | 1. Paint any underlining affecting the text of the fragment, 343 | in tree order of the elements applying the underlining 344 | (such that the deepest element's underline, 345 | if any, 346 | if painted topmost 347 | and the root element's underlining, 348 | if any, 349 | is painted bottommost), 350 | onto |canvas|. 351 | 352 | 2. Paint any overlining affecting the text of the fragment, 353 | in the same order as underlines, 354 | onto |canvas|. 355 | 356 | 3. Paint the text onto |canvas|. 357 | 358 | 4. Paint any line-through affecting the text of the fragment, 359 | in the same order as underlines, 360 | onto |canvas|. 361 | 362 | : Otherwise 363 | :: 364 | [=Paint an inline run=] from |frag| 365 | onto |canvas|. 366 |
367 | 368 | : If |frag| was generated by an [=inline-level=] [=block=] or [=table wrapper box=] 369 | :: 370 | [=Paint a stacking context=] from |frag|’s generating [=box=] 371 | onto |canvas|, 372 | skipping any [=positioned=] descendants of the box 373 | and any descendants of the box 374 | that actually create new [=stacking contexts=]. 375 | (They are, instead, 376 | painted as part of their nearest ancestor [=stacking context=].) 377 | 378 | : If |frag| was generated by an [=inline-level=] [=replaced=] box 379 | :: 380 | Paint the replaced content, atomically, 381 | onto |canvas|. 382 |
383 | 384 | 2. Optionally, 385 | paint the outline of |frag| onto |canvas|. 386 | 387 | Note: Some of the fragments in |frags| 388 | might have been generated by line splitting 389 | or the Unicode bidirectional algorithm. 390 | 391 | Issue: Figure out if filtering/clipping/compositing 392 | can take place at this step, 393 | and if so, 394 | exactly how to phrase it 395 | since this step potentially paints from multiple elements. 396 | 397 | Issue: While the backgrounds of bidirectional inlines 398 | are painted in tree order, 399 | they are positioned in visual order. 400 | Is the positioning of inline backgrounds still undefined? 401 |
402 | 403 | -------------------------------------------------------------------------------- /css-sticky-scrollbars/index.bs: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | 20 | This Spec Has Been Superseded {#intro} 21 | ====================================== 22 | 23 | This spec has been superseded by other CSS technology. 24 | In particular, to implement a chatroom 25 | that "sticks" the scrollbar to the bottom of the scroller when you're near the bottom, 26 | staying there if you add new messages to the bottom, 27 | but not messing with your scroll position when you're scrolled elsewhere in the history, 28 | just use [[css-scroll-snap-1]]: 29 | 30 |
31 | .message-container {
32 |   scroll-snap-type: proximity;
33 | }
34 | .message-container::after {
35 |   content: "";
36 |   height: 0;
37 |   overflow: hidden;
38 |   display: block;
39 |   scroll-snap-align: end;
40 | }
41 | 
42 | 43 | This creates a single scroll snap area in the message container, 44 | aligned with the very bottom of the container. 45 | If you scroll "near" the bottom, you'll snap to it; 46 | if you add more content to the message container 47 | (thus pushing the ::after further down), 48 | it'll automatically re-snap to it 49 | (because scroll containers have to re-snap to the same scroll snap area if it still exists); 50 | if you are scrolled somewhere else in the history, 51 | it won't do anything at all. 52 | 53 | The use-case of "stable scrolling", 54 | where you want "whatever you're currently looking at" to stay on the screen 55 | when things are added/removed/resized higher up in the scroll container, 56 | is handled by the Scroll Anchoring proposal 57 | currently making its way thru the standards process. 58 | -------------------------------------------------------------------------------- /css-toggle-states/index.bs: -------------------------------------------------------------------------------- 1 | 14 | 15 | 21 | 22 |

23 | Introduction

24 | 25 | This section is not normative. 26 | 27 | Some user-interface languages define elements which can have "toggleable state", 28 | which can be modified by user interaction and selected using CSS Selectors. 29 | For example, in HTML, the <input type=checkbox> has a "checked" state 30 | which toggles between true and false when the user activates the element, 31 | and which is selected by the '':checked'' pseudoclass. 32 | 33 |
34 | The following markup example shows how to lightly abuse HTML semantics to declaratively use toggleable state: 35 | 36 |
 37 | 			<ul class='ingredients'>
 38 | 			  <li><label><input type=checkbox><span>1 banana</span></label>
 39 | 			  <li><label><input type=checkbox><span>1 cup blueberries</span></label>
 40 | 			  ...
 41 | 			</ul>
 42 | 			<style>
 43 | 			input[type='checkbox'] {
 44 | 			  display: none;
 45 | 			}
 46 | 			input[type='checkbox']:checked + span {
 47 | 			  color: silver;
 48 | 			  text-decoration: line-through;
 49 | 			}
 50 | 			</style>
 51 | 		
52 | 53 | In this markup, 54 | one can cross out ingredients as they're used in the recipe 55 | by simply clicking on them. 56 |
57 | 58 | This module generalizes this ability and allows it to be applied to any element via CSS. 59 | Elements can be declared to have toggleable state, 60 | with any number of states that can be toggled between. 61 | Multiple elements can share access to the same toggleable state, 62 | similar to HTML's <input type=radio> element. 63 | This state can be manipulated by activating the element or other specified elements, 64 | or by other user interactions. 65 | 66 | 67 |

68 | Creating a Toggleable Element: the 'toggle-states' and 'toggle-initial' property

69 | 70 |
 71 | 	Name: toggle-states
 72 | 	Value: none | <> [cycle | sticky]?
 73 | 	Initial: none
 74 | 	Applies to: all elements
 75 | 	Inherited: no
 76 | 	Percentages: n/a
 77 | 	Media: interactive
 78 | 	Computed value: as specified
 79 | 	Animatable: no
 80 | 	
81 | 82 |
 83 | 	Name: toggle-initial
 84 | 	Value: <>
 85 | 	Initial: 0
 86 | 	Applies to: all elements
 87 | 	Inherited: no
 88 | 	Percentages: n/a
 89 | 	Media: interactive
 90 | 	Computed value: as specified
 91 | 	Animatable: no
 92 | 	
93 | 94 | The 'toggle-states' property controls whether an element has toggleable state or not. 95 | 96 |
97 |
none 98 |
99 | Indicates that the element does not have toggleable state. 100 | 101 |
<> [cycle | sticky]? 102 |
103 | Indicates that the element is toggleable. 104 | The <> gives the number of states; 105 | it must be 2 or greater, or else the property is invalid. 106 | The following optional keyword defines the behavior 107 | when the element is already at its last state, 108 | and is toggled again: 109 | cycle defines that it should cycle back around to the first state, 110 | while sticky defines that it should stay at the last state. 111 |
112 | 113 | If an element is toggleable, 114 | it has a toggle state, 115 | which is an integer from 0 to some maximum value, 116 | as defined by 'toggle-states'. 117 | This state is incremented whenever the element is activated by the user, 118 | using the same defininition of "activated" as the '':active'' pseudo-class, 119 | and can be selected by the '':checked'' or '':checked()'' pseudo-classes, 120 | as defined later in this specification. 121 | 122 |
123 | Revisiting the example in the Introduction, 124 | the same ingredient list can be specified in simple HTML and CSS: 125 | 126 |
127 | 			<ul class='ingredients'>
128 | 			  <li>1 banana
129 | 			  <li>1 cup blueberries
130 | 			  ...
131 | 			</ul>
132 | 			<style>
133 | 			li {
134 | 			  toggle-states: 2;
135 | 			}
136 | 			li:checked {
137 | 			  color: silver;
138 | 			  text-decoration: line-through;
139 | 			}
140 | 			</style>
141 | 		
142 | 143 | The effect is identical to what was specified in the Introduction example, 144 | except the markup is much simpler and more semantic. 145 |
146 | 147 | The 'toggle-initial' property sets the initial toggle state of the element. 148 | Its value must be a non-negative integer, 149 | or else the property is invalid. 150 | If the value is equal to or greater than the number of states defined by 'toggle-states', 151 | it computes to the greatest toggle state. 152 | 153 | 154 |

155 | Linking Toggle States: the 'toggle-group' property

156 | 157 |
158 | 	Name: toggle-group
159 | 	Value: none | <>
160 | 	Initial: none
161 | 	Applies to: all elements
162 | 	Inherited: no
163 | 	Percentages: n/a
164 | 	Media: interactive
165 | 	Computed value: as specified
166 | 	Animatable: no
167 | 	
168 | 169 | By default, each toggleable element's toggle state is independent; 170 | incrementing one has no effect an any other. 171 | The 'toggle-group' property allows elements to link their toggle states together 172 | by declaring them to be part of a named toggle group, 173 | such that only one can have a non-zero toggle state at a time, 174 | similar to HTML's <input type=radio> element. 175 | Each [=toggle group=] on a page is identified by a unique <>. 176 | 177 |
178 |
none 179 |
180 | The element is not in a toggle group. 181 | It's toggle state is independent of any other elements'. 182 | 183 |
<> 184 |
185 | The element is in the toggle group named by the <>. 186 | Any time an element in the given toggle group has its toggle state incremented, 187 | the toggle state of every other element in the same toggle group is set to 0. 188 | 189 | The keyword none is excluded from this <>. 190 |
191 | 192 |
193 | For example, 'toggle-group' can be used to control a tabbed display, 194 | so that only one panel is displayed at a time: 195 | 196 |
197 | 			.tab {
198 | 			  toggle-states: 2 sticky;
199 | 			  toggle-group: "tabs";
200 | 			  toggle-share: select(attr(for idref));
201 | 			}
202 | 			.panel {
203 | 			  toggle-states: 2 sticky;
204 | 			  toggle-group: "panels";
205 | 			}
206 | 			.tab:checked {
207 | 			  /* styling for the active tab */
208 | 			}
209 | 			.panel:not(:checked) {
210 | 			  display: none;
211 | 			}
212 | 		
213 | 214 | Clicking on any tab will increment its toggle state from 0 to 1 215 | (and the ''sticky'' keyword will keep it at 1 if activated multiple times), 216 | while resetting the rest of the tabs' toggle states to 0. 217 | The same happens to the panels, 218 | using the 'toggle-share' property defined in a later section. 219 | The active tab and panel are styled and shown differently than the other tabs and panels. 220 |
221 | 222 |

223 | The name is global to the page. 224 | Should we have a way to specify more implicit groups? 225 | Maybe a ''parent'' keyword, 226 | or a way to scope names to a subtree? 227 | 228 | 229 |

230 | Sharing Toggle Activations: the 'toggle-share' property

231 | 232 |
233 | 	Name: toggle-share
234 | 	Value: none | <>
235 | 	Initial: none
236 | 	Applies to: all elements
237 | 	Inherited: no
238 | 	Percentages: n/a
239 | 	Media: interactive
240 | 	Computed value: as specified
241 | 	Animatable: no
242 | 	
243 | 244 | By default, activating an element only increments its own toggle state. 245 | The 'toggle-share' property allows an element to additionally increment the toggle state of another element. 246 | 247 |
248 |
none 249 |
250 | Activating the element only increments its own toggle state 251 | (assuming the element is toggleable). 252 | 253 |
<> 254 |
255 | Activating the element increments the toggle state 256 | of both itself and all the elements matched by the given selector 257 | (assuming the elements are toggleable). 258 | 259 | If the set of elements sharing the activation includes elements that share a toggle group, 260 | only the last such element (in document order) per group has its toggle state incremented. 261 |
262 | 263 |
264 | The preceding section for 'toggle-group' contained an example showing off 'toggle-share'. 265 | When the user activates a tab, 266 | the activation is shared with the associated panel. 267 |
268 | 269 | Note: This functionality is similar in nature to HTML's <label> element, 270 | but not identical. 271 | 'toggle-share' causes the activation to be shared, 272 | rather than transferred like <label> does. 273 | Additionally, this sharing only affects the toggle state, 274 | while <label more strongly transfers the concept of "activating", 275 | affecting things such as click events and the '':hover'' pseudo-class. 276 | 277 | 278 |

279 | Selecting Elements Based on Toggle State: the '':checked'' and '':checked()'' pseudo-class

280 | 281 | The '':checked'' pseudo-class, 282 | defined in [[SELECTORS-4]], 283 | has its definition expanded to additionally match any element 284 | whose toggle state is non-zero. 285 | 286 | The :checked(<>) pseudo-class 287 | selects any elements whose toggle state has the value given by its argument. 288 | 289 |

290 | Problems with Combining '':checked'' and 'toggle-*' Properties

291 | 292 | Naively combining '':checked'' and the 'toggle-*' properties causes circularity issues. 293 | 294 |
295 | For example, 296 | in the following code, 297 | the element starts in a state that matches '':checked'', 298 | but the '':checked'' selector makes the element no longer toggleable, 299 | so it no longer matches '':checked''. 300 | 301 |
302 | 			#foo {
303 | 				toggle-states: 2;
304 | 				toggle-initial: 1;
305 | 			}
306 | 			#foo:checked {
307 | 				toggle-states: none;
308 | 			}
309 | 		
310 |
311 | 312 | To avoid this, 313 | the 'toggle-states' and 'toggle-initial' are defined as selector-affecting properties, 314 | and the '':checked'' and '':checked()'' pseudo-classes are defined as property-affected selectors. 315 | In any style rule whose selector includes a property-affected selector, 316 | any selector-affecting properties are invalid. 317 | 318 | Issue: I'm not sure this is sufficient. 319 | For example, you could set the property in an animation, 320 | which is triggered by an affected selector. 321 | Is there a better way to define this so that it's reliable? 322 | -------------------------------------------------------------------------------- /css-when-else/index.bs: -------------------------------------------------------------------------------- 1 | 13 | 14 | 18 | 19 | Introduction {#intro} 20 | ===================== 21 | 22 | Writing complex media queries or supports queries is difficult, 23 | particularly when you want to do Thing A in one circumstance, 24 | Thing B in another circumstance, 25 | and Thing C otherwise. 26 | This requires carefully crafting your conditional rules to exclude anything matching the other rules, 27 | while also making sure you're not accidentally over-excluding things and leaving some situations unmatched. 28 | 29 | This spec proposes two things to fix this problem. 30 | First, it proposes an ''@when'' rule, 31 | which generalizes the concept of a conditional rule. 32 | Anything you can express in an existing conditional rule 33 | can be expressed in ''@when'', 34 | it just has to be wrapped in an appropriate function 35 | to declare what kind of condition it is. 36 | This allow authors to easily combine multiple types of queries, 37 | such as media queries and supports queries, 38 | in a single boolean expression. 39 | Without this, 40 | authors must rely on nesting separate conditional rules, 41 | which is harder to read and write, 42 | presupposes the conditions are to be conjoined with the "and" boolean relation 43 | (with no easy way to indicate anything else), 44 | and restricts their utility in the proposed conditional rule chains. 45 | 46 | Second, it proposes the introduction of ''@else'' rules, 47 | which follow conditional rules 48 | and automatically qualify their conditions as you'd expect, 49 | such that at most one rule in an conditional rule chain is chosen as active. 50 | 51 | Generalized Conditional Rules: the ''@when'' rule {#when-rule} 52 | ========================================================== 53 | 54 | The @when at-rule is a conditional group rule 55 | that generalizes the individual conditional group rules 56 | such as ''@media'' and ''@supports''. 57 | It is defined as: 58 | 59 |
 60 | @when <> {
 61 | 	<>
 62 | }
 63 | 
64 | 65 | Where <> is a boolean algebra a la [[mediaqueries-4#mq-syntax]], 66 | but with ''media()'' and ''supports()'' functions as leaves. 67 | 68 | Issue: Define "boolean algebra, with X as leaves" in a generic way in Conditional, 69 | so all the conditional rules can reference it directly, 70 | rather than having to redefine boolean algebra on their own. 71 | 72 | The ''media()'' and ''supports()'' functions are defined as: 73 | 74 |
 75 | media() = media( [ <> | <> | <> ] )
 76 | supports() = supports( <> )
 77 | 
78 | 79 | A ''media()'' or ''supports()'' function is associated the boolean result 80 | that its contained condition is associated with. 81 | 82 | Chained Conditionals: the ''@else'' rule {#else-rule} 83 | ===================================================== 84 | 85 | Usually, conditional group rules are independent; 86 | each one has a separate condition 87 | evaluated without direct reference to any other rule, 88 | and decides whether or not to apply its contained rules 89 | based solely on its condition. 90 | 91 | This is fine for simple conditions, 92 | but makes it difficult to write a collection of conditionals that are meant to be mutually exclusive; 93 | authors have to very carefully craft their conditions to not activate when the other rules are meant to, 94 | and make sure the collection of conditionals don't accidentally all exclude some situation 95 | which is then left unstyled. 96 | 97 | The @else rule is a conditional group rule 98 | used to form conditional rule chains, 99 | which allow multiple conditional rules to be provided 100 | and guarantee that at most one of them will evaluate their condition as true. 101 | It is defined as: 102 | 103 |
104 | @else <>? {
105 | 	<>
106 | }
107 | 
108 | 109 | ''@else'' is interpreted identically to ''@when''. 110 | If its <> is omitted, 111 | it's treated as having a condition that's always true. 112 | 113 | A conditional rule chain is a series of consecutive conditional group rules, 114 | starting with a conditional group rule other than ''@else'', 115 | followed by zero or more ''@else'' rules. 116 | There cannot be anything between the successive conditional group rules 117 | other than whitespace and/or comments; 118 | any other token "breaks" the chain. 119 | 120 | Issue: Should we require that only the last ''@else'' in a chain can have an omitted condition? 121 | It's not uncommon for me, when debugging code, 122 | to short-circuit an if-else chain by setting one of them to "true"; 123 | I presume that would be similarly useful in CSS? 124 | It's still pretty easy to see you've done something wrong if you omit the condition accidentally. 125 | 126 | Within a conditional rule chain, 127 | the conditions of each conditional group rule are evaluated in order. 128 | If one of them is true, 129 | the conditions of all following conditional group rules in the chain must evaluate to false, 130 | regardless of what they contain. 131 | 132 | An ''@else'' rule that is not part of a conditional rule chain is invalid and must be ignored. 133 | 134 |
135 | For example, here's a (somewhat silly) conditional chain: 136 | 137 |
138 | 		@when media(width >= 400px) and media(pointer: fine) and supports(display: flex) {
139 | 			/* A */
140 | 		} @else supports(caret-color: pink) and supports(background: double-rainbow()) {
141 | 			/* B */
142 | 		} @else {
143 | 			/* C */
144 | 		}
145 | 	
146 | 147 | Exactly one of the preceding rules will be chosen, 148 | even tho the second rule 149 | doesn't exclude large widths, fine points, or flexbox support, 150 | and the last rule 151 | doesn't specify anything at all. 152 | 153 | To achieve the same result without conditional rule chains, 154 | you'd need to write: 155 | 156 |
157 | 		@media (width >= 400px) and (pointer: fine) {
158 | 			@supports (display: flex) {
159 | 				/* A */
160 | 			}
161 | 			@supports not (display: flex) {
162 | 				@supports (caret-color: pink) and (background: double-rainbow()) {
163 | 					/* B */
164 | 				}
165 | 				@supports not ((caret-color: pink) and (background: double-rainbow())) {
166 | 					/* C */
167 | 				}
168 | 			}
169 | 		}
170 | 		@media not ((width >= 400px) and (pointer: fine)) {
171 | 			@supports (caret-color: pink) and (background: double-rainbow()) {
172 | 				/* B */
173 | 			}
174 | 			@supports not ((caret-color: pink) and (background: double-rainbow())) {
175 | 				/* C */
176 | 			}
177 | 		}
178 | 	
179 | 180 | This is simultaneously impossible to read, 181 | requires significant duplication of both conditions and contents, 182 | and is very difficult to write correctly 183 | (I wrote it wrong twice while producing this example). 184 | If the conditions got any more complicated 185 | (which is not unusual in real-world content), 186 | the example would get significantly worse. 187 |
188 | -------------------------------------------------------------------------------- /css-will-change/index.bs: -------------------------------------------------------------------------------- 1 | 13 | 14 |

15 | Introduction

16 | 17 | Modern CSS renderers perform a number of complex optimizations in order to render webpages quickly and efficiently. 18 | Unfortunately, employing these optimizations often has a non-trivial start-up cost, 19 | which can have a negative impact on the responsiveness of a page. 20 | 21 |
22 | For example, when using CSS 3D Transforms to move an element around the screen, 23 | the element and its contents might be promoted to a “layer”, 24 | where they can render independently from the rest of the page and be composited in later. 25 | This isolates the rendering of the content so that the rest of the page doesn't have to be rerendered 26 | if the element’s transform is the only thing that changes between frames, 27 | and often provides significant speed benefits. 28 | 29 | However, setting up the element in a fresh layer is a relatively expensive operation, 30 | which can delay the start of a 'transform' animation by a noticeable fraction of a second. 31 |
32 | 33 | The 'will-change' property defined in this specification allows an author to declare ahead-of-time what properties are likely to change in the future, 34 | so the UA can set up the appropriate optimizations some time before they're needed. 35 | This way, when the actual change happens, 36 | the page updates in a snappy manner. 37 | 38 |

39 | Hinting at Future Behavior: the 'will-change' property

40 | 41 |
 42 | 	Name: will-change
 43 | 	Value: auto | <>#
 44 | 	Initial: auto
 45 | 	Applies to: all elements
 46 | 	Inherited: no
 47 | 	Percentages: n/a
 48 | 	Media: all
 49 | 	Computed value: specified value
 50 | 	
51 | 52 |
<animateable-feature> = scroll-position | contents | <>
53 | 54 | The 'will-change' property provides a rendering hint to the user agent, 55 | stating what kinds of changes the author expects to perform on the element. 56 | This allows the user agent to perform ahead-of-time any optimizations necessary for rendering those changes smoothly, 57 | avoiding “jank” when the author does begin changing or animating that feature. 58 | 59 | Values have the following meanings: 60 | 61 |
62 |
auto 63 |
64 | Expresses no particular intent. 65 | 66 |
scroll-position 67 |
68 | Indicates that the author expects to animate or change the scroll position of the element in the near future. 69 | 70 |
contents 71 |
72 | Indicates that the author expects to animate or change something about the element's contents in the near future. 73 | 74 |
<> 75 |
76 | Indicates that the author expects to animate or change the property with the given name on the element in the near future. 77 | 78 | The <> production used here excludes the keywords will-change, none, all, auto, scroll-position, and contents, 79 | in addition to the keywords normally excluded from <>. 80 | 81 | Note: Note that most properties will have no effect when specified, 82 | as the user agent doesn't perform any special optimizations for changes in most properties. 83 | It is still safe to specify them, though; 84 | it'll simply have no effect. 85 | 86 | If any non-initial value of a property would create a stacking context on the element, 87 | specifying that property in 'will-change' must create a stacking context on the element. 88 | 89 | If any non-initial value of a property would cause the element to generate a containing block for fixed-position elements, 90 | specifying that property in 'will-change' must cause the element to generate a containing block for fixed-position elements. 91 | 92 | If a non-initial value of a property would cause rendering differences on the element 93 | (such as using a different anti-aliasing strategy for text), 94 | the user agent should use that alternate rendering when the property is specified in 'will-change', 95 | to avoid sudden rendering differences when the property is eventually changed. 96 |
97 | 98 | 99 |
100 | For example, setting 'opacity' to any value other than 1 creates a stacking context on the element. 101 | Thus, setting ''will-change: opacity'' also creates a stacking context, 102 | even if 'opacity' is currently still equal to 1. 103 |
104 | 105 | The 'will-change' property has no direct effect on the element it is specified on, 106 | beyond the creation of stacking contexts and containing blocks as specified above. 107 | It is solely a rendering hint to the user agent, 108 | allowing it set up potentially-expensive optimizations for certain types of changes 109 | before the changes actually start occurring. 110 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | Look at the README 3 |

Look at the README

4 |

5 | I don't feel like duplicating this information between the README and the index page, 6 | so if you want to know the list of specs in this repository, 7 | look at the README. 8 |

9 | xoxo, Tab 10 | -------------------------------------------------------------------------------- /layout-transitions/index.bs: -------------------------------------------------------------------------------- 1 |

16 | 17 | 20 | 21 |

22 | Introduction

23 | 24 | [[CSS3-TRANSITIONS]] provide web authors with the ability to generate smooth transitioning effects 25 | when mutating the CSS of their web pages. 26 | However, the transitions that can be generated in this manner are limited in important ways, 27 | which make it difficult or impossible to use them in some cases. 28 | 29 | In particular, 30 | CSS Transitions only operate on computed style values, 31 | such as between ''100px'' and ''200px''; 32 | values that rely on layout, 33 | such as ''width: auto'', 34 | can't be used as the start or end of a transition. 35 | 36 | Furthermore, CSS Transitions only work over actual CSS property values, 37 | but some of aspects of an element one might wish to transition are derived from other properties 38 | rather than being directly specified. 39 | For example, the position and size of an element positioned with Grid Layout 40 | is derived from its [=grid-placement properties=], 41 | rather than being directly specified. 42 | An author can transition the [=grid-placement properties=], 43 | but that will merely cause the element to "skip" from cell to cell 44 | as its 'grid-row-start' and similar properties transition as integers; 45 | it won't have the desired effect of making the element smoothly move between its start and end position. 46 | Relatedly, there is no reasonable way to express a transition when an element enters or leaves the document. 47 | 48 | These shortcomings make [[CSS3-TRANSITIONS]] unsuitable for specifying transitions between laid out states of a web page. 49 | This specification provides a set of primitive JavaScript methods 50 | to enable transition-like graphical effects for complex layout changes. 51 | 52 |

53 | Motivating Examples

54 | 55 | Layout transition primitives can be used to programmatically control transitions between layout states. 56 | For example: 57 | 58 |
59 | To transition element myDiv from an initial laid out position to a new position: 60 | 61 |
 62 | 			myDiv.suspendPainting();
 63 | 			CSS.elementSources.myDivSnapshot = myDiv.snapshot();
 64 | 			var div = document.createElement('div');
 65 | 			div.style.position = 'absolute';
 66 | 			div.style.left = myDiv.offsetLeft + 'px';
 67 | 			// ...
 68 | 			div.style.backgroundImage = 'element(myDivSnapshot)';
 69 | 			document.body.appendChild(div);
 70 | 			// perform layout
 71 | 			div.animate({left: myDiv.offsetLeft, ... }, 1).source.onEnd(function() {
 72 | 				myDiv.resumePainting();
 73 | 				div.remove();
 74 | 			});
 75 | 		
76 |
77 | 78 | 79 |
80 | Layout transition primitives also allow element insertions and removals to be smoothed. 81 | 82 | In this example, afterDiv is the last div in a list. 83 | We wish to grow newDiv in-place before afterDiv, 84 | smoothly moving afterDiv down as we do so. 85 | 86 |
 87 | 			container.suspendPainting();
 88 | 			CSS.elementSources.afterDivSnapshot = afterDiv.snapshot();
 89 | 			// .. create and insert snapshot element (see previous example)
 90 | 			container.appendBefore(afterDiv, newDiv);
 91 | 			var bounds = newDiv.recastElement();
 92 | 			new ParGroup([
 93 | 				bounds.animate([{height: 0}, {height: bounds.height}], 1),
 94 | 				div.animate({top: afterDiv.top}, 1)
 95 | 			]).source.onEnd(function() {
 96 | 				myDiv.resumePainting();
 97 | 				div.remove();
 98 | 			});
 99 | 		
100 |
101 | 102 | 103 |
104 | When combined with [[CSS4-IMAGES]], 105 | layout transition primitves allow crossfade and transfade effects to be scripted. 106 | For example: 107 | 108 |
109 | 			myDiv.suspendPainting();
110 | 			CSS.elementSources.before = myDiv.snapshot();
111 | 			// .. create and insert snapshot element (see previous example)
112 | 			// perform layout
113 | 			CSS.elementSources.after = myDiv.snapshot();
114 | 			div.style.transition = 'background-image 1s';
115 | 			div.style.backgroundImage = 'element(after)';
116 | 			setTimeout(function() {
117 | 				myDiv.resumePainting();
118 | 				div.remove();
119 | 			}, 1000);
120 | 		
121 |
122 | 123 |

124 | IDL

125 | 126 | 127 | partial interface Element { 128 | void suspendPainting(); 129 | void resumePainting(); 130 | Promise<OpaqueImageSnapshot> snapshot(); 131 | ElementBounds recastElement(); 132 | void cancelRecast(); 133 | }; 134 | 135 | interface OpaqueImageSnapshot { 136 | }; 137 | 138 | interface ElementBounds { 139 | attribute DOMString left; 140 | attribute DOMString top; 141 | attribute DOMString width; 142 | attribute DOMString height; 143 | attribute DOMString transform; 144 | attribute DOMString transformOrigin; 145 | attribute DOMString opacity; 146 | attribute DOMString overflow; 147 | }; 148 | 149 | 150 | Issue: Ensure that ElementBounds implements Animatable, 151 | assuming that this idea makes it into the Web Animations specification. 152 | 153 |

154 | Suspending Painting - the suspendPainting() and resumePainting() methods

155 | 156 | The {{suspendPainting()}} and {{resumePainting()}} methods on elements 157 | allow an author to control whether an element "paints", 158 | or is displayed on the screen. 159 | This is similar to using the 'visibility' property, 160 | but more explicit and slightly more powerful. 161 | Like 'visibility' and unlike other properties such as 'display', 162 | the element is still laid out and takes up space on the page as normal 163 | even if it's not being painted. 164 | 165 | Note: Suspending the painting of an element is commonly used with the other methods in this specification, 166 | to get the original element "out of the way" while script is simulating a transition of the element with snapshots and recastings. 167 | 168 | When {{suspendPainting()}} is called on an element, 169 | the element's painting suspended flag must be set. 170 | When {{resumePainting()}} is called on an element, 171 | the element's [=painting suspended flag=] must be unset. 172 | 173 | When an element's [=painting suspended flag=] is toggled from unset to set, 174 | its subtree must be repainted. 175 | 176 | Issue: This is actually trying to introduce the notion that {{suspendPainting()}} is an entry in the style updates queue. 177 | How should this be worded? 178 | 179 | An element is suspended if its [=painting suspended flag=] is set, 180 | or if it has a parent element and that parent element is [=suspended=]. 181 | 182 | Whether the [=painting suspended flag=] is set or unset must not change if the element is added or removed from the document. 183 | 184 | When an element is [=suspended=], 185 | its generated box is invisible 186 | (fully transparent, nothing is drawn), 187 | but still affects layout. 188 | This is similar to the effects of ''visibility: hidden'' 189 | 190 | Note: Calling {{resumePainting()}} on an element which is [=suspended=] 191 | due to an ancestor having its [=painting suspended flag=] set will do nothing; 192 | the element's [=painting suspended flag=] is already unset. 193 | 194 |

195 | Snapshotting Elements - The snapshot() method

196 | 197 | The {{snapshot()}} method takes a "snapshot" of an element, 198 | returning an image of the element at that time 199 | (even if the element is currently [=suspended=]) 200 | which is useful in implementing layout transitions, 201 | as described in the Examples section of this document. 202 | 203 | When {{snapshot()}} is called on an element el, 204 | the user agent must perform the following steps: 205 | 206 |
    207 |
  1. 208 | Let snapshot be a newly-created {{OpaqueImageSnapshot}} object. 209 | Return snapshot, 210 | and complete the rest of these steps asynchronously. 211 | 212 |
  2. 213 | Create a new [=style-dependent action=] action 214 | which, when executed, 215 | captures the current rendering of el, 216 | associates the rendering with snapshot, 217 | and resolves snapshot's ready promise with undefined. 218 | 219 |
  3. 220 | Push action onto el's [=style updates queue=]. 221 |
222 | 223 | Issue: Rewrite this to return a promise for a snapshot, 224 | rather than sync-returning a snapshot that then has a ready promise. 225 | 226 | When asked to capture the current rendering of an element el, 227 | the user agent must produce 228 | the image that would be represented by an ''element()'' function referencing el at that moment, 229 | with the image having the same width and height as el does at that moment. 230 | If el is currently [=suspended=], 231 | for the purposes of generating this image it is treated as being not [=suspended=]. 232 | 233 | Note: Only the current element's [=suspended=] state is altered 234 | for the purposes of generating a snapshot image. 235 | If descendant elements are also marked as [=suspended=], 236 | then those elements will remain transparent in the snapshot. 237 | 238 | Note: The image does not necessarily have to be a raster bitmap, 239 | as the actual image data is never directly exposed to the page. 240 | For example, some user agents use an intermediate vector-like representation of an element 241 | before the rasterization step; 242 | this alternative representation may be produced instead, 243 | so that the image can be rendered accurately at any target size 244 | without scaling artifacts. 245 | 246 | Note: Due to the way the [=style updates queue=] works, 247 | if an author generates a snapshot 248 | before creating a new element and assigning the snapshot as a background image, 249 | it's guaranteed that there will be no FOUC (flash of unstyled content). 250 | Any other order might generate a FOUC, 251 | depending on timing and user-agent-specific behavior. 252 | 253 | Note: Snapshots never "expire" or otherwise become unusable, 254 | even if the element they are snapshotting is removed or deleted. 255 | 256 | 257 |

258 | Snapshots: the OpaqueImageSnapshot object

259 | 260 | {{OpaqueImageSnapshot}} objects are returned by the {{snapshot()}} method, 261 | and represent the rendering of an element at the time that {{snapshot()}} is called. 262 | 263 | For security reasons, 264 | the image data represented by an {{OpaqueImageSnapshot}} object is not obtainable by any means; 265 | the image can only be displayed indirectly, 266 | by using the {{OpaqueImageSnapshot}} object 267 | in conjunction with CSS's ''element()'' function 268 | and the {{elementSources}} map. 269 | 270 | An {{OpaqueImageSnapshot}} object might represent an image. 271 | If it does, it provides a [=paint source=], 272 | with the width, height, and appearance of the image it represents. 273 | 274 | When the {{ready()}} method of an {{OpaqueImageSnapshot}} snapshot is called, 275 | user agents must perform the following steps: 276 | 277 |
    278 |
  1. 279 | Let ready promise be a newly-created Promise. 280 | Return it, 281 | and perform the rest of these steps asynchronously. 282 | 283 |
  2. 284 | When snapshot represents an image, 285 | resolve ready promise with undefined. 286 |
287 | 288 |

289 | Is there any way for a snapshot to fail? 290 | Deleting the element before it's rendered? 291 | 292 |

293 | Recasting Painting - The recastElement() and cancelRecast() methods

294 | 295 | While snapshotting elements into static images 296 | is appropriate for many layout transitions, 297 | sometimes it is necessary to continuously lay out the element and its contents 298 | as it changes size and shape. 299 | However, the actual element can't be used for this purpose, 300 | as it's busy occupying space in the layout. 301 | Instead, a [=suspended=] element can have its painting recasted, 302 | rendering it at an explicitly-set size and position 303 | without moving it in the layout as far as the outer page is concerned. 304 | 305 | When the {{recastElement()}} method is called on an element el, 306 | the user agent must perform the following steps: 307 | 308 |
    309 |
  1. 310 | If the element is not currently [=suspended=], 311 | throw a ??? error 312 | and exit this algorithm. 313 | 314 |
  2. 315 | If the element already has an associated {{ElementBounds}} object, 316 | return that object 317 | and exit this algorithm. 318 | 319 |
  3. 320 | Create a new {{ElementBounds}} object bounds 321 | associated with el. 322 | [=Initialize the element bounds=]. 323 | Return bounds. 324 |
325 | 326 | While an element has an associated {{ElementBounds}} object, 327 | it is recast. 328 | 329 | If an element is [=recast=], 330 | and stops being [=suspended=] for any reason, 331 | it must cancel recast, 332 | which causes its associated {{ElementBounds}} object to no longer be associated with it. 333 | 334 | While an element is [=recast=], 335 | it must be laid out twice. 336 | The first is as normal for a [=suspended=] element, 337 | to establish the space that the element takes up in the page. 338 | 339 | The second treats the element as [=absolutely positioned=] 340 | with the [=initial containing block=] as its containing block, 341 | and the element's 'width', 'height', 'left', 'top', 'opacity', and 'transform' properties 342 | set to the corresponding values from the element's associated {{ElementBounds}} object 343 | rather than the values obtained from the cascade. 344 | Additionally, the element's 'right' and 'bottom' properties must be treated as ''right/auto'' for this layout. 345 | The element must then render as normal based on the results of this layout. 346 | 347 | Modifying the element's associated {{ElementBounds}} object 348 | must cause the element to perform its second layout with the new values, 349 | as if this were an ordinary style change. 350 | 351 | Querying the style of any properties on the element 352 | must return the results of the first layout, 353 | not the second. 354 | 355 | Note: Note that while an element is [=recast=], 356 | any additional calls to {{recastElement()}} will return the same {{ElementBounds}} object. 357 | 358 | When the {{cancelRecast()}} method is called on an element, 359 | the user agent must [=cancel recast=] on it. 360 | 361 | Removing a [=recast=] element from the document 362 | causes that element to [=cancel recast=]. 363 | However, atomic moves within the same document do not [=cancel recast=]. 364 | 365 | Note: recasting an element does not alter the suspended state of 366 | descendents of that element. 367 | 368 |

369 | The ElementBounds Object

370 | 371 | The {{ElementBounds}} object controls the position and size of a [=recast=] element's rendering. 372 | It is returned by calling {{recastElement()}} on an element. 373 | 374 | When asked to initialize the element bounds for an element el 375 | and an {{ElementBounds}} object eb, 376 | user agents must perform the following steps: 377 | 378 |
    379 |
  1. 380 | Lay out the element as normal. 381 | 382 |
  2. 383 | Set the {{ElementBounds/width}}, 384 | {{ElementBounds/height}}, 385 | {{ElementBounds/opacity}}, 386 | and {{ElementBounds/transform}} attributes of eb 387 | to the used values of the corresponding properties from el. 388 | 389 |
  3. 390 | Set the {{ElementBounds/left}} and {{ElementBounds/top}} attributes of eb 391 | to the offsets of el's left and top edges, respectively, 392 | relative to the top left corner of the initial containing block. 393 |
394 | 395 |

396 | Appendix A: The Style Updates Queue

397 | 398 | Note: This section probably isn't best placed here, 399 | but I need some terms defined that aren't currently defined. 400 | 401 | Each element in a document is associated with a style updates queue, 402 | containing [=style updates=] and [=style-dependent actions=]. 403 | A style update is a pending currently-unapplied change made to the style of an element on the page 404 | which might have an effect on the style, layout, or rendering of the element. 405 | A style-dependent action is an operation which relies on the element's style, layout, and/or rendering 406 | being fully up-to-date. 407 | 408 | Whenever a change is made to the page's style that may affect an element, 409 | a [=style update=] must be pushed onto the element's [=style updates queue=]. 410 | The element's style, layout, and/or rendering must not be updated 411 | unless a corresponding [=style update=] is at the front of the [=style updates queue=]. 412 | When a [=style update=] is applied, 413 | it must be popped from the queue. 414 | 415 | Similarly, [=style-dependent actions=] must not be executed 416 | unless they are at the front of the [=style updates queue=]. 417 | When they are executed, 418 | they must be popped from the queue. 419 | 420 | User agents may delay applying [=style updates=] as long as they consider reasonable 421 | so as to batch any work caused by updating styles, layout, and rendering. 422 | User agents should prioritize applying [=style updates=] 423 | that precede a [=style-dependent action=] 424 | when a [=style-dependent action=] is in the queue. 425 | -------------------------------------------------------------------------------- /qrcode/index.bs: -------------------------------------------------------------------------------- 1 | 15 | 16 | Introduction {#intro} 17 | ===================== 18 | 19 | Representing relatively small amounts of data in a machine-readable format 20 | has been important for decades. 21 | The humble UPC barcode format, 22 | for instance, 23 | allows storing numeric values 24 | up to ten decimal digits. 25 | 26 | As time has passed, tho, we've required larger amounts of data to be represented 27 | (even if the amounts are still modest; a few kilobytes at most), 28 | and better error correction 29 | (UPC barcodes can correct for *one* wrong digit, but no more). 30 | Many approaches have been proposed and even adopted in various industries, 31 | but the QR Code, 32 | first invented in Japan in the 90s for labeling parts in semi-automated factories, 33 | has emerged as the clear leader in overall usage across the world in recent years. 34 | 35 | While QR Code images are very usable in practice, 36 | they're difficult to *create*; 37 | beyond the ordinary difficulties of creating any image file programmatically, 38 | the QR format is non-trivial to follow, 39 | and the error-correction parts of the format are complex. 40 | However, all the devices a user can expect to *see* a QR Code 41 | have access to libraries for creating them. 42 | 43 | This specification defines a new QRCODE image format, 44 | and its associated MIME type `image/qrcode`, 45 | which represents the content of a QR code 46 | in a simple, human-readable, hand-authorable format. 47 | User agents, such as browsers, that recieve QRCODE images 48 | are expected to render them as QR codes. 49 | 50 | Notes {#notes} 51 | =============== 52 | 53 | Parameters of a QR code: 54 | * "version": a number between 1 and 40, dictating the overall size in pixels/"modules". The eventual size of the QR code is version * 4 + 17 modules, plus additional margin space around the code (typically, at least one module in width). 55 | * error-correction level: what level of error correction is applied to the payload, dictating how much of the code can be lost/obscured/misread without corrupting the code itself. Four values, corresponding to "low" (7% recoverable loss), "medium" (14%), "quartile" (25%), or "high" (30%). 56 | * mask type: to help avoid large black or white "fields" in the code that make it harder to read or recognize, some of the data pixels can be inverted. There are 8 mask types, dictating which pixels are inverted and should be read as their opposite value. 57 | * encoding type: how to interpret the bits in the payload. Three commonly-used value: "numeric", "alphanumeric", and "bytes". 58 | * Numeric is the digits 0-9. 59 | * Alphanumeric is 0-9, A-Z (uppercase only), and some punctuation. Aka a subset of ASCII. 60 | * Bytes has been defined by specs as two different byte-based character encodings. In practice, treating it as UTF-8 seems to be modern practice and is widely recognized by scanners (possibly heuristically). 61 | 62 | Additional params I need to introduce: 63 | 64 | * module size: a number of CSS pixels dictating the side length of a module. 65 | * image size: a number of CSS pixels dictating the overall image size (which dictates the module size). 66 | * using both module and image size would just ignore one of them, I guess. Maybe use the larger one. 67 | * margin?: a CSS pixel size for the safe area around the code 68 | 69 | Image Format {#format} 70 | ============ 71 | 72 | Every QRCODE image must begin with the bytes 73 | `51 52 43 4f 44 45 7b` 74 | (spelling "`QRCODE{`" in ASCII). 75 | Following that are zero or more non-`7d` bytes 76 | (the parameter bytes), 77 | followed by a `7d` byte ("}" in ASCII), 78 | optionally followed by `0d 0a` bytes (CR and NL in ASCII), 79 | followed by zero or more bytes with any value 80 | (the payload bytes). 81 | 82 | A QRCODE image that does not follow this byte format is [=invalid=]. 83 | 84 |
85 | Thus, a valid QRCODE file might be 86 | QRCODE{}https://example.com, 87 | which will be rendered as QR Code image 88 | containing a link to example.com. 89 | 90 | Alternately, the link could be rendered on a separate line for readability, 91 | like: 92 | 93 |
 94 | 		QRCODE{}
 95 | 		https://example.com
 96 | 	
97 | 98 | This is particular useful if several parameters are provided, 99 | like: 100 | 101 |
102 | 		QRCODE{version=5;error=low;mask=3;modulesize=5;margin=2}
103 | 		https://example.com
104 | 	
105 |
106 | 107 | Parameters {#parameters} 108 | ---------- 109 | 110 | The [=parameter bytes=] are interpreted into the [=QR code parameters=], 111 | which affect how the QR code image is generated. 112 | The format is intentionally identical to how MIME-type parameters are interpreted. 113 | 114 |
115 | To parse parameter bytes |bytes| 116 | execute the following steps. 117 | It returns either [=QR code parameters=], 118 | or failure. 119 | 120 | 1. Let |str| be the result of [=isomorphic decoding=] |bytes|. 121 | Let |parameters| be an empty [=QR code parameters=]. 122 | 123 | 2. [=string/Strictly split=] |str| on the delimiter U+003B SEMICOLON (;), 124 | and let |param strings| be the result. 125 | 126 | 3. [=list/For each=] |param string| of |param strings|: 127 | 1. 128 |
-------------------------------------------------------------------------------- /respimg/images/difimages.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tabatkins/specs/c492931b1458ff5dc84a814805093763fcf3e3bd/respimg/images/difimages.jpg -------------------------------------------------------------------------------- /respimg/images/viewport_selection_mob_first.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tabatkins/specs/c492931b1458ff5dc84a814805093763fcf3e3bd/respimg/images/viewport_selection_mob_first.jpg -------------------------------------------------------------------------------- /svg-params/index.bs: -------------------------------------------------------------------------------- 1 | 13 | 14 | 21 | 22 | Introduction {#intro} 23 | ===================== 24 | 25 | SVG is stylable with CSS, 26 | and when used inline in HTML, 27 | this capability can be very useful. 28 | For example, an SVG icon can take on a different color based on whether the user is hovering it or not, 29 | just by appling a '':hover'' rule to it that changes the 'fill' property. 30 | 31 | When the SVG is referenced in a way that doesn't allow selectors or CSS inheritance from the outer page to apply to it 32 | (such as embedding it via <{img}> or <{iframe}> in HTML), 33 | though, this functionality is lost. 34 | The only way to change the display of such "external" SVG images 35 | is to produce several of them, 36 | and change which image you're referencing. 37 | This incurs delay on the page as a new resource is downloaded, 38 | and disallows dynamic effects like CSS Transitions. 39 | 40 | SVG Parameters are a way to set CSS custom properties on an "external" SVG image, 41 | by passing them through a special fragment scheme on the URL. 42 | This gives a limited, but powerful, subset of the customizability that "inline" SVG images have 43 | to "external" SVG images. 44 | 45 | Setting an SVG Parameter {#setting} 46 | =================================== 47 | 48 | To "set" an SVG Parameter, 49 | a special "fragment identifier" must be used in the fragment of the URL used to reference. 50 | Several examples of existing "fragment identifiers" for SVG documents can be found in the SVG 1.1 specification. 51 | 52 | The syntax of an SVG parameter fragment identifier is: 53 | 54 |
param( <> <> )
55 | 56 | (using the CSS value definition syntax). 57 | 58 |
59 | For example, to set the "--text-color" custom property of an SVG image to ''blue'', 60 | one can reference the image with a url like “http://example.com/image.svg#param(--text-color%20blue)”. 61 |
62 | 63 | If passing multiple parameters to an image, 64 | additional param() functions must be appended to the URL. 65 | If multiple param() functions specify the same <>, 66 | the custom property is set to the value of the last one. 67 | 68 |
69 | For example, if the image from the previous example also used a "--bg-color" custom property, 70 | it could be referenced with a url like “http://example.com/image.svg#param(--text-color%20blue)param(--bg-color%20white)”. 71 |
72 | 73 | Note: Spaces, and some other characters that might be valid in CSS syntax, 74 | are not technically valid in URLs. 75 | In some contexts, 76 | you might need to escape those characters to form a valid URL. 77 | In most cases, though, 78 | such as HTML's <{a}> element or CSS's ''url()'' function, 79 | spaces are accepted and do not need to be escaped. 80 | 81 | When a valid param() function is encountered in the fragment referencing an SVG document, 82 | it sets the initial value of the given custom property to the given <>. 83 | (By default, the initial value of a custom property is an invalid value.) 84 | 85 | Setting via the CSS ''url()'' Function {#setting-url} 86 | ----------------------------------------------------- 87 | 88 | When referencing an SVG image via CSS, 89 | the param() function can be used in the ''url()'' function. 90 | But a common use-case is passing in values of the page's own custom properties; 91 | for example, a page might use a ''--primary-color'' custom property, 92 | and want to make an SVG image match. 93 | There's no way, however, to integrate the value of a custom property in CSS into the URL passed to the ''url()'' function. 94 | 95 | To accomodate this, 96 | this specification defines a new <>, 97 | the ''param()'' function: 98 | 99 |
param() = param( <> <> )
100 | 101 | Note: You may recognize this as identical to the syntax of the param() fragment identifer. 102 | 103 | Similarly to the param() fragment identifier, 104 | the ''param()'' <> 105 | sets the initial value of the referenced custom property to the passed <>. 106 | Also similarly to the fragment identifier, 107 | if multiple ''param()'' functions reference the same custom property, 108 | the last one wins. 109 | 110 |
111 | For example, 112 | if the site is using a ''--primary-color'' custom property to theme its elements with, 113 | and wanted an SVG background using a ''--color'' custom property to reflect it, 114 | it could write: 115 | 116 |
117 | 		.foo {
118 | 			background-image: url("http://example.com/image.svg" param(--color var(--primary-color)));
119 | 		}
120 | 	
121 |
122 | 123 | Using SVG Parameters {#using} 124 | ============================= 125 | 126 | Within an SVG image, 127 | any SVG parameters set the initial value of the corresponding custom properties. 128 | They can then be used directly in any CSS property 129 | via the CSS ''var()'' function. 130 | 131 |
132 | For example, if an SVG image wanted to expose a ''--color'' parameter, 133 | it could use it like: 134 | 135 |
136 | 		<svg>
137 | 			<g style="fill: var(--color);">
138 | 				<path d="..." />
139 | 			</g>
140 | 		</svg>
141 | 	
142 |
143 | 144 | Issue: Can it be used in presentation attributes? 145 | 146 |
147 | It's usually a good idea to make your SVG image usable even if no parameters are given, 148 | by providing "default values" for each of the custom properties. 149 | There are several ways to do this. 150 | 151 | 1. On each ''var()'' function, provide a fallback value, like ''fill: var(--color, blue)''. 152 | 2. If the custom property is going to be used a lot, 153 | such that providing a fallback for each individual ''var()'' is troublesome, 154 | store the custom property in a different name while invoking the default, 155 | like: 156 | 157 |
158 | 			:root {
159 | 				--color2: var(--color, blue);
160 | 			}
161 | 		
162 | 163 | In this example, if ''--color'' is provided via an SVG parameter, 164 | ''--color2'' will receive its value. 165 | If not, it will recieve the default ''blue'' value. 166 | In either case, ''--color2'' can be used in the SVG image's stylesheet unconditionally, 167 | secure in the knowledge that it will always have a value. 168 | 3. In a future level of the Custom Properties specification [[CSS-VARIABLES]], 169 | some "parent's value" functionality will be available to make the previous suggestion more usable: 170 | 171 |
172 | 			:root {
173 | 				--color: var(parent --color, blue);
174 | 			}
175 | 		
176 | 177 | (This is an example syntax, and is not yet final.) 178 | 179 | By invoking the value of the --color property on the parent 180 | (which, on the root element, refers to the initial value), 181 | an author can avoid self-reference loops while retaining the same custom property name. 182 |
183 | -------------------------------------------------------------------------------- /unit-problems/index.bs: -------------------------------------------------------------------------------- 1 | 10 | 11 | Introduction {#intro} 12 | ===================== 13 | 14 | The current [[css-typed-om-1]] approach to unitted valued is incoherent and inextensible. 15 | There are three distinct object "shapes" employed right now, 16 | and we're only handling two "types" of units - lengths and angles. 17 | The inconsistency makes it difficult for authors to predict how to interact with unitted values, 18 | and limits our ability to innovate in the future. 19 | The overall approach means we have to invent a large number of different interfaces 20 | to handle all the different types of unitted values CSS has, 21 | and completely fails to handle the planned addition 22 | of custom unit types. 23 | 24 | Inconsistency {#inconsistency} 25 | ------------------------------ 26 | 27 | We're currently using three different "shapes" for unitted value objects: 28 | 29 | 1. "Simple" lengths (corresponding to values like `5px` or `2em`) 30 | have a {value, unit} structure. 31 | 32 | 2. "Complex" lengths (corresponding to a `calc()` expressions) 33 | have a {px, pc, in, em, vw, ...} structure, 34 | where each field is an independent entry in the sum-of-values 35 | that makes up the calc(). 36 | 37 | 3. "Simple" angles have a {deg, rad, grad, turn} structure, 38 | where each field is linked; 39 | they all reflect a hidden internal value, 40 | so you can write to any field 41 | and then read the equivalent value in a different unit 42 | from another field. 43 | (Such as `x.deg = 180; print(x.turn) // .5`.) 44 | 45 | 46 | Explosion of Types {#type-explosion} 47 | ------------------------------------ 48 | 49 | While <> has two types-- 50 | simple and `calc()`-- 51 | <> only has one, 52 | because all <>-related `calc()`s can be resolved into a "simple" angle currently. 53 | 54 | This ignores the possibility of a future property using <> and <> together 55 | in a way that isn't immediately resolvable 56 | (for example, audio properties 57 | that use % to convey left-to-right progress along the audio stage, 58 | which has an unknown width), 59 | or the addition of an <> unit that doesn't have a fixed conversion ratio 60 | (like ''em'' or ''vw'' has for <>). 61 | 62 | The spec also currently ignores all the *other* types of units, 63 | which will need to be represented in the Typed OM at some point. 64 | They'll result in a number of additional interfaces when we support them. 65 | These interfaces will all need to decide whether they look like {{CSSSimpleLength}} or {{CSSAngleValue}}, 66 | sometimes without any information about the type family 67 | (for example, the <> type has only a single unit in it; 68 | which variant should we choose?). 69 | 70 | 71 | No User Extensibility {#no-extensibility} 72 | ----------------------------------------- 73 | 74 | One of the recorded plans for a future Houdini API 75 | is to allow authors to define custom units for themselves. 76 | For example, 77 | there's still a mess of length units 78 | used by publishers 79 | which we don't particularly want to add to core CSS 80 | (we've already added several, like `pc` and `q`), 81 | but which would be useful for authors using CSS for publishing. 82 | 83 | The {{CSSSimpleLength}} interface is compatible with custom units-- 84 | you just express the custom unit in the `.type`. 85 | (We'll have to relax the attribute into a DOMString, 86 | and the constructor into `(LengthType or DOMString)`, 87 | but that's easy.) 88 | 89 | The {{CSSCalcLength}} interface is also able to be extended to handle custom units; 90 | we'll have to extend it to handle *complex* units already 91 | (when we allow unit algebra), 92 | and a similar approach will allow arbitrary unit extensions 93 | (a Map hanging off the side which contains arbitrary additional entries). 94 | 95 | But the {{CSSAngleValue}} interface doesn't work at all, 96 | at least not without some severe awkwardness. 97 | If you hang a map off the side, 98 | you need to have magical updating going on whenever you set a value, 99 | which is difficult to spec right now 100 | (because Maps don't have a natural way to observe them). 101 | 102 | And this doesn't cover brand new units, 103 | which don't map to any of the existing types, 104 | at all. 105 | They don't have a corresponding OM class to live under. 106 | 107 | 108 | Proposal {#proposal} 109 | ==================== 110 | 111 |
112 | interface CSSDimension {
113 | 	CSSDimension add(CSSDimension value);
114 | 	CSSDimension subtract(CSSDimension value);
115 | 	CSSDimension multiply(double value);
116 | 	CSSDimension divide(double value);
117 | 	static CSSDimension from(DOMString cssText);
118 | 	static CSSDimension from(double value, DOMString type);
119 | 	CSSDimension to(DOMString type);
120 | };
121 | 
122 | interface CSSSimpleDimension : CSSDimension {
123 | 	attribute double value;
124 | 	attribute DOMString type;
125 | };
126 | 
127 | interface CSSCalcLength : CSSDimension {
128 | 	attribute double? px;
129 | 	attribute double? percent;
130 | 	// ...
131 | 	static CSSDimension from(optional CSSCalcLengthDictionary dictionary);
132 | };
133 | 
134 | interface CSSCalcAngle : CSSDimension {
135 | 	attribute double deg;
136 | 	attribute double rad;
137 | 	attribute double grad;
138 | 	attribute double turn;
139 | 	static CSSDimension from(optional CSSCalcAngleDictionary dictionary);
140 | };
141 | 
142 | // same for <time> and <frequency>,
143 | // the only other types allowed in calc() currently
144 | 
145 | 146 | *All* unitted values share the {{CSSSimpleDimension}} interface. 147 | 148 | Arithmetic on {{CSSDimension}} values 149 | throws if the value types aren't compatible 150 | (just like, today, they'd throw if you passed a {{CSSAngleValue}} 151 | to {{CSSLengthValue/add()}}). 152 | Otherwise, it returns the appropriate {{CSSCalc*}} subclass. 153 | 154 | The new {{CSSDimension/to()}} method converts from one unit to another. 155 | It throws if the types aren't convertible 156 | (such as `px` to `deg`, but also `px` to `em`), 157 | or if the object is a {{CSSCalc*}} 158 | and some of its non-zero specified values aren't convertible 159 | (so `CSSCalcLength({px:5, in:1}).to("px")` is fine, 160 | but `CSSCalcLength({px:5, em:1}).to("px")` throws). 161 | Otherwise, 162 | it returns a new {{CSSSimpleDimension}} with the specified unit. 163 | 164 | Consistency {#consistency} 165 | -------------------------- 166 | 167 | All unitted values now use the same interface structure. 168 | You don't need to remember whether something is a <> or <> 169 | to know how to get its value out, 170 | or just guess at less-used unit types; 171 | they're all `.value`. 172 | 173 | All types that are allowed in ''calc()'' 174 | now have corresponding interfaces, 175 | again all with the same structure. 176 | As we expand ''calc()'' to allow new types, 177 | we'll add new classes. 178 | 179 | All types that can be converted 180 | do so with a standard mechanism 181 | (the {{to()}} method), 182 | which is short and easy to use. 183 | 184 | 185 | Minimal Types {#minimal-types} 186 | ------------------------------ 187 | 188 | Rather than needing separate classes for every new kind of unit 189 | (and who knows about user-defined units), 190 | we have a single class for all "simple" unitted values, 191 | and one class per variety of type allowed in calc(), 192 | which is a small group that grows slowly. 193 | 194 | 195 | User Extensibility {#extensibility} 196 | ----------------------------------- 197 | 198 | When user-defined units arrive, 199 | they'll be handled with the exact same mechanism as any other unit-- 200 | the author will just create a CSSSimpleDimension for them. 201 | 202 | For calc()-allowed types, 203 | all {{CSSCalc*}} classes will use the same mechanism 204 | to represent user-defined units 205 | (a Map hanging off the side). 206 | 207 | Cons {#cons} 208 | ------------ 209 | 210 | * Converting between the types of angles is somewhat more difficult. 211 | Before you just read the attribute you want, like `x.rad`, 212 | now you have to do `x.to("rad").value`. 213 | (On the plus side, you can now convert between all the absolute length units, 214 | which wasn't previously possible.) 215 | 216 | * You could previously tell by standard JS type-testing 217 | whether a given unitted value was a length or angle. 218 | That's no longer possible unless it's a calc() value; 219 | you have to be able to infer that from the unit now. 220 | 221 | 222 | 223 | Alternatives {#alternatives} 224 | ============================ 225 | 226 | Instead of the calc() interfaces having explicit attributes for their known units, 227 | with extra Maps eventually hanging off of them 228 | for user-defined units 229 | and complex units, 230 | we could instead just make them Maplike. 231 | *All* units would then be treated identically; 232 | you `.get()` and `.set()` them, 233 | and can iterate over it to get the values. 234 | 235 | This also lets us avoid any name collisions between CSS units 236 | and future attributes or methods on the objects; 237 | for example, in the current design we wouldn't be able to ever create a `to` unit, 238 | as it would clash with the {{to()}} method on the prototype. 239 | --------------------------------------------------------------------------------