Scale-to-Fit

Wide content like tables created with Great Tables, DataFrames, and custom _repr_html_ objects often overflow the content area on smaller screens. When a table is just slightly wider than the container, the reader has to scroll horizontally to see a small sliver of remaining content, which is a frustrating experience. Shrinking the element by a few percent makes it fit cleanly and nobody notices the difference. On the other hand, when an element is dramatically wider than the container, scaling it down would make the text unreadably small. In that case, horizontal scrolling is the better option.

Great Docs includes a scale-to-fit system that handles both situations. It automatically shrinks targeted elements so they fit within the container width, and falls back to horizontal scrolling when the element would need to shrink beyond a configurable threshold.

See It in Action

The examples below use :::{.scale-to-fit} divs to demonstrate the scaling behavior, but this is just one of three ways to enable scale-to-fit. You can also target elements globally through great-docs.yml or per-page through frontmatter (both covered in later sections). Try resizing your browser window to see elements shrink. The third example uses a per-div data-min-scale attribute to show the scrolling fallback.

A Table That Fits Normally

This table is narrow enough to fit the content area without any scaling. It renders at its natural size.

:::{.scale-to-fit}
```{=html}
<table style="width: 400px; ...">
  ...
```
:::
Name Value Status
Alpha 42 Active
Beta 87 Pending

At 400px, this table fits comfortably within the content area. No scaling is applied and no scrollbar appears.

A Wide Table That Scales Down

This table is 1600px wide, wider than most content areas. Scale-to-fit shrinks it proportionally so it fits without overflow.

:::{.scale-to-fit}
```{=html}
<table style="width: 1600px; ...">
  ...
```
:::
ID Name Category Region Q1 Revenue Q2 Revenue Q3 Revenue Q4 Revenue Total Status
001 Acme Corp Enterprise North America $1,245,000 $1,389,000 $1,102,000 $1,567,000 $5,303,000 Active
002 Globex Inc Mid-Market Europe $892,000 $1,045,000 $978,000 $1,123,000 $4,038,000 Active
003 Initech Startup Asia Pacific $234,000 $312,000 $289,000 $401,000 $1,236,000 Review

Notice that the text is slightly smaller than in the first table. The system shrank the 1600px table to fit the content area, and the reduction is modest enough that everything stays readable.

A Very Wide Element (Scrolling Fallback)

This element is 2400px wide. It has data-min-scale="0.65" set directly on the div, so when the computed scale factor drops below 0.65 the system falls back to horizontal scrolling instead of shrinking the content to an unreadable size.

:::{.scale-to-fit data-min-scale="0.65"}
```{=html}
<table style="width: 2400px; ...">
  ...
```
:::
ID Product SKU Category Supplier Region Warehouse Stock Unit Price Q1 Sales Q2 Sales Q3 Sales Q4 Sales Annual Total YoY Growth Margin Rating Status
P-001 Widget Pro Max WPM-2024-A Hardware TechSource Ltd North America Dallas-TX 12,450 $149.99 3,200 4,150 3,890 5,100 16,340 +18.2% 34.5% 4.7/5 Active
P-002 Gadget Elite GE-2024-B Electronics CircuitWorks Europe Munich-DE 8,320 $249.50 1,800 2,450 2,100 3,200 9,550 +12.7% 28.3% 4.5/5 Active

This table is so wide that scaling it down would make the text unreadable. Because data-min-scale="0.65" is set on the div, the system switches to horizontal scrolling instead. Scroll right to see the rest of the columns.

How It Works

The scale-to-fit system operates as a three-level cascade:

  1. Global config: target specific CSS selectors across the entire site
  2. Page frontmatter: override the selectors and threshold on individual pages
  3. Manual div: wrap any content block in a :::{.scale-to-fit} div for one-off scaling

When an element matches a targeted selector, the system:

  • Measures the element’s natural width against the available container width
  • Computes a scale factor (container width / element width)
  • Applies a CSS transform: scale() to shrink the element proportionally
  • If the scale factor falls below the minimum threshold, the element is shown at full size with horizontal scrolling instead

The scaling is applied on page load and recalculated on window resize. Together, these three levels give you fine-grained control over which elements scale, how far they can shrink, and when they should scroll instead.

Global Configuration

To enable scale-to-fit for specific elements across your entire site, add scale_to_fit to your great-docs.yml with a list of CSS selectors. Any element that matches one of these selectors will be automatically scaled.

great-docs.yml
scale_to_fit:
  - "#my_wide_table"
  - ".wide-output"

A single selector also works:

great-docs.yml
scale_to_fit:
  - "#gt_table_1"

Minimum Scale Threshold

By default there is no minimum scale: elements will shrink as much as needed to fit. You can set a threshold below which the system falls back to horizontal scrolling instead:

great-docs.yml
scale_to_fit:
  - "#my_wide_table"
scale_to_fit_min_scale: tablet

The threshold can be a viewport keyword or a numeric fraction.

Viewport Keywords

Viewport keywords switch to scrolling when the viewport is at or below the named breakpoint, regardless of the computed scale factor.

Keyword Max Width When It Scrolls
mobile 576 px Phones in portrait
tablet 768 px Tablets in portrait
desktop 992 px Small laptops and below
great-docs.yml
scale_to_fit_min_scale: mobile   # Only scroll on phones
great-docs.yml
scale_to_fit_min_scale: desktop  # Scroll on anything below a large desktop

Viewport keywords are the simplest way to set a threshold: pick the device class where scaling should stop and scrolling should begin.

Numeric Fraction

A decimal value between 0 and 1 sets a minimum scale factor. If the computed scale drops below this value, the element scrolls instead.

great-docs.yml
scale_to_fit_min_scale: 0.5  # Scroll if element would shrink below 50%
great-docs.yml
scale_to_fit_min_scale: 0.35  # Allow more aggressive shrinking

Choose a numeric fraction when you want precise control over the shrink limit, independent of any particular viewport size.

Disabling

To disable scale-to-fit entirely, remove the scale_to_fit key from your config or set it explicitly:

great-docs.yml
scale_to_fit: false

With scale_to_fit and scale_to_fit_min_scale, the global configuration covers most sites. Every page inherits the same selectors and threshold, so you only need to set it once. For pages that need different behavior, use page-level overrides.

Page-Level Overrides

Individual pages can override both the targeted selectors and the minimum scale threshold using frontmatter keys. This is useful when a particular page needs different behavior than the site-wide default.

Overriding Selectors

Use scale-to-fit in the page’s YAML frontmatter to target different elements on that page:

---
title: My Page
scale-to-fit:
  - "#special_table"
  - "#dashboard_widget"
---

The page-level selectors replace (not merge with) the global selectors for that page. If you want to keep the global selectors and add more, list them all in the page frontmatter.

Overriding the Threshold

Use scale-to-fit-min-scale in frontmatter to set a different threshold for the page:

---
title: My Page
scale-to-fit:
  - "#wide_output"
scale-to-fit-min-scale: mobile
---

If a page specifies scale-to-fit selectors but omits scale-to-fit-min-scale, the global scale_to_fit_min_scale value is used as a fallback. This lets you change which elements are targeted on a page without having to repeat the threshold.

Combined Example

Consider a site that globally targets #main_table with a tablet threshold:

great-docs.yml
scale_to_fit:
  - "#main_table"
scale_to_fit_min_scale: tablet

A specific page can override both:

---
title: Dashboard
scale-to-fit:
  - "#main_table"
  - "#summary_card"
scale-to-fit-min-scale: 0.4
---

On this page, #main_table and #summary_card are both scaled, and the threshold is a 40 % minimum scale factor instead of the global tablet keyword. Page-level overrides give you full flexibility to tailor the scaling behavior for individual pages without changing the site-wide defaults.

Manual Div Wrapping

For one-off cases where you want to scale a single block of content without adding it to the global config, wrap it in a :::{.scale-to-fit} fenced div in your .qmd page:

:::{.scale-to-fit}
```{python}
#| echo: false
my_wide_widget()
```
:::

The .scale-to-fit class provides the same scaling behavior: content is measured, scaled to fit, and scrolled if it would exceed the minimum threshold. This approach requires no configuration at all; the elements inside the div are always considered for scaling. Use manual wrapping for isolated wide outputs that don’t warrant a global selector.

Per-Div Minimum Scale

You can set a minimum scale threshold directly on an individual div using the data-min-scale attribute. This accepts the same values as the global and page-level settings: a viewport keyword (mobile, tablet, desktop) or a numeric fraction between 0 and 1.

:::{.scale-to-fit data-min-scale="0.5"}
```{python}
#| echo: false
my_extremely_wide_table()
```
:::

The per-div threshold takes precedence over any page-level or global threshold. This is useful when a single element on a page needs a different scrolling cutoff than the rest.

Typical Selectors

The selectors you provide are standard CSS selectors. These examples show common patterns:

Selector Matches
#my_table An element with id="my_table"
.gt_table Any element with class gt_table
table.dataframe A <table> element with class dataframe

For GT tables, the id parameter controls the HTML id:

GT(df, id="my_table")

For objects with _repr_html_, include the id attribute in your returned HTML:

class MyWidget:
    def _repr_html_(self):
        return '<div id="my_widget" style="width:1400px;">...</div>'

As long as your output element has a stable id or class name, it can be targeted by scale-to-fit: the system works with any HTML content, not just tables.

Configuration Reference

Global (great-docs.yml)

Key Type Default Description
scale_to_fit list of strings None CSS selectors to target for auto-scaling
scale_to_fit_min_scale string or float None Minimum threshold: "mobile", "tablet", "desktop", or a float (0–1)

Page Frontmatter

Key Type Description
scale-to-fit list of strings Overrides global selectors for this page
scale-to-fit-min-scale string or float Overrides global threshold for this page

Note the key naming: global config uses underscores (scale_to_fit) to match Python property names, while page frontmatter uses hyphens (scale-to-fit) to match Quarto’s built-in key style. Between these two tables you have the full set of options available for controlling scale-to-fit behavior at both the site and page level.

Putting It All Together

For most projects, a single scale_to_fit entry in great-docs.yml is all you need. Pick the selectors that match your wide outputs, choose a minimum scale threshold that feels right, and every page on your site benefits automatically. When a particular page calls for something different, override the selectors or threshold in that page’s frontmatter. And for the occasional one-off table or widget that just needs to fit, wrap it in a :::{.scale-to-fit} div and move on. The three levels work together so you can start simple and add precision only where it matters.

Next Steps

Scale-to-fit keeps wide content readable on any screen size without horizontal scrolling. The three-level cascade (global, page, div) lets you start with a single config line and add precision only where needed.