Closed andrewheiss closed 6 months ago
Yes, I agree this is a very common use case, and it should be easier. People should not have to write CSS for this.
I'll try to think of a solution. In the meantime, I believe that tabularray_inner
accepts a wd
setting, but I'm not sure what unit it requires or if it does percentages.
I figured out one way (based on §2.6.1 in the tabularray manual, but it doesn't use the wd
setting and instead sets column widths for the whole table.
tt(x) |>
style_tt(tabularray_inner = "colspec={X[0.3,l] X[0.7,l]}")
You can also optionally set column alignment there too, which probably conflicts with style_tt(..., align = "blah")
.
Surely the wd
argument is better, but it's hard to search for in the documentation :)
Ah, wd
is easier than I thought. It takes any of the standard LaTeX units like pt
, mm
, cm
, in
, ex
, and em
:
tt(x) |>
style_tt(j = 1, tabularray_inner = "column{1}={wd=1in}") |>
style_tt(j = 2, tabularray_inner = "column{2}={wd=5in}")
You can use percentages too by multiplying stuff with \linewidth
:
tt(x) |>
style_tt(j = 1, tabularray_inner = "column{1}={wd=0.3\\linewidth}") |>
style_tt(j = 2, tabularray_inner = "column{2}={wd=0.7\\linewidth}")
So it seems there are a bunch of ways to control widths (in exact measurements and in percentages) across different formats:
# With colspec and percentages (or exact measurements too)
tt(x) |>
style_tt(tabularray_inner = "colspec={X[0.3,l] X[0.7,l]}")
# With wd and inches (or cm or pt or mm or ex or em)
tt(x) |>
style_tt(j = 1, tabularray_inner = "column{1}={wd=1in}") |>
style_tt(j = 2, tabularray_inner = "column{2}={wd=5in}")
# With wd and percentages
tt(x) |>
style_tt(j = 1, tabularray_inner = "column{1}={wd=0.3\\linewidth}") |>
style_tt(j = 2, tabularray_inner = "column{2}={wd=0.7\\linewidth}")
# With CSS for HTML
tt(x) |>
style_tt(j = 1, bootstrap_css = "width: 30%;") |>
style_tt(j = 2, bootstrap_css = "width: 70%;")
I have no idea what the best approach for making this all more general and cross-format would be, though. Maybe a function similar to gt::pct()
that builds the right percent based on output?
tinytable::pct(30, format = "latex")
#> "column{BLAH}={wd=0.3\\linewidth}"
tinytable::pct(30, format = "html")
#> "width: 30%;"
gt(x) |>
style_tt(j = 1, width = pct(30)) |>
style_tt(j = 2, width = pct(70))
That seems complicated, though—idk.
Ah thanks for the investigation. That's very useful.
I'm thinking maybe we should just allow a vector in the width argument of tt(), and then document the other options better for those who want more control.
Cool, yeah, a vector in tt()
would be easy and straightforward. It would just need to use some sensible default unit for each output
Like tt(x, width = c(3, 7))
could use em
s in HTML, and maybe also in LaTeX?
I was thinking: elements of the vector are proportions of line width. So you can control both total and column width together. Width a useful error message if the sum of the vector exceeds 1.
Oooh I like combining total and column widths. That fixes an issue I thought of after posting that last comment—if widths
is a vector, there's no way to control the overall table width, so you'd need something like tt(x, table_width = 0.8, col_widths = c(0.3, 0.7)
, where the columns are 30% and 70% of the 80%-wide table
So something like tt(x, width = c(0.24, 0.56))
would get the same thing—30 and 70% of the 80%-wide table
You could feed it math to simplify things: tt(x, width = c(0.3, 0.7) * 0.8)
(↑ that gets trickier with HTML, where CSS would be defined as 30% and 70% within the parent 80% element, though)
this feature is merged on Github and there's an example in the tutorial. I just released to CRAN, so have to wait over a month before this makes it there.
Thanks for a great suggestion.
Minor improvement merged:
When the sum of the width
vector exceeds 1, it is automatically normalized to full-width. This is convenient when we only want to specify column width in relative terms:
tt(x, width = c(1, 1, 1, 4)) |>
style_tt(0:4, line = "tblr", align = "c")
Finally getting around to playing with these changes and it's sooo nice!
This monstrosity (for simultaneous HTML and PDF output)…
tt(x) |>
style_tt(tabularray_inner = "width={1\\linewidth},colspec={X[0.3]X[0.7]}") |>
style_tt(j = 1, bootstrap_css = "width: 30%;") |>
style_tt(j = 2, bootstrap_css = "width: 70%;")
…gets simplified down to just this:
tt(x, width = c(0.3, 0.7))
Nice!
You can also pick 1 and 2.5 if you want to use relative widths. When the sum is greater than 1, entries get normalized.
I've found that lots of my students and collaborators want to be able to control column widths in both LaTeX and HTML. Currently
tt()
does a good job with automatic widths:Based on #172 it seems possible to control HTML widths with
style_tt(width = X)
, but that uses hard-codedem
values. I was trying to use percents, likegt::pct()
, but couldn't find a way until I stumbled on this in #112:And it is indeed!
At least for HTML.
I'm still trying to figure out how to control PDF column widths—I'm assuming it involves some settings passed to the
tabularray_inner
argument instyle_tt()
, but I haven't taught myself enough tabularray to figure it out yet.In any case, I think that setting column widths is a common enough use case (see {gt} and {kableExtra} and {huxtable} and {flextable}) to warrant an example in the tutorial.