Skip to content

Commit 8b12cb6

Browse files
authored
ENH: omit CSSStyle rules for hidden table elements (#43619) (#43673)
* ENH: omit CSSStyle rules for hidden table cells (#43619)
1 parent 9a21c3c commit 8b12cb6

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Styler
7979
- Keyword arguments ``level`` and ``names`` added to :meth:`.Styler.hide_index` and :meth:`.Styler.hide_columns` for additional control of visibility of MultiIndexes and index names (:issue:`25475`, :issue:`43404`, :issue:`43346`)
8080
- Global options have been extended to configure default ``Styler`` properties including formatting and encoding and mathjax options and LaTeX (:issue:`41395`)
8181
- Naive sparsification is now possible for LaTeX without the multirow package (:issue:`43369`)
82+
- :meth:`Styler.to_html` omits CSSStyle rules for hidden table elements (:issue:`43619`)
8283

8384
Formerly Styler relied on ``display.html.use_mathjax``, which has now been replaced by ``styler.html.mathjax``.
8485

pandas/io/formats/style_render.py

+21-6
Original file line numberDiff line numberDiff line change
@@ -378,11 +378,12 @@ def _translate_header(
378378
if clabels:
379379
column_headers = []
380380
for c, value in enumerate(clabels[r]):
381+
header_element_visible = _is_visible(c, r, col_lengths)
381382
header_element = _element(
382383
"th",
383384
f"{col_heading_class} level{r} col{c}",
384385
value,
385-
_is_visible(c, r, col_lengths),
386+
header_element_visible,
386387
display_value=self._display_funcs_columns[(r, c)](value),
387388
attributes=(
388389
f'colspan="{col_lengths.get((r, c), 0)}"'
@@ -393,7 +394,11 @@ def _translate_header(
393394

394395
if self.cell_ids:
395396
header_element["id"] = f"level{r}_col{c}"
396-
if (r, c) in self.ctx_columns and self.ctx_columns[r, c]:
397+
if (
398+
header_element_visible
399+
and (r, c) in self.ctx_columns
400+
and self.ctx_columns[r, c]
401+
):
397402
header_element["id"] = f"level{r}_col{c}"
398403
self.cellstyle_map_columns[
399404
tuple(self.ctx_columns[r, c])
@@ -537,11 +542,14 @@ def _translate_body(
537542

538543
index_headers = []
539544
for c, value in enumerate(rlabels[r]):
545+
header_element_visible = (
546+
_is_visible(r, c, idx_lengths) and not self.hide_index_[c]
547+
)
540548
header_element = _element(
541549
"th",
542550
f"{row_heading_class} level{c} row{r}",
543551
value,
544-
_is_visible(r, c, idx_lengths) and not self.hide_index_[c],
552+
header_element_visible,
545553
display_value=self._display_funcs_index[(r, c)](value),
546554
attributes=(
547555
f'rowspan="{idx_lengths.get((c, r), 0)}"'
@@ -552,7 +560,11 @@ def _translate_body(
552560

553561
if self.cell_ids:
554562
header_element["id"] = f"level{c}_row{r}" # id is specified
555-
if (r, c) in self.ctx_index and self.ctx_index[r, c]:
563+
if (
564+
header_element_visible
565+
and (r, c) in self.ctx_index
566+
and self.ctx_index[r, c]
567+
):
556568
# always add id if a style is specified
557569
header_element["id"] = f"level{c}_row{r}"
558570
self.cellstyle_map_index[tuple(self.ctx_index[r, c])].append(
@@ -580,18 +592,21 @@ def _translate_body(
580592
if (r, c) in self.cell_context:
581593
cls = " " + self.cell_context[r, c]
582594

595+
data_element_visible = (
596+
c not in self.hidden_columns and r not in self.hidden_rows
597+
)
583598
data_element = _element(
584599
"td",
585600
f"{data_class} row{r} col{c}{cls}",
586601
value,
587-
(c not in self.hidden_columns and r not in self.hidden_rows),
602+
data_element_visible,
588603
attributes="",
589604
display_value=self._display_funcs[(r, c)](value),
590605
)
591606

592607
if self.cell_ids:
593608
data_element["id"] = f"row{r}_col{c}"
594-
if (r, c) in self.ctx and self.ctx[r, c]:
609+
if data_element_visible and (r, c) in self.ctx and self.ctx[r, c]:
595610
# always add id if needed due to specified style
596611
data_element["id"] = f"row{r}_col{c}"
597612
self.cellstyle_map[tuple(self.ctx[r, c])].append(f"row{r}_col{c}")

pandas/tests/io/formats/style/test_html.py

+63
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,66 @@ def test_maximums(styler_mi, rows, cols):
467467
assert ">5</td>" in result # [[0,1], [4,5]] always visible
468468
assert (">8</td>" in result) is not rows # first trimmed vertical element
469469
assert (">2</td>" in result) is not cols # first trimmed horizontal element
470+
471+
472+
def test_include_css_style_rules_only_for_visible_cells(styler_mi):
473+
# GH 43619
474+
result = (
475+
styler_mi.set_uuid("")
476+
.applymap(lambda v: "color: blue;")
477+
.hide_columns(styler_mi.data.columns[1:])
478+
.hide_index(styler_mi.data.index[1:])
479+
.to_html()
480+
)
481+
expected_styles = dedent(
482+
"""\
483+
<style type="text/css">
484+
#T__row0_col0 {
485+
color: blue;
486+
}
487+
</style>
488+
"""
489+
)
490+
assert expected_styles in result
491+
492+
493+
def test_include_css_style_rules_only_for_visible_index_labels(styler_mi):
494+
# GH 43619
495+
result = (
496+
styler_mi.set_uuid("")
497+
.applymap_index(lambda v: "color: blue;", axis="index")
498+
.hide_columns(styler_mi.data.columns)
499+
.hide_index(styler_mi.data.index[1:])
500+
.to_html()
501+
)
502+
expected_styles = dedent(
503+
"""\
504+
<style type="text/css">
505+
#T__level0_row0, #T__level1_row0 {
506+
color: blue;
507+
}
508+
</style>
509+
"""
510+
)
511+
assert expected_styles in result
512+
513+
514+
def test_include_css_style_rules_only_for_visible_column_labels(styler_mi):
515+
# GH 43619
516+
result = (
517+
styler_mi.set_uuid("")
518+
.applymap_index(lambda v: "color: blue;", axis="columns")
519+
.hide_columns(styler_mi.data.columns[1:])
520+
.hide_index(styler_mi.data.index)
521+
.to_html()
522+
)
523+
expected_styles = dedent(
524+
"""\
525+
<style type="text/css">
526+
#T__level0_col0, #T__level1_col0 {
527+
color: blue;
528+
}
529+
</style>
530+
"""
531+
)
532+
assert expected_styles in result

0 commit comments

Comments
 (0)