Skip to content

Commit dfb6c48

Browse files
maxwassermanjorisvandenbossche
maxwasserman
authored andcommitted
BUG: Fix css for displaying DataFrames in notebook #16792 (#16879)
1 parent b3087ef commit dfb6c48

File tree

3 files changed

+43
-16
lines changed

3 files changed

+43
-16
lines changed

Diff for: doc/source/whatsnew/v0.21.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ I/O
522522
- Bug in :func:`read_stata` where the index was not set (:issue:`16342`)
523523
- Bug in :func:`read_html` where import check fails when run in multiple threads (:issue:`16928`)
524524
- Bug in :func:`read_csv` where automatic delimiter detection caused a ``TypeError`` to be thrown when a bad line was encountered rather than the correct error message (:issue:`13374`)
525+
- Bug in ``DataFrame.to_html()`` with ``notebook=True`` where DataFrames with named indices or non-MultiIndex indices had undesired horizontal or vertical alignment for column or row labels, respectively (:issue:`16792`)
525526

526527
Plotting
527528
^^^^^^^^

Diff for: pandas/io/formats/format.py

+36-14
Original file line numberDiff line numberDiff line change
@@ -1132,20 +1132,42 @@ def write_tr(self, line, indent=0, indent_delta=4, header=False,
11321132
self.write('</tr>', indent)
11331133

11341134
def write_style(self):
1135-
template = dedent("""\
1136-
<style>
1137-
.dataframe thead tr:only-child th {
1138-
text-align: right;
1139-
}
1140-
1141-
.dataframe thead th {
1142-
text-align: left;
1143-
}
1144-
1145-
.dataframe tbody tr th {
1146-
vertical-align: top;
1147-
}
1148-
</style>""")
1135+
# We use the "scoped" attribute here so that the desired
1136+
# style properties for the data frame are not then applied
1137+
# throughout the entire notebook.
1138+
template_first = """\
1139+
<style scoped>"""
1140+
template_last = """\
1141+
</style>"""
1142+
template_select = """\
1143+
.dataframe %s {
1144+
%s: %s;
1145+
}"""
1146+
element_props = [('tbody tr th:only-of-type',
1147+
'vertical-align',
1148+
'middle'),
1149+
('tbody tr th',
1150+
'vertical-align',
1151+
'top')]
1152+
if isinstance(self.columns, MultiIndex):
1153+
element_props.append(('thead tr th',
1154+
'text-align',
1155+
'left'))
1156+
if all((self.fmt.has_index_names,
1157+
self.fmt.index,
1158+
self.fmt.show_index_names)):
1159+
element_props.append(('thead tr:last-of-type th',
1160+
'text-align',
1161+
'right'))
1162+
else:
1163+
element_props.append(('thead th',
1164+
'text-align',
1165+
'right'))
1166+
template_mid = '\n\n'.join(map(lambda t: template_select % t,
1167+
element_props))
1168+
template = dedent('\n'.join((template_first,
1169+
template_mid,
1170+
template_last)))
11491171
if self.notebook:
11501172
self.write(template)
11511173

Diff for: pandas/tests/io/formats/test_to_html.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -1868,12 +1868,16 @@ def test_to_html_no_index_max_rows(self):
18681868
def test_to_html_notebook_has_style(self):
18691869
df = pd.DataFrame({"A": [1, 2, 3]})
18701870
result = df.to_html(notebook=True)
1871-
assert "thead tr:only-child" in result
1871+
assert "tbody tr th:only-of-type" in result
1872+
assert "vertical-align: middle;" in result
1873+
assert "thead th" in result
18721874

18731875
def test_to_html_notebook_has_no_style(self):
18741876
df = pd.DataFrame({"A": [1, 2, 3]})
18751877
result = df.to_html()
1876-
assert "thead tr:only-child" not in result
1878+
assert "tbody tr th:only-of-type" not in result
1879+
assert "vertical-align: middle;" not in result
1880+
assert "thead th" not in result
18771881

18781882
def test_to_html_with_index_names_false(self):
18791883
# gh-16493

0 commit comments

Comments
 (0)