css technique for aligning decimals.ยค
all of my recent plotting techniques rely on access to cell values in css. when we have the values in css, along with their extent (min/max), we can adjust the values using math to align decimal points.
decimal point aligned is important in scanning documents and improving low numeracy experiences.
disclaimer: this technique use css log
and sign
. can i use sign
indicates the function lacks broad support only works in firefox and safari which limits the application of this technique.
%%
our approach is to calculate the order of magnitude of our values and their sign on a monospace font.
we only need the maximum number of digits and signs before the decimal;
we'll refer to these values with the prefix `--tens`
display\
```css
#aligned {
font-family: monospace;
--tens-max: calc(
round(up, max(1, log(abs(var(--0-max)), 10)))
+ abs(min(0, sign(var(--0-max))))
);
--tens-min: calc(
round(up, max(1, log(abs(var(--0-min)), 10)))
+ abs(min(0, sign(var(--0-min))))
);
--tens-total: calc(max(var(--tens-max), var(--tens-min)));
```
insert a pseudo-element in each table cell that using `1ch` spaces -
[Relative to the width of the "0" (zero)](https://www.w3schools.com/cssref/css_units.php) -
display\
```css
#aligned td {
text-align: left;
&::before {
display: inline-block;
content: "";
--tens: calc(
round(up, max(1, log(abs(var(--0)), 10)))
+ abs(min(0, sign(var(--0))))
);
width: calc(1ch * (var(--tens-total) - var(--tens)));
padding: 0;
}
}
}
```
add a background grid for visual verification of the decimal alignment.
display\
```css
#aligned {
--w: 2px;
position: relative;
font-size: 36px;
background: linear-gradient(90deg, transparent calc(0.25em - var(--w)), blue var(--w));
background-size: 0.25em 100%;
background-repeat: repeat-x;
tr {
background: unset;
}
}
```
for each cell value we use the `::before` element to insert a single character width for
each `--tens` unit. if padding is not removed then we'll end up with extra left whitespace.
we overlay a visual grid for verification.
display\
```css
#aligned td {
text-align: left;
&::before {
display: inline-block;
content: "";
--tens: calc(
round(up, max(1, log(abs(var(--0)), 10)))
+ abs(min(0, sign(var(--0))))
);
width: calc(1ch * (var(--tens-total) - var(--tens)));
padding: 0;
}
}
```
import nbconvert_a11y.table
(df := DataFrame(
numpy.random.randn(30, 1)
).pow(9))
df.table(id="aligned")