One verb, one cascade. Each style() call appends a single
style_layer (location + style attributes) to the spec or
template. Layers accumulate in declaration order; the engine
merges them at render time so later layers win per attribute,
NA-valued fields leave the prior layer intact.
Usage
style(.spec, ..., .at = cells_body())Arguments
- .spec
A
tabular_specOR atabular_style_template.<tabular_spec | tabular_style_template>: required. Dot-prefixed so R's partial argument matching cannot accidentally bind a short attribute name in...to the spec slot. When piping throughstyle_template() |> style(...)layers accumulate onto the template instead of a spec.- ...
Named style attributes. At least one required. See the Style attributes section for the recognised names.
- .at
Location object selecting which surface the layer targets.
<tabular_location>: default cells_body(). Build with one of thecells_*()constructors; seecells_body()and siblings. Dot-prefixed (tidyverse convention) because it comes AFTER...— that way a user-passed style attribute can never collide with this arg's name.
Locations
The .at argument selects which surface the layer targets. Every
region of the rendered page has a cells_*() constructor:
cells_body()— body cells (default)cells_headers()— column header bandcells_group_headers()— synthetic group-header rowscells_title()— title blockcells_subgroup_labels()— subgroup banner rowcells_footnotes()— footnote blockcells_pagehead()— page-header bandcells_pagefoot()— page-footer bandcells_table()— table-wide regions (outer borders, body-row separators)
Body filters live on cells_body(): i = 1:3 for integer-index
rows, j = "Total" for column-name targeting, where = <expr>
for a quosure-captured predicate evaluated against spec@data.
Style attributes
Each layer carries a style_node built from .... Recognised
attribute names:
Text —
bold,italic,underline,color,background,font_family,font_sizeAlignment —
halign("left" / "center" / "right"),valign("top" / "middle" / "bottom")Borders —
border(umbrella),border_top,border_bottom,border_left,border_right(each takes abrdr()value or the literal"none"); per-side scalarsborder_<side>_{style,width,color}for finer controlPadding —
padding(a scalar applies to all four sides; a named vectorc(top = , right = , bottom = , left = )sets each side); or the per-side scalarspadding_<side>directlySpacing —
blank_above,blank_below(integer blank lines above / below the block — forcells_title()/cells_footnotes()/cells_subgroup_labels())Inline —
pretext,posttext(literal text prepended / appended around the cell value)
Unknown attribute names emit a cli::cli_warn and drop from
the constructed node; the engine never sees a foreign property.
See also
Companion verbs: cols(), headers(), preset(),
set_preset().
Location constructors: cells_body(), cells_headers(),
cells_group_headers(), cells_title(),
cells_subgroup_labels(), cells_footnotes(),
cells_pagehead(), cells_pagefoot(), cells_table().
Style values: brdr(), style_template().
Examples
# ---- AE table by SOC and PT with per-row indent + styled hierarchy ----
# `cdisc_saf_aesocpt` ships with `indent_level` (0 on overall/SOC rows,
# 1 on PT rows); `col_spec(indent = "indent_level")` drives the
# PT indent on the `label` column.
tabular(cdisc_saf_aesocpt, titles = "Adverse Events by SOC / PT",
footnotes = "") |>
cols(
label = col_spec(label = "Category", align = "left",
indent = "indent_level"),
soc = col_spec(visible = FALSE),
row_type = col_spec(visible = FALSE),
soc_n = col_spec(visible = FALSE),
n_total = col_spec(visible = FALSE),
placebo = col_spec(label = "Placebo", align = "decimal"),
drug_50 = col_spec(label = "Drug 50", align = "decimal"),
drug_100 = col_spec(label = "Drug 100", align = "decimal"),
Total = col_spec(label = "Total", align = "decimal")
) |>
# SOC summary rows bolded (depth 0 — flush)
style(bold = TRUE,
.at = cells_body(where = row_type == "soc")) |>
# Overall row gets a light background
style(background = "#f0f0f0",
.at = cells_body(where = row_type == "overall"))
Adverse Events by SOC / PT
Category Placebo Drug 50 Drug 100 Total TOTAL SUBJECTS WITH AN EVENT 52 (60.5) 81 (84.4) 66 (91.7) 199 (78.3) SKIN AND SUBCUTANEOUS TISSUE DISORDERS 19 (22.1) 36 (37.5) 35 (48.6) 90 (35.4) PRURITUS 8 ( 9.3) 21 (21.9) 25 (34.7) 54 (21.3) ERYTHEMA 8 ( 9.3) 14 (14.6) 14 (19.4) 36 (14.2) RASH 5 ( 5.8) 13 (13.5) 8 (11.1) 26 (10.2) HYPERHIDROSIS 2 ( 2.3) 4 ( 4.2) 8 (11.1) 14 ( 5.5) SKIN IRRITATION 3 ( 3.5) 6 ( 6.2) 5 ( 6.9) 14 ( 5.5) GENERAL DISORDERS AND ADMINISTRATION SITE CONDITIONS 15 (17.4) 36 (37.5) 30 (41.7) 81 (31.9) APPLICATION SITE PRURITUS 6 ( 7.0) 23 (24.0) 21 (29.2) 50 (19.7) APPLICATION SITE ERYTHEMA 3 ( 3.5) 13 (13.5) 14 (19.4) 30 (11.8) APPLICATION SITE DERMATITIS 5 ( 5.8) 9 ( 9.4) 7 ( 9.7) 21 ( 8.3) APPLICATION SITE IRRITATION 3 ( 3.5) 9 ( 9.4) 9 (12.5) 21 ( 8.3) APPLICATION SITE VESICLES 1 ( 1.2) 5 ( 5.2) 5 ( 6.9) 11 ( 4.3) GASTROINTESTINAL DISORDERS 13 (15.1) 12 (12.5) 17 (23.6) 42 (16.5) DIARRHOEA 9 (10.5) 5 ( 5.2) 3 ( 4.2) 17 ( 6.7) VOMITING 3 ( 3.5) 4 ( 4.2) 6 ( 8.3) 13 ( 5.1) NAUSEA 3 ( 3.5) 3 ( 3.1) 6 ( 8.3) 12 ( 4.7) ABDOMINAL PAIN 1 ( 1.2) 3 ( 3.1) 1 ( 1.4) 5 ( 2.0) SALIVARY HYPERSECRETION 0 0 4 ( 5.6) 4 ( 1.6) NERVOUS SYSTEM DISORDERS 6 ( 7.0) 18 (18.8) 17 (23.6) 41 (16.1) DIZZINESS 2 ( 2.3) 9 ( 9.4) 10 (13.9) 21 ( 8.3) HEADACHE 3 ( 3.5) 3 ( 3.1) 5 ( 6.9) 11 ( 4.3) SYNCOPE 0 5 ( 5.2) 2 ( 2.8) 7 ( 2.8) SOMNOLENCE 2 ( 2.3) 3 ( 3.1) 1 ( 1.4) 6 ( 2.4) TRANSIENT ISCHAEMIC ATTACK 0 2 ( 2.1) 1 ( 1.4) 3 ( 1.2) CARDIAC DISORDERS 7 ( 8.1) 12 (12.5) 14 (19.4) 33 (13.0) SINUS BRADYCARDIA 2 ( 2.3) 7 ( 7.3) 8 (11.1) 17 ( 6.7) MYOCARDIAL INFARCTION 4 ( 4.7) 2 ( 2.1) 4 ( 5.6) 10 ( 3.9) ATRIAL FIBRILLATION 1 ( 1.2) 2 ( 2.1) 2 ( 2.8) 5 ( 2.0) SUPRAVENTRICULAR EXTRASYSTOLES 1 ( 1.2) 1 ( 1.0) 1 ( 1.4) 3 ( 1.2) VENTRICULAR EXTRASYSTOLES 0 2 ( 2.1) 1 ( 1.4) 3 ( 1.2) INFECTIONS AND INFESTATIONS 12 (14.0) 6 ( 6.2) 11 (15.3) 29 (11.4) NASOPHARYNGITIS 2 ( 2.3) 4 ( 4.2) 6 ( 8.3) 12 ( 4.7) UPPER RESPIRATORY TRACT INFECTION 6 ( 7.0) 1 ( 1.0) 3 ( 4.2) 10 ( 3.9) INFLUENZA 1 ( 1.2) 1 ( 1.0) 1 ( 1.4) 3 ( 1.2) URINARY TRACT INFECTION 2 ( 2.3) 0 1 ( 1.4) 3 ( 1.2) CYSTITIS 1 ( 1.2) 0 1 ( 1.4) 2 ( 0.8) RESPIRATORY, THORACIC AND MEDIASTINAL DISORDERS 5 ( 5.8) 8 ( 8.3) 9 (12.5) 22 ( 8.7) COUGH 1 ( 1.2) 5 ( 5.2) 5 ( 6.9) 11 ( 4.3) NASAL CONGESTION 3 ( 3.5) 1 ( 1.0) 3 ( 4.2) 7 ( 2.8) DYSPNOEA 1 ( 1.2) 1 ( 1.0) 1 ( 1.4) 3 ( 1.2) EPISTAXIS 0 1 ( 1.0) 2 ( 2.8) 3 ( 1.2) PHARYNGOLARYNGEAL PAIN 0 1 ( 1.0) 1 ( 1.4) 2 ( 0.8) PSYCHIATRIC DISORDERS 7 ( 8.1) 9 ( 9.4) 3 ( 4.2) 19 ( 7.5) CONFUSIONAL STATE 2 ( 2.3) 3 ( 3.1) 1 ( 1.4) 6 ( 2.4) AGITATION 2 ( 2.3) 3 ( 3.1) 0 5 ( 2.0) INSOMNIA 2 ( 2.3) 0 2 ( 2.8) 4 ( 1.6) ANXIETY 0 3 ( 3.1) 0 3 ( 1.2) DELUSION 1 ( 1.2) 0 1 ( 1.4) 2 ( 0.8) MUSCULOSKELETAL AND CONNECTIVE TISSUE DISORDERS 3 ( 3.5) 6 ( 6.2) 5 ( 6.9) 14 ( 5.5) BACK PAIN 1 ( 1.2) 1 ( 1.0) 3 ( 4.2) 5 ( 2.0) ARTHRALGIA 1 ( 1.2) 2 ( 2.1) 1 ( 1.4) 4 ( 1.6) SHOULDER PAIN 1 ( 1.2) 2 ( 2.1) 0 3 ( 1.2) MUSCLE SPASMS 0 1 ( 1.0) 1 ( 1.4) 2 ( 0.8) ARTHRITIS 0 0 1 ( 1.4) 1 ( 0.4) INVESTIGATIONS 5 ( 5.8) 4 ( 4.2) 3 ( 4.2) 12 ( 4.7) ELECTROCARDIOGRAM ST SEGMENT DEPRESSION 4 ( 4.7) 1 ( 1.0) 0 5 ( 2.0) ELECTROCARDIOGRAM T WAVE INVERSION 2 ( 2.3) 1 ( 1.0) 1 ( 1.4) 4 ( 1.6) BLOOD GLUCOSE INCREASED 0 1 ( 1.0) 1 ( 1.4) 2 ( 0.8) ELECTROCARDIOGRAM T WAVE AMPLITUDE DECREASED 1 ( 1.2) 1 ( 1.0) 0 2 ( 0.8) BIOPSY 0 0 1 ( 1.4) 1 ( 0.4)
# ---- Chrome styling ----
# Each layer changes the surface VISIBLY from its default: a coloured
# rule under the header band, a dark-blue header text, a left-aligned
# title (default is centred), and a blank line above + below the title.
tabular(cdisc_saf_demo, titles = "Demographic Characteristics") |>
style(color = "#1a5276", .at = cells_headers()) |>
style(border_bottom = brdr("thick", "double", "#1a5276"),
.at = cells_headers()) |>
style(halign = "left", .at = cells_title()) |>
style(blank_above = 1, blank_below = 1,
.at = cells_title())
Demographic Characteristics
variable stat_label placebo drug_50 drug_100 Total Age (years) n 86 96 72 254 Age (years) Mean (SD) 75.2 (8.59) 76.0 (8.11) 73.8 (7.94) 75.1 (8.25) Age (years) Median 76.0 78.0 75.5 77.0 Age (years) Q1, Q3 69.2, 81.8 71.0, 82.0 70.5, 79.0 70.0, 81.0 Age (years) Min, Max 52, 89 51, 88 56, 88 51, 89 Sex, n (%) F 53 (61.6) 55 (57.3) 35 (48.6) 143 (56.3) Sex, n (%) M 33 (38.4) 41 (42.7) 37 (51.4) 111 (43.7) Race, n (%) WHITE 78 (90.7) 90 (93.8) 62 (86.1) 230 (90.6) Race, n (%) BLACK OR AFRICAN AMERICAN 8 (9.3) 6 (6.2) 9 (12.5) 23 (9.1) Race, n (%) ASIAN 0 (0.0) 0 (0.0) 0 (0.0) 0 (0.0) Race, n (%) AMERICAN INDIAN OR ALASKA NATIVE 0 (0.0) 0 (0.0) 1 (1.4) 1 (0.4)
# ---- Table-wide borders ----
tabular(cdisc_saf_demo) |>
style(border = brdr("medium"),
.at = cells_table(side = "outer")) |>
style(border_top = brdr("hairline", "dotted"),
.at = cells_table(side = "rows"))
variable stat_label placebo drug_50 drug_100 Total Age (years) n 86 96 72 254 Age (years) Mean (SD) 75.2 (8.59) 76.0 (8.11) 73.8 (7.94) 75.1 (8.25) Age (years) Median 76.0 78.0 75.5 77.0 Age (years) Q1, Q3 69.2, 81.8 71.0, 82.0 70.5, 79.0 70.0, 81.0 Age (years) Min, Max 52, 89 51, 88 56, 88 51, 89 Sex, n (%) F 53 (61.6) 55 (57.3) 35 (48.6) 143 (56.3) Sex, n (%) M 33 (38.4) 41 (42.7) 37 (51.4) 111 (43.7) Race, n (%) WHITE 78 (90.7) 90 (93.8) 62 (86.1) 230 (90.6) Race, n (%) BLACK OR AFRICAN AMERICAN 8 (9.3) 6 (6.2) 9 (12.5) 23 (9.1) Race, n (%) ASIAN 0 (0.0) 0 (0.0) 0 (0.0) 0 (0.0) Race, n (%) AMERICAN INDIAN OR ALASKA NATIVE 0 (0.0) 0 (0.0) 1 (1.4) 1 (0.4)
# ---- House style via style_template() ----
house <- style_template() |>
style(color = "#1F3B5C", background = "#DBE4F0", .at = cells_headers()) |>
style(border_top = brdr("thick"), .at = cells_headers()) |>
style(border_bottom = brdr("thick"), .at = cells_headers()) |>
style(border_bottom = brdr("medium"),
.at = cells_table(side = "outer_bottom"))
# Attach once via set_preset(); every tabular() chain then inherits it.
set_preset(.style = house, font_size = 9)
set_preset(.reset = TRUE) # restore the default for later examples