WebCraft

Catalogue

Every element, with the caveat that comes with it

88 interface elements, each rendered live on its own page with the source and the one thing that breaks it.

  1. Text the find bar can still reach hidden="until-found" disclosure
  2. A dialog opened with no script at all command / commandfor dialog
  3. A select you can finally style appearance: base-select form
  4. A bar sized by its own data attribute attr() type() layout
  5. A stagger that survives a new item sibling-index() motion
  6. Card rows that line up across cards subgrid layout
  7. A sticky header that knows it is stuck scroll-state(stuck) scroll
  8. Hover that stays off touchscreens @media (hover: hover) hover
  9. The filled half of a range track ::-moz-range-progress form
  10. Numbering the browser keeps for you counters() text
  11. An underline you actually drew text-underline-offset type
  12. Type on rails, not on stops clamp() type
  13. The fixed element that stopped meaning it fixed under transform layout
  14. A shadow that knows the shape filter: drop-shadow() surface
  15. The long word that will not bend overflow-wrap: anywhere text
  16. An ellipsis is three declarations, not one text-overflow: ellipsis text
  17. Less motion is not no motion prefers-reduced-motion motion
  18. A layout drawn as a picture of itself grid-template-areas layout
  19. Four faint shadows beat one dark one box-shadow ×4 surface
  20. Five colours out of one token oklch(from …) surface
  21. Hidden from eyes, kept for readers .visually-hidden a11y
  22. The link only keyboards ever meet skip link + :focus a11y
  23. The same two colours, mixed two ways color-mix() surface
  24. Why the last row stretches, and how to stop it auto-fit vs auto-fill layout
  25. Centring with no flex and no grid align-content (block) layout
  26. An edge that fades instead of cutting mask-composite: intersect scroll
  27. A vertical label that does not break the box writing-mode: vertical-rl layout
  28. A heading that sits on its own cap height text-box: trim-both type
  29. Type that inverts itself over anything mix-blend-mode: difference surface
  30. An outline that does not eat the letters paint-order: stroke fill type
  31. A drop cap the browser measures for you initial-letter text
  32. Stripes that stay right when rows are filtered :nth-child(of S) table
  33. One declaration that covers both themes light-dark() surface
  34. Carousel dots the browser draws itself ::scroll-marker scroll
  35. A tooltip that follows its anchor with no JavaScript anchor-name + position-area layout
  36. Styles that stop at a boundary you name @scope layout
  37. Animating height to auto, finally interpolate-size motion
  38. A spring in the easing function linear() motion
  39. Type that wraps to a curve, not a box shape-outside type
  40. Reveal on scroll, with no observer animation-timeline: view() motion
  41. Clipping that leaves sticky alone overflow: clip layout
  42. A dropdown a keyboard can hold open :focus-within a11y
  43. Avatars that never squash object-fit: cover media
  44. An underline that slides in background-size hover
  45. An analog clock wound by one line of JavaScript animation-delay: -43200s motion
  46. The logo that never hits the corner animation + cqw motion
  47. resize keeps writing after max-width stops it resize + max-width layout
  48. A gradient border that keeps its corners background + padding surface
  49. A spotlight that follows the cursor radial-gradient at var() hover
  50. A progress bar tied to scroll, with no JavaScript animation-timeline: scroll() motion
  51. A table header that stays put position: sticky table
  52. Cut a paragraph to three lines -webkit-line-clamp text
  53. A textarea that grows as you type field-sizing: content form
  54. An accordion with no JavaScript <details name> disclosure
  55. A focus ring for keyboards only :focus-visible a11y
  56. A wide table that keeps its first column position: sticky (inline) table
  57. Shadows that show there is more to scroll background-attachment: local scroll
  58. A segmented control with a sliding indicator :has() + translate control
  59. A skeleton that does not lie about the layout @keyframes + gradient loading
  60. A menu button that turns into a close button aria-expanded menu
  61. A switch that is still a checkbox appearance: none form
  62. A marquee that never jumps translateX(-50%) motion
  63. Frosted glass over anything backdrop-filter surface
  64. Type painted with a gradient background-clip: text type
  65. A range slider you can actually style ::-webkit-slider-thumb, ::-moz-range-thumb form
  66. A card that tips towards the cursor perspective + rotate hover
  67. A gradient angle that actually animates @property motion
  68. A card that reads its own container, not the window @container layout
  69. Type that scales with its container cqi layout
  70. Boxes that keep their proportions aspect-ratio layout
  71. A heading that breaks where a typesetter would text-wrap: balance type
  72. Paragraphs with no orphan last line text-wrap: pretty type
  73. Hyphenation in a narrow column hyphens: auto type
  74. An error state that waits its turn :user-invalid form
  75. Native controls in your palette accent-color form
  76. A label that floats out of the way :placeholder-shown form
  77. A carousel the browser drives scroll-snap-type scroll
  78. Scrolling that stops at the edge overscroll-behavior scroll
  79. Anchor links that clear a sticky header scroll-padding-top scroll
  80. A wrapper that knows its input is wrong :has() state
  81. Hovering one row quiets the others :has() + :not() hover
  82. A layout that changes when the list gets long :has(:nth-child()) layout
  83. A modal that traps focus for you showModal() dialog
  84. A popover with no JavaScript at all popovertarget dialog
  85. A section the page cannot reach inert a11y
  86. Animating something in from display: none @starting-style motion
  87. The exit animation, which is the hard half allow-discrete motion
  88. Reordering a list without it jumping startViewTransition() motion