scrollbar.css 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /* Scrollbar skin: the sole consumer of the four --dsw-alias-scrollbar-*
  2. * tokens. Without it every scrolling region renders the UA scrollbar, which
  3. * ignores the theme — a light native bar over the dark palette.
  4. *
  5. * The rules sit on `body`, not `html`: design-platform.css declares the
  6. * --dsw-alias-* tokens on `body` (and the dark overrides on
  7. * `body[data-ds-dark-theme]`), and custom properties only inherit downward,
  8. * so an `html` rule resolves them to the guaranteed-invalid value and
  9. * `scrollbar-color` falls back to `auto`.
  10. *
  11. * Surfaces pick their elevation by rebinding --dsh-scrollbar-thumb{,-hover}:
  12. * the l1 pair here is the base-surface default, and an elevated surface
  13. * (menu, popover, dialog) rebinds to the l2 pair on its own container. Both
  14. * rendering paths below read the indirection, so one rebind reaches whichever
  15. * path the engine took. */
  16. body {
  17. --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l1);
  18. --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l1);
  19. /* The WebKit bar's layout width, mirrored by the ::-webkit-scrollbar rule
  20. below. A surface that must align itself beside a space-consuming bar
  21. (ConversationRoot's overlay composer seat) reads this instead of
  22. hardcoding the number. */
  23. --dsh-scrollbar-width: 8px;
  24. }
  25. /* The two paths are mutually exclusive, and the gate is load-bearing rather
  26. than defensive. A non-`auto` `scrollbar-width` or `scrollbar-color` makes
  27. Chromium and Safari drop every `::-webkit-scrollbar*` rule for that
  28. element, including `::-webkit-scrollbar-thumb:hover` — measured in chromium
  29. as an 8px `::-webkit-scrollbar` width taking effect on its own and being
  30. ignored as soon as `scrollbar-width: thin` is added. Declaring both
  31. unconditionally therefore leaves the hover tokens with no rendering at all,
  32. because the engines that implement the hover pseudo-element are exactly the
  33. ones the standard properties silence, and Firefox has no hover
  34. pseudo-element to fall back on.
  35. `not selector(::-webkit-scrollbar)` is true only where the pseudo-element
  36. is unimplemented, so Firefox takes the standard path and WebKit-based
  37. engines take the pseudo-element path. An engine too old for the
  38. `selector()` function makes the condition invalid, which evaluates false
  39. and selects the pseudo-element path — the correct side for the pre-16.4
  40. Safari that is the realistic case. */
  41. @supports not selector(::-webkit-scrollbar) {
  42. /* Declared on every element rather than inherited from `body`. Inheriting
  43. would pass down the COLOUR already substituted at `body`, so a descendant
  44. rebinding --dsh-scrollbar-thumb could not change it; re-declaring makes
  45. each element substitute the variable as it sees it, which is what gives
  46. an elevated surface a working rebind. `scrollbar-width` is not an
  47. inherited property at all, so it needs the per-element declaration
  48. regardless.
  49. No hover counterpart exists on this path: `scrollbar-color` states one
  50. thumb colour and the engine derives its own hover treatment. */
  51. body,
  52. body * {
  53. scrollbar-width: thin;
  54. scrollbar-color: var(--dsh-scrollbar-thumb) transparent;
  55. }
  56. }
  57. /* Not gated in turn: an engine that does not implement these pseudo-elements
  58. drops the rules as unknown selectors, so the gate would only restate what
  59. selector matching already does. Not inherited either, hence the unscoped
  60. selectors. */
  61. ::-webkit-scrollbar {
  62. width: 8px;
  63. height: 8px;
  64. }
  65. /* Track stays transparent so the thumb reads against whatever surface scrolls
  66. under it; only the thumb carries a token colour. */
  67. ::-webkit-scrollbar-track {
  68. background: transparent;
  69. }
  70. ::-webkit-scrollbar-thumb {
  71. border-radius: 4px;
  72. background: var(--dsh-scrollbar-thumb);
  73. }
  74. ::-webkit-scrollbar-thumb:hover {
  75. background: var(--dsh-scrollbar-thumb-hover);
  76. }
  77. /* Both scrollbars meeting in a corner: no separate token, so the corner
  78. matches the transparent track rather than the UA's opaque default. */
  79. ::-webkit-scrollbar-corner {
  80. background: transparent;
  81. }