xterm.js
xterm.js copied to clipboard
Character size computation is affected by CSS transforms
When a Terminal is opened in an element subject to CSS transformations such as scale
or rotate
, the computation of the character size is affected by that transformation, which is wrong because the rendering should be transform-agnostic.
As a result, this makes the integration of Xterm.js into reveal.js slides render incorrectly when the slides are scaled down to fit the browser viewport.
Changing the measurement method in CharSizeService
to use getComputedStyle
instead of getBoundingClientRect
makes the computation independent of CSS transforms.
Details
- Browser and browser version: Firefox 69.0 and Chromium 77.0
- OS version: Arch Linux
- xterm.js version: current master (6311076)
Steps to reproduce
- Add
style="transform: rotate(90deg);"
to the<body>
tag indemo/index.html
- Notice that character boxes in the demo have the wrong dimensions
Workaround
With the rotate(90deg)
CSS transform Xterm.js renders character cells with the width and height swapped around:
The cause is in the measurement methods in CharSizeService
: it uses getBoundingClientRect
, which returns the size of the bounding box after CSS transforms.
https://github.com/xtermjs/xterm.js/blob/631107698ec1f28577101cc570540f097a83af68/src/browser/services/CharSizeService.ts#L71-L86
My understanding is that the rendering of the terminal should not be affected by said transforms. And indeed, replacing the geometry
definition in the code above with (POC)
const computedStyle = getComputedStyle(this._measureElement);
const geometry = {
height: Number(computedStyle.getPropertyValue('height').replace('px', '')),
width: Number(computedStyle.getPropertyValue('width').replace('px', '')),
}
yields a correct rendering:
Note that my proof-of-concept fix above may be insufficient in cases where the element or its parent are display: none
.
@cebamps the workaround seems reasonable.
Note that my proof-of-concept fix above may be insufficient in cases where the element or its parent are display: none.
I don't think this should matter.
I am not really able to reproduce. The selection with cursor is broken when you rotate the terminal.
Still reproduces:
Oh well, wasnt aware of this - also needs to be changed in #4605.