☰ GDG /
Docstrings (001–005)
#002 gdtest_google #003 gdtest_sphinx #001 gdtest_minimal #004 gdtest_nodocs #005 gdtest_mixed_docs
Layouts (006–013)
#007 gdtest_python_layout #008 gdtest_lib_layout #006 gdtest_src_layout #009 gdtest_hatch #010 gdtest_setuptools_find #011 gdtest_setup_cfg #012 gdtest_setup_py #013 gdtest_auto_discover
Exports (014–017)
#014 gdtest_no_all #016 gdtest_config_exclude #015 gdtest_all_concat #017 gdtest_auto_exclude
Object Types (018–027)
#018 gdtest_small_class #020 gdtest_dataclasses #019 gdtest_big_class #021 gdtest_enums #022 gdtest_typed_containers #023 gdtest_protocols #024 gdtest_descriptors #026 gdtest_nested_class #025 gdtest_dunders #027 gdtest_constants
Directives (028–032)
#028 gdtest_seealso #029 gdtest_nodoc #030 gdtest_user_guide_auto #031 gdtest_user_guide_sections #032 gdtest_user_guide_subdirs
User Guide (033–038)
#033 gdtest_user_guide_explicit #034 gdtest_user_guide_custom_dir #035 gdtest_user_guide_hyphen #036 gdtest_readme_rst #037 gdtest_index_qmd #038 gdtest_index_md
Landing Pages (039–043)
#039 gdtest_no_readme #040 gdtest_index_wins #041 gdtest_index_frontmatter #042 gdtest_full_extras #043 gdtest_github_contrib
Extras & Config (044–050)
#044 gdtest_cli_click #048 gdtest_name_mismatch #046 gdtest_explicit_ref #045 gdtest_cli_nested #047 gdtest_kitchen_sink #049 gdtest_src_big_class #050 gdtest_google_big_class
Cross-Dimension (051–065)
#051 gdtest_user_guide_cli #053 gdtest_src_no_all #052 gdtest_explicit_big_class #055 gdtest_google_seealso #054 gdtest_extras_guide #056 gdtest_setup_cfg_src #057 gdtest_exclude_cli #058 gdtest_src_explicit_ref #059 gdtest_async_funcs #060 gdtest_generators #061 gdtest_overloads #062 gdtest_abstract_props #063 gdtest_multi_inherit #064 gdtest_slots_class #065 gdtest_frozen_dc
API Patterns (066–077)
#066 gdtest_generics #067 gdtest_context_mgr #068 gdtest_decorators #069 gdtest_exceptions #070 gdtest_reexports #071 gdtest_many_exports #072 gdtest_deep_nesting #073 gdtest_long_docs #074 gdtest_many_guides #076 gdtest_flit #077 gdtest_pdm #075 gdtest_many_big_classes
Scale & Stress (078–082)
#078 gdtest_namespace #079 gdtest_monorepo #080 gdtest_multi_module #081 gdtest_src_legacy #082 gdtest_empty_module
Build Systems (083–088)
#083 gdtest_all_private #084 gdtest_duplicate_all #085 gdtest_badge_readme #086 gdtest_math_docs #087 gdtest_mixed_guide_ext #088 gdtest_unicode_docs
Edge Cases (089–095)
#089 gdtest_config_all_on #090 gdtest_config_display #091 gdtest_config_minimal #092 gdtest_config_parser #093 gdtest_config_extra_keys #094 gdtest_github_icon #095 gdtest_source_branch
Config Matrix (096–100)
#096 gdtest_source_path #097 gdtest_source_title #098 gdtest_source_disabled #099 gdtest_sidebar_disabled #100 gdtest_sidebar_min_items
Config Options (101–125)
#102 gdtest_cli_name #103 gdtest_dynamic_false #101 gdtest_sidebar_float #104 gdtest_parser_google #105 gdtest_parser_sphinx #106 gdtest_display_name #107 gdtest_funding #108 gdtest_authors_multi #109 gdtest_no_darkmode #110 gdtest_exclude_list #111 gdtest_jupyter_kernel #112 gdtest_config_sections #113 gdtest_config_ug_string #114 gdtest_config_ug_list #115 gdtest_config_changelog #116 gdtest_config_reference #117 gdtest_config_combo_a
#121 gdtest_config_combo_e FAIL
#118 gdtest_config_combo_b #119 gdtest_config_combo_c #120 gdtest_config_combo_d #122 gdtest_config_combo_f #123 gdtest_attribution_on #124 gdtest_attribution_off #125 gdtest_rst_versionadded
Docstring Richness (126–150)
#126 gdtest_rst_deprecated #127 gdtest_rst_note #128 gdtest_rst_warning #130 gdtest_rst_caution #129 gdtest_rst_tip #131 gdtest_rst_danger #132 gdtest_rst_important #134 gdtest_directives #133 gdtest_rst_mixed_dirs #135 gdtest_sphinx_func_role #136 gdtest_sphinx_class_role #137 gdtest_sphinx_exc_role #138 gdtest_sphinx_meth_role #139 gdtest_sphinx_mixed_roles #140 gdtest_numpy_rich #141 gdtest_google_rich #142 gdtest_sphinx_rich #143 gdtest_docstring_examples #144 gdtest_examples_rst_repro #145 gdtest_docstring_notes #146 gdtest_docstring_warnings #147 gdtest_docstring_references #148 gdtest_docstring_seealso #150 gdtest_docstring_tables #149 gdtest_docstring_math
UG Variations (151–165)
#151 gdtest_docstring_combo #152 gdtest_ug_auto #153 gdtest_ug_numbered #154 gdtest_ug_sections_fm #155 gdtest_ug_subdirs #156 gdtest_ug_custom_dir #157 gdtest_ug_deep_nest #158 gdtest_ug_mixed_ext #160 gdtest_ug_explicit_order #159 gdtest_ug_many_pages #162 gdtest_ug_no_frontmatter #161 gdtest_ug_single_page #164 gdtest_ug_with_images #163 gdtest_ug_with_code #165 gdtest_ug_hyphen_dir
Custom Sections (166–175)
#166 gdtest_ug_combo #167 gdtest_sec_examples #168 gdtest_sec_tutorials #169 gdtest_sec_recipes #170 gdtest_sec_blog #171 gdtest_sec_faq #172 gdtest_sec_multi #173 gdtest_sec_navbar_after #174 gdtest_sec_with_ug #175 gdtest_sec_with_ref
Reference Config (176–185)
#176 gdtest_sec_deep #177 gdtest_sec_index_opt #178 gdtest_sec_index_hero #179 gdtest_sec_sidebar_single #180 gdtest_custom_passthrough_navbar #181 gdtest_custom_raw_navbar_after #182 gdtest_custom_mixed_modes #183 gdtest_custom_nested_combo #184 gdtest_custom_basename_output #185 gdtest_custom_nested_output
Site Theming (186–195)
#186 gdtest_custom_missing_dir_combo #187 gdtest_ref_explicit #188 gdtest_ref_members_false #189 gdtest_ref_mixed #190 gdtest_ref_reorder #192 gdtest_ref_single_section #191 gdtest_ref_sectioned #193 gdtest_ref_module_expand #194 gdtest_ref_big_class #195 gdtest_ref_multi_big
Stress Tests (196–200)
#196 gdtest_ref_title #197 gdtest_theme_cosmo #198 gdtest_theme_lumen #199 gdtest_theme_cerulean #200 gdtest_toc_disabled #201 gdtest_toc_depth #202 gdtest_toc_title #203 gdtest_site_combo #204 gdtest_display_badges #205 gdtest_display_authors #206 gdtest_display_funding #207 gdtest_stress_all_config #208 gdtest_stress_all_docstr #209 gdtest_stress_all_ug #210 gdtest_stress_all_sections #212 gdtest_src_google_seealso #211 gdtest_stress_everything #213 gdtest_hatch_nodoc #214 gdtest_pdm_big_class #215 gdtest_flit_enums #216 gdtest_namespace_ug #217 gdtest_ug_subdir_numbered #218 gdtest_homepage_ug #220 gdtest_logo #221 gdtest_hero_basic #222 gdtest_hero_readme_badges #219 gdtest_long_names #223 gdtest_hero_disabled #224 gdtest_hero_custom #225 gdtest_hero_wordmark #226 gdtest_hero_no_logo #227 gdtest_hero_explicit_badges #228 gdtest_hero_index_qmd #229 gdtest_hero_auto_logo #230 gdtest_md_disabled #231 gdtest_md_no_widget #232 gdtest_announce_simple #233 gdtest_announce_dict #234 gdtest_announce_disabled #235 gdtest_gradient_sky #236 gdtest_gradient_peach #237 gdtest_gradient_prism #238 gdtest_gradient_lilac #239 gdtest_gradient_slate #240 gdtest_gradient_honey #241 gdtest_gradient_dusk #242 gdtest_gradient_mint #243 gdtest_gradient_navbar #244 gdtest_gradient_both #245 gdtest_gradient_mixed #246 gdtest_gradient_no_dismiss #247 gdtest_header_text #248 gdtest_header_list #249 gdtest_header_file #250 gdtest_navbar_color #251 gdtest_navbar_color_light #252 gdtest_navbar_color_dark #253 gdtest_navbar_color_same #254 gdtest_navbar_color_split #256 gdtest_stress_everything_q #255 gdtest_kitchen_sink_q #257 gdtest_seealso_desc #258 gdtest_numpy_seealso_desc #259 gdtest_interlinks_prose #260 gdtest_autolink #261 gdtest_skill_default #262 gdtest_skill_curated #264 gdtest_skill_disabled #263 gdtest_skill_config #265 gdtest_skill_rich #266 gdtest_skill_combo #267 gdtest_skill_complex #268 gdtest_i18n_french #269 gdtest_i18n_japanese #270 gdtest_i18n_arabic #271 gdtest_code_cells #273 gdtest_page_tags #272 gdtest_nav_icons #274 gdtest_page_status #277 gdtest_homepage_ug_subdirs #275 gdtest_tag_location #276 gdtest_icon_shortcode #278 gdtest_gt_tables #281 gdtest_homepage_wide #282 gdtest_interlinks_userguide #279 gdtest_scale_to_fit #280 gdtest_scale_min_scale #283 gdtest_code_span_headings #286 gdtest_namespace_src #284 gdtest_sec_blog_user_index #285 gdtest_sec_dir_titles #287 gdtest_auto_include #288 gdtest_no_auto_exclude #290 gdtest_tbl_shortcode #292 gdtest_hr_shortcode #293 gdtest_accent_color #294 gdtest_keys_shortcode #291 gdtest_tbl_explorer #289 gdtest_tbl_preview #296 gdtest_inline_always #295 gdtest_inline_methods #297 gdtest_inline_never #298 gdtest_inline_threshold #299 gdtest_ref_inherited_explicit #300 gdtest_ref_include_inherited #304 gdtest_lightbox #302 gdtest_details_shortcode #303 gdtest_termshow #301 gdtest_mock_code #305 gdtest_hero_no_name #306 gdtest_sec_nested_tags #307 gdtest_sec_xref_subdirs #308 gdtest_bibliography #311 gdtest_go_cli #309 gdtest_bibliography_csl #310 gdtest_custom_css #312 gdtest_ug_dark_assets #313 gdtest_code_include #314 gdtest_ug_mixed_subdir_order #315 gdtest_type_aliases
314/315 built ⏱ 1m 34s 🧪 8/8

gdtest-scale-to-fit

Test the 3-level scale-to-fit system for wide HTML output.

Tests the 3-level scale-to-fit configuration system: global config targeting by CSS selector, page-level frontmatter overrides, and manual div wrapping. Uses GT tables of varying widths (4-16 cols) and a custom repr_html widget to verify correct scaling behavior, ID-based targeting, and override precedence.

Source files
📁 gdtest_scale_to_fit/
📄 __init__.py
"""A test package for scale-to-fit auto-scaling."""

__version__ = "0.1.0"
__all__ = [
    "make_wide_table",
    "make_narrow_table",
    "make_medium_table",
    "CustomWidget",
]


def make_wide_table():
    """
    Create a wide GT table with 12 columns.

    Returns
    -------
    GT
        A GT table with many columns that overflows its container.

    Examples
    --------
    ```{python}
    from gdtest_scale_to_fit import make_wide_table
    make_wide_table()
    ```
    """
    from great_tables import GT
    import pandas as pd

    df = pd.DataFrame({
        f"Col_{i:02d}": [f"val_{r}_{i}" for r in range(4)]
        for i in range(1, 13)
    })
    return (
        GT(df, id="wide_gt")
        .tab_header(title="Wide Table (12 cols)")
        .cols_width(**{f"Col_{i:02d}": "110px" for i in range(1, 13)})
        .tab_options(quarto_disable_processing=True)
    )


def make_narrow_table():
    """
    Create a narrow GT table with 3 columns.

    Returns
    -------
    GT
        A GT table that fits comfortably in its container.
    """
    from great_tables import GT
    import pandas as pd

    df = pd.DataFrame({
        "Name": ["Alice", "Bob"],
        "Score": [95, 87],
        "Grade": ["A", "B+"],
    })
    return (
        GT(df, id="narrow_gt")
        .tab_header(title="Narrow Table (3 cols)")
        .tab_options(quarto_disable_processing=True)
    )


def make_medium_table():
    """
    Create a medium GT table with 8 columns.

    Returns
    -------
    GT
        A GT table that is moderately wide.
    """
    from great_tables import GT
    import pandas as pd

    df = pd.DataFrame({
        f"Metric_{i}": [round(i * 1.5 + r * 0.3, 1) for r in range(5)]
        for i in range(1, 9)
    })
    return (
        GT(df, id="medium_gt")
        .tab_header(title="Medium Table (8 cols)")
        .cols_width(**{f"Metric_{i}": "120px" for i in range(1, 9)})
        .tab_options(quarto_disable_processing=True)
    )


class CustomWidget:
    """
    A custom widget with ``_repr_html_`` for scale-to-fit testing.

    This produces a wide HTML block that is NOT a GT table, verifying
    that scale-to-fit works for arbitrary ``_repr_html_`` objects.

    Parameters
    ----------
    width
        CSS width of the widget (e.g., ``"1500px"``).
    widget_id
        HTML ``id`` attribute for targeting.
    """

    def __init__(self, width: str = "1500px", widget_id: str = "custom_html"):
        self.width = width
        self.widget_id = widget_id

    def _repr_html_(self) -> str:
        """Render as wide HTML block."""
        return (
            f'<div id="{self.widget_id}" '
            f'style="width:{self.width};background:#e8f4fd;'
            f'border:2px solid #2196F3;padding:16px;'
            f'font-family:monospace;">'
            f'<strong>CustomWidget</strong> &mdash; '
            f'width: {self.width}, id: {self.widget_id}'
            f'</div>'
        )
📁 user_guide/
📄 01-global-targeting.qmd
---
title: Global Config Targeting
---

## Wide GT Table (12 columns)

This GT table has `id="wide_gt"` and should be auto-scaled
because the global config has `scale_to_fit: ["#wide_gt", ...]`.

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"Col_{i:02d}": [f"val_{r}_{i}" for r in range(4)]
    for i in range(1, 13)
})

(
    GT(df, id="wide_gt")
    .tab_header(title="Wide Table (12 cols)")
    .cols_width(**{f"Col_{i:02d}": "110px" for i in range(1, 13)})
    .tab_options(quarto_disable_processing=True)
)
```

## Custom HTML Widget

This `_repr_html_` object has `id="custom_html"` and should also
be auto-scaled by the global config.

```{python}
#| echo: false
from gdtest_scale_to_fit import CustomWidget
CustomWidget(width='1500px', widget_id='custom_html')
```

## Narrow GT Table (not targeted)

This table has `id="narrow_gt"` which is NOT in the global
`scale_to_fit` list, so it should NOT be auto-scaled.

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    "Name": ["Alice", "Bob"],
    "Score": [95, 87],
    "Grade": ["A", "B+"],
})

(
    GT(df, id="narrow_gt")
    .tab_header(title="Narrow Table (3 cols)")
    .tab_options(quarto_disable_processing=True)
)
```
📄 02-page-override.qmd
---
title: Page-Level Override
scale-to-fit:
  - "#page_gt"
scale-to-fit-min-scale: mobile
---

## Medium GT Table (page-targeted)

This page has `scale-to-fit: ["#page_gt"]` in its frontmatter,
which overrides the global config. Only `#page_gt` should scale.

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"Metric_{i}": [round(i * 1.5 + r * 0.3, 1) for r in range(5)]
    for i in range(1, 9)
})

(
    GT(df, id="page_gt")
    .tab_header(title="Page-Targeted Table (8 cols)")
    .cols_width(**{f"Metric_{i}": "120px" for i in range(1, 9)})
    .tab_options(quarto_disable_processing=True)
)
```

## Wide GT Table (NOT targeted on this page)

This table has `id="wide_gt_2"` which matches nothing on this page
(the page override replaces the global selectors).

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"Col_{i:02d}": [f"val_{r}_{i}" for r in range(4)]
    for i in range(1, 13)
})

(
    GT(df, id="wide_gt_2")
    .tab_header(title="Wide Table 2 (not targeted here)")
    .cols_width(**{f"Col_{i:02d}": "110px" for i in range(1, 13)})
    .tab_options(quarto_disable_processing=True)
)
```
📄 03-manual-div.qmd
---
title: Manual Div Wrapping
---

## Manually Scaled Table

This table is wrapped in a `:::{.scale-to-fit}` div.
No config or frontmatter needed.

:::{.scale-to-fit}
```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"Field_{i}": [f"data_{r}_{i}" for r in range(3)]
    for i in range(1, 11)
})

(
    GT(df, id="manual_gt")
    .tab_header(title="Manual Scale (10 cols)")
    .cols_width(**{f"Field_{i}": "110px" for i in range(1, 11)})
    .tab_options(quarto_disable_processing=True)
)
```
:::

## Unwrapped Table (for comparison)

This table is NOT wrapped and NOT targeted by any selector.

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"X_{i}": [i * 10 + r for r in range(3)]
    for i in range(1, 11)
})

(
    GT(df, id="unwrapped_gt")
    .tab_header(title="Unwrapped Table (10 cols, no scaling)")
    .cols_width(**{f"X_{i}": "110px" for i in range(1, 11)})
    .tab_options(quarto_disable_processing=True)
)
```
📄 04-per-div-min-scale.qmd
---
title: Per-Div Min Scale
---

## Wide Table with Numeric Threshold

This table is inside a `.scale-to-fit` div with
`data-min-scale="0.5"`, which overrides the global
`tablet` keyword threshold.

:::{.scale-to-fit data-min-scale="0.5"}
```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"Col_{i:02d}": [f"val_{r}_{i}" for r in range(4)]
    for i in range(1, 13)
})

(
    GT(df, id="perdiv_numeric")
    .tab_header(title="Per-Div Numeric Threshold (0.5)")
    .cols_width(**{f"Col_{i:02d}": "110px" for i in range(1, 13)})
    .tab_options(quarto_disable_processing=True)
)
```
:::

## Wide Table with Keyword Threshold

This table is inside a `.scale-to-fit` div with
`data-min-scale="mobile"`, so it only scrolls on
viewports at or below 576 px.

:::{.scale-to-fit data-min-scale="mobile"}
```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"Col_{i:02d}": [f"val_{r}_{i}" for r in range(4)]
    for i in range(1, 13)
})

(
    GT(df, id="perdiv_keyword")
    .tab_header(title="Per-Div Keyword Threshold (mobile)")
    .cols_width(**{f"Col_{i:02d}": "110px" for i in range(1, 13)})
    .tab_options(quarto_disable_processing=True)
)
```
:::

## Wide Table without Per-Div Override

This table uses a plain `.scale-to-fit` div with no
`data-min-scale`, so it inherits the global `tablet` threshold.

:::{.scale-to-fit}
```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"Col_{i:02d}": [f"val_{r}_{i}" for r in range(4)]
    for i in range(1, 13)
})

(
    GT(df, id="perdiv_inherit")
    .tab_header(title="Plain Div (inherits global threshold)")
    .cols_width(**{f"Col_{i:02d}": "110px" for i in range(1, 13)})
    .tab_options(quarto_disable_processing=True)
)
```
:::
📄 05-width-comparison.qmd
---
title: Width Comparison
---

This page shows GT tables of increasing widths for visual
comparison. None are auto-scaled (no matching selectors).

## 4-Column Table

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"C{i}": [f"v{r}{i}" for r in range(3)]
    for i in range(1, 5)
})
GT(df, id='cmp_4').tab_header(title='4 Columns').tab_options(quarto_disable_processing=True)
```

## 8-Column Table

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"C{i}": [f"v{r}{i}" for r in range(3)]
    for i in range(1, 9)
})
GT(df, id='cmp_8').tab_header(title='8 Columns').tab_options(quarto_disable_processing=True)
```

## 12-Column Table

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"C{i}": [f"v{r}{i}" for r in range(3)]
    for i in range(1, 13)
})
GT(df, id='cmp_12').tab_header(title='12 Columns').tab_options(quarto_disable_processing=True)
```

## 16-Column Table

```{python}
#| echo: false
from great_tables import GT
import pandas as pd

df = pd.DataFrame({
    f"C{i}": [f"v{r}{i}" for r in range(3)]
    for i in range(1, 17)
})
GT(df, id='cmp_16').tab_header(title='16 Columns').tab_options(quarto_disable_processing=True)
```
📄 README.md
# gdtest-scale-to-fit

Test the 3-level scale-to-fit system for wide HTML output.
📄 great-docs.yml
scale_to_fit:
  - "#wide_gt"
  - "#custom_html"
scale_to_fit_min_scale: tablet