CHA-CSS(7)

πŸ“¦
version 0.5.0 Β· 3 versions
, in arch rolling

πŸ’… CSS in Chawan πŸ’…

okay bestie, this is the CHA-CSS(7) manual page from the Miscellaneous Information Manual, and it's literally all about the CSS that Chawan supports, plus its proprietary extensions and where it deviates from standards. no cap.

This doc describes the CSS features supported by Chawan, as well as its proprietary extensions and deviations from standards.

If you discover a deviation that is not covered by this document, please open a ticket at https://todo.sr.ht/~bptato/chawan.


✨ Standard properties ✨

here’s the list of supported standard properties, with lil notes on values that aren’t implemented yet:

  • align-items β€” flex only; baseline is treated as flex-start
  • align-self β€” see above
  • background-color β€” see color
  • background-image β€” displays placeholders only
  • border-collapse
  • border-*-style, border-*-color, border-*-width β€” but see borders
  • border-spacing
  • bottom
  • box-sizing
  • caption-side
  • clear
  • color β€” hex values, colors except system keywords, and functions rgb, rgba, hsl, hsla, oklab, oklch; see limitations on relative colors (β€œfrom” keyword) below
  • content β€” string, (no-)open/close-quote, counter()
  • counter-increment
  • counter-reset
  • counter-set
  • display β€” block, inline-block, list-item, table, inline-table, table-*, flex, inline-flex, flow-root, as well as multi-keyword aliases (including list-item variants)
  • flex-basis β€” but content not supported
  • flex-direction
  • flex-grow
  • flex-shrink
  • flex-wrap
  • float
  • font-size β€” ignored; only for JS compatibility
  • font-style β€” oblique interpreted as italic
  • font-weight β€” numeric properties > 500 interpreted as bold, others as regular
  • height
  • justify-content β€” flex only
  • left
  • list-style-position
  • list-style-type β€” but no custom list styles
  • margin-bottom
  • margin-left
  • margin-right
  • margin-top
  • max-height
  • max-width
  • min-height
  • min-width
  • opacity β€” hacky; only works with opacity: 0
  • overflow-x β€” see below on scrollbars
  • overflow-y β€” see below on scrollbars
  • padding-bottom
  • padding-left
  • padding-right
  • padding-top
  • position β€” see below for sticky and fixed
  • quotes
  • right
  • text-align
  • text-decoration β€” none, underline, overline, line-through
  • text-transform
  • top
  • vertical-align
  • visibility
  • white-space
  • width
  • word-break
  • z-index

πŸŽ€ Shorthands πŸŽ€

  • all
  • margin
  • padding
  • border, border-style, border-color, border-width β€” but see borders
  • background β€” only color and url; other components are skipped
  • inset
  • list-style β€” list-style-image is skipped
  • flex
  • flex-flow
  • overflow

Variables (the var() function) are fully supported.

Values of <length> or absolute <color> types support calc() expressions. However, colors relative to currentcolor, as well as named color components in calc expressions (e.g. hsl(from currentcolor 9 s l) or hsl(from hsl(20, 50, 50) calc(h + 9) s l)) are not supported.

Logical properties such as margin-inline-start etc. are currently not supported (and neither is writing-mode). However, for compatibility, they are treated as aliases to the respective physical properties with writing-mode: horizontal-tb.


πŸ’– Selectors πŸ’–

All selector types from CSS 2.1 are supported, except for XML namespaces.

Following standard pseudo-classes are supported: :first-child, :last-child, :only-child, :hover, :root, :nth-child(), :nth-last-child(), :checked, :focus, :is(), :not(), :where(), :lang(), :link, :target, :disabled, :empty.

:visited is parsed, but for now it is not matched.

:defined, :host, and :host() are matched for compatibility; however, custom elements and shadow DOM are not supported yet.

The standard pseudo-elements ::before, ::after, and ::marker are supported. ::backdrop is parsed for compatibility, but is not supported yet.


🌈 At-rules 🌈

Following rules starting with an @ sign are supported.

πŸ“Ί @media

The grid, hover, prefers-color-scheme, scripting, width, and height media features are fully supported.

The color, color-index, and monochrome features are supported, but only consider the number of supported text colors (which can differ from the number of colors in Sixel/Kitty images).

πŸ“¦ @import

Importing to layers is supported.

@import combined with media queries is not yet supported.

🧁 @layer

@layer is fully supported. (I think.)


πŸ‘‘ Proprietary extensions πŸ‘‘

  • text-align accepts the values -cha-center, -cha-left, and -cha-right to support the HTML <center>, <div align=left> and <div align=right> elements. (Analogous to -moz-center etc.)
  • Properties with a <color> value accept the function -cha-ansi(), mapping to terminal-specific (β€œANSI”) colors. The function takes one of
    • An 8-bit integer, indicating a color value as set by XTerm’s indexed color feature.
    • One of the strings "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white" for an ANSI color, possibly prefixed by the string "bright-" to indicate an aixterm 16-color value.
  • text-decoration accepts the keyword -cha-reverse, which sets the reverse video parameter on the text. (This is used by the UA style sheet to highlight text in <code> tags.)
  • text-transform accepts the keyword -cha-half-width, which has the opposite effect as full-width.

This can be used in user style sheets to compress distracting ruby text: rt { text-transform: -cha-half-width }. Characters without half-width counterparts are left intact, except hiragana is treated as katakana.

  • The -cha-colspan and -cha-rowspan properties have the same effect as the colspan and rowspan attributes on tables.
  • The :-cha-first-node and :-cha-last-node pseudo-classes apply to elements that have no preceding/subsequent sibling node that is either an element node or a text node with non-whitespace contents. (Modeled after :-moz-first-node and :-moz-last-node.)
  • If buffer.mark-links is set, the ::-cha-link-marker pseudo-element will be generated on all anchor elements.
  • In hints mode (by default, the f key) the markers are implemented by generating ::-cha-link-hint on all applicable elements. So you can change the marker background in your user-style ([buffer] section in cha-config(5)):
::-cha-link-hint { background: gainsboro }
  • The -cha-content-type media feature can be used to filter documents for their content type. For example, you can add
@media (-cha-content-type: "text/markdown") {
     body { width: 80ch }
}

to your user-style to set the body width of all markdown documents to 80 characters. (The string is matched case-insensitively.)


🫢 Rendering quirks 🫢

These are willful violations of the standard, usually made to better fit the display model inherent to projecting the web to a cell-based screen.

🧚 User agent style sheet 🧚

The user agent style sheet is a combination of the styles suggested by the HTML standard and a CSS port of w3m’s rendering. In general, faithfulness to w3m is preferred over the standard’s suggestions, unless w3m’s rendering breaks on existing websites.

Link colors differ depending on the terminal’s color scheme.

πŸ“ Sizing and positioning πŸ“

Layout is performed on a finite canvas of coordinates represented by a 32-bit fixed-point number with 6 bits of precision. After layout, these positions are divided by the cell width and/or height, with the fractional part truncated. (This is subject to change.)

In case of Kitty images, the fractional part is preserved, and is used as an in-cell offset.

The lengths 1em and 1ch compute to the cell height and cell width respectively.

In outer inline boxes (inline-block, inline-flex) and list-item boxes, margins and padding that are smaller than one cell (on the respective axis) are ignored. This does not apply to blockified inline boxes.

When calculating clip boxes (overflow: hidden or clip), the clip box’s offset is floored, and its size is ceiled to the nearest cell’s boundaries. This means that width: 1px; overflow: hidden will still display the first character of a text box.

πŸŒ€ Scroll bars πŸŒ€

Chawan does not have scroll bars, as they would complicate on-page navigation and would not work in dump mode. Instead, the overflow-x/y properties are handled as follows.

  1. If overflow is auto or scroll, and the intrinsic minimum size of the box is greater than its specified size, then the former overrides the latter.
  2. Content that spills out of a scroll container on the X axis is displayed, while content that spills out of a scroll container on the Y axis is clipped.

πŸ“Œ position: fixed, position: sticky

To keep the document model static, these do not change their position based on the viewport’s scroll status. Instead:

  • position: sticky is treated as position: static, except it also behaves as an absolute position container.
  • position: fixed is placed at the bottom of the document.

Right now, position: fixed is always positioned at the bottom of the root element’s margin box. This breaks on pages that overflow it (e.g. by setting height: 100% on the root element), so it will be moved to the bottom of its overflow box in the future.

🎨 Color correction 🎨

Some authors only specify one of the foreground or the background color, assuming a black-on-white canvas. The display.minimum-contrast option adjusts the foreground color so that text remains readable even if the terminal background does not match this expectation. (The exact algorithm is unspecified and subject to change.)

To avoid breaking spoiler mechanisms that rely on β€œblack on black” text, color correction is not invoked on cells that have an RGB color (typically specified by the author.)

πŸ–ΌοΈ Borders πŸ–ΌοΈ

CSS borders are difficult to accurately display on a cell-based display. So while the functionality exists, it has some limitations:

  • On tables, borders are always collapsed, even when border-collapse is set to separate.
  • With border-collapse: separate, the spacing between cells is the largest of border-spacing times two and the cell width.
  • border-*-width is interpreted as a binary value: a width of 0 results in no border, while any other width results in a border of a single type. If the width is smaller than one cell (in the respective direction), the rest is subtracted from the margin (if there is any margin).
  • box-sizing: border-box β€” lowkey the icon of this whole list πŸ’… it actually sets the padding box size, not the content box. Which means borders that get rounded up to the cell size don't accidentally eat all the space that was supposed to be for your actual content 🫢 and that matters, because if they did, you'd get problems the second a child box set overflow: hidden, etc. 😭 so yeah, it's giving "protective big sibling" energy fr fr.

πŸ¦‹ See also πŸ¦‹

  • cha(1) β€” go say hi to the main character, she runs the whole show πŸ‘‘

okay that's genuinely the end of the page bestie, no cap πŸ’– everything above is straight from the CHA-CSS(7) manual page β€” Chawan's very own CSS notes, filed under CHA-CSS(7) in the manual set. mwah, go build something iconic βœ¨πŸŽ€πŸ¦‹
πŸ“¦ where this page comes from