1

I have a Jupyter notebook python cell where I'm trying to display some output in an HTML formatted table. I can't seem to be able to remove the border lines around internal cells.

Here's the HTML that I generate:

<html><style>
    table {border-style: solid; border-color: DodgerBlue;}
    .cp {background-color:DarkGreen; border-collapse:collapse;text-align:center;}
    .cf {background-color:DarkRed; border-collapse:collapse;text-align:center;}
</style>
<table>
<caption>Automaton 1 Evaluation</caption>
<caption style="background-color:DodgerBlue;">State Seen At Step</caption>
<thead style="background-color:DodgerBlue;"> 
    <tr><th>Trace #</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th></tr></thead>
<tbody>
    <tr><td style="text-align:center;">0</td><td  class="cp">1</td><td  class="cf">3</td><td  class="cf">3</td><td  class="cf">3</td><td  class="cf">3</td></tr>
    <tr><td style="text-align:center;">1</td><td  class="cp">1</td><td  class="cp">0</td><td  class="cp">1</td><td  class="cp">1</td><td  class="cp">0</td></tr>
    <tr><td style="text-align:center;">2</td><td  class="cp">1</td><td  class="cp">0</td><td  class="cp">1</td><td  class="cp">0</td><td  class="cp">0</td></tr>
    <tr><td style="text-align:center;">3</td><td  class="cp">1</td><td >2</td><td  class="cp">0</td><td  class="cp">1</td><td >2</td></tr>
    <tr><td style="text-align:center;">4</td><td  class="cp">1</td><td >2</td><td  class="cp">1</td><td >2</td><td >2</td></tr>
</tbody>
</table></html>

and I display it in the cell using:

from IPython.display import HTML, display
tbl1 = auto1.traceListHTML(auto1.traceLog,title=f'Automaton 1 Evaluation')
tbl2 = auto2.traceListHTML(auto2.traceLog,title=f'Automaton 2 Evaluation')

box_layout = Layout(display='flex',
                    flex_flow='row',
                    justify_content='space-around',
                    width='450px'
                   )

#display(HTML(tbl1))
hbox1 = widgets.Box(children=[widgets.HTML(tbl1),widgets.HTML(tbl2)], layout=box_layout)
display(hbox1)

where auto1.traceListHTML generates the above HTML code.

What I get is: Display of above HTML in notebook cell

I'm trying to get rid of the hairlines between the internal cells. Even if I add border-style: solid to my .cp and.cf styles, those thin black lines remain as seen here:

.cf {background-color:DarkRed; border-collapse:collapse;text-align:center; border-style: solid}

Display of same HTML but with addition of border-style: solid

I'm wondering if this might be a problem with IPython.

1
  • It is best to include a minimal, reproducible example in your post. See the section 'Help others reproduce the problem' in How do I ask a good question?. I think I converted what you had closer to one and got rid of all borders. I'm happy to delete it later but for now it may help you improve your post. Or let others try things more easily. Commented Aug 23, 2024 at 16:36

1 Answer 1

1

Skip to the bottom section because I think I got it...

Leaving this here though because maybe it will help someone else with less complicated needs. Or help others to see the journey.


This doesn't quite work as I believe you want, but you didn't provide an minimal, reproducible example which I think mine does:

Cell #1 content:

# I added the `<table cellspacing="0" cellpadding="0">` from https://stackoverflow.com/a/71657476/8508004
s='''<html><style>
    table {border-style: solid; border-color: DodgerBlue;}
    .cp {background-color:DarkGreen; text-align:center;}
    .cf {background-color:DarkRed; text-align:center;}
</style>
<table cellspacing="0" cellpadding="0">
<caption>Automaton 1 Evaluation</caption>
<caption style="background-color:DodgerBlue;">State Seen At Step</caption>
<thead style="background-color:DodgerBlue;"> 
    <tr><th>Trace #</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th></tr></thead>
<tbody>
    <tr><td style="text-align:center;">0</td><td  class="cp">1</td><td  class="cf">3</td><td  class="cf">3</td><td  class="cf">3</td><td  class="cf">3</td></tr>
    <tr><td style="text-align:center;">1</td><td  class="cp">1</td><td  class="cp">0</td><td  class="cp">1</td><td  class="cp">1</td><td  class="cp">0</td></tr>
    <tr><td style="text-align:center;">2</td><td  class="cp">1</td><td  class="cp">0</td><td  class="cp">1</td><td  class="cp">0</td><td  class="cp">0</td></tr>
    <tr><td style="text-align:center;">3</td><td  class="cp">1</td><td >2</td><td  class="cp">0</td><td  class="cp">1</td><td >2</td></tr>
    <tr><td style="text-align:center;">4</td><td  class="cp">1</td><td >2</td><td  class="cp">1</td><td >2</td><td >2</td></tr>
</tbody>
</table></html>'''

Cell #2 content:

from IPython.display import HTML, display
from ipywidgets import widgets, Layout, HTML
tbl1 = s
tbl2 = s

box_layout = Layout(display='flex',
                    flex_flow='row',
                    justify_content='space-around',
                    width='450px'
                   )

#display(HTML(tbl1))
hbox1 = widgets.Box(children=[widgets.HTML(tbl1),widgets.HTML(tbl2)], layout=box_layout)
display(hbox1)

Result:

enter image description here

Key was I added the <table cellspacing="0" cellpadding="0"> from here, but you probably wanted the table itself to have a border? So that is why I suppose it isn't complete.

So I need to go back to <table>....


Maybe closer:

s='''<html><style>
    table {
        border: 2px solid #222222;
        border-collapse: collapse;
    }
    td, th {
        border: none;
        padding: 5px;
    }
    caption {
        background-color: DodgerBlue;
        color: white;
        padding: 5px;
    }
    thead {
        background-color: DodgerBlue;
        color: white;
    }
    .cp {background-color:DarkGreen; color: white; text-align:center;}
    .cf {background-color:DarkRed; color: white; text-align:center;}
</style>
<table>
<caption>Automaton 1 Evaluation</caption>
<caption>State Seen At Step</caption>
<thead> 
    <tr><th>Trace #</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th></tr>
</thead>
<tbody>
    <tr><td style="text-align:center;">0</td><td class="cp">1</td><td class="cf">3</td><td class="cf">3</td><td class="cf">3</td><td class="cf">3</td></tr>
    <tr><td style="text-align:center;">1</td><td class="cp">1</td><td class="cp">0</td><td class="cp">1</td><td class="cp">1</td><td class="cp">0</td></tr>
    <tr><td style="text-align:center;">2</td><td class="cp">1</td><td class="cp">0</td><td class="cp">1</td><td class="cp">0</td><td class="cp">0</td></tr>
    <tr><td style="text-align:center;">3</td><td class="cp">1</td><td>2</td><td class="cp">0</td><td class="cp">1</td><td>2</td></tr>
    <tr><td style="text-align:center;">4</td><td class="cp">1</td><td>2</td><td class="cp">1</td><td>2</td><td>2</td></tr>
</tbody>
</table></html>'''
from IPython.display import HTML, display
from ipywidgets import widgets, Layout, HTML
tbl1 = s
tbl2 = s

box_layout = Layout(display='flex',
                    flex_flow='row',
                    justify_content='space-around',
                    width='450px'
                    )

#display(HTML(tbl1))
hbox1 = widgets.Box(children=[widgets.HTML(tbl1),widgets.HTML(tbl2)], layout=box_layout)
display(hbox1)

enter image description here


Or closer option #2:

s='''<html><style>
    table {
        border: 4px solid DodgerBlue;
        border-collapse: separate;
        border-spacing: 0;
    }
    table::after {
        content: '';
        position: absolute;
        top: 1px;
        left: 1px;
        right: 1px;
        bottom: 1px;
        border: 1px solid #222222;
    }
    td, th {
        border: none;
        padding: 5px;
        position: relative;
    }
    caption {
        background-color: DodgerBlue;
        color: white;
        padding: 5px;
    }
    thead {
        background-color: DodgerBlue;
        color: white;
    }
    .cp {background-color:DarkGreen; color: white; text-align:center;}
    .cf {background-color:DarkRed; color: white; text-align:center;}
</style>
<table>
<caption>Automaton 1 Evaluation</caption>
<caption>State Seen At Step</caption>
<thead> 
    <tr><th>Trace #</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th></tr>
</thead>
<tbody>
    <tr><td style="text-align:center;">0</td><td class="cp">1</td><td class="cf">3</td><td class="cf">3</td><td class="cf">3</td><td class="cf">3</td></tr>
    <tr><td style="text-align:center;">1</td><td class="cp">1</td><td class="cp">0</td><td class="cp">1</td><td class="cp">1</td><td class="cp">0</td></tr>
    <tr><td style="text-align:center;">2</td><td class="cp">1</td><td class="cp">0</td><td class="cp">1</td><td class="cp">0</td><td class="cp">0</td></tr>
    <tr><td style="text-align:center;">3</td><td class="cp">1</td><td>2</td><td class="cp">0</td><td class="cp">1</td><td>2</td></tr>
    <tr><td style="text-align:center;">4</td><td class="cp">1</td><td>2</td><td class="cp">1</td><td>2</td><td>2</td></tr>
</tbody>
</table></html>'''
from IPython.display import HTML, display
from ipywidgets import widgets, Layout, HTML
tbl1 = s
tbl2 = s

box_layout = Layout(display='flex',
                    flex_flow='row',
                    justify_content='space-around',
                    width='450px'
                    )

#display(HTML(tbl1))
hbox1 = widgets.Box(children=[widgets.HTML(tbl1),widgets.HTML(tbl2)], layout=box_layout)
display(hbox1)

enter image description here

Or closer option #3:

s='''<html><style>
    table {
        border: 4px solid DodgerBlue;
        border-top: 4px solid #333333;
        border-collapse: collapse;
    }
    td, th {
        border: none;
        padding: 5px;
    }
    caption {
        background-color: DodgerBlue;
        color: white;
        padding: 5px;
    }
    thead {
        background-color: DodgerBlue;
        color: white;
    }
    .cp {background-color:DarkGreen; color: white; text-align:center;}
    .cf {background-color:DarkRed; color: white; text-align:center;}
</style>
<table>
<caption>Automaton 1 Evaluation</caption>
<caption>State Seen At Step</caption>
<thead> 
    <tr><th>Trace #</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th></tr>
</thead>
<tbody>
    <tr><td style="text-align:center;">0</td><td class="cp">1</td><td class="cf">3</td><td class="cf">3</td><td class="cf">3</td><td class="cf">3</td></tr>
    <tr><td style="text-align:center;">1</td><td class="cp">1</td><td class="cp">0</td><td class="cp">1</td><td class="cp">1</td><td class="cp">0</td></tr>
    <tr><td style="text-align:center;">2</td><td class="cp">1</td><td class="cp">0</td><td class="cp">1</td><td class="cp">0</td><td class="cp">0</td></tr>
    <tr><td style="text-align:center;">3</td><td class="cp">1</td><td>2</td><td class="cp">0</td><td class="cp">1</td><td>2</td></tr>
    <tr><td style="text-align:center;">4</td><td class="cp">1</td><td>2</td><td class="cp">1</td><td>2</td><td>2</td></tr>
</tbody>
</table></html>'''
from IPython.display import HTML, display
from ipywidgets import widgets, Layout, HTML
tbl1 = s
tbl2 = s

box_layout = Layout(display='flex',
                    flex_flow='row',
                    justify_content='space-around',
                    width='450px'
                    )

#display(HTML(tbl1))
hbox1 = widgets.Box(children=[widgets.HTML(tbl1),widgets.HTML(tbl2)], layout=box_layout)
display(hbox1)

enter image description here


I think this does it?

Made a secondary caption and applied styling to that to separate it from the top part of the table.

(Plus I realized the top caption had gotten the dodger blue background along the way and OP wanted it dark.)

s='''<html><style>
    table {
        border: 4px solid DodgerBlue;
        border-collapse: collapse;
        width: 100%;
    }
    td, th {
        border: none;
        padding: 5px;
    }
    caption {
        color: white;
        padding: 5px;
    }
    .primary-caption {
        background-color: black;
    }
    .secondary-caption {
        background-color: DodgerBlue;
        border-bottom: 1px solid black;
    }
    thead {
        background-color: DodgerBlue;
        color: white;
    }
    .table-header {
        border-top: 1px solid black;
    }
    .cp {background-color:DarkGreen; color: white; text-align:center;}
    .cf {background-color:DarkRed; color: white; text-align:center;}
</style>
<table>
<caption class="primary-caption">Automaton 1 Evaluation</caption>
<caption class="secondary-caption">State Seen At Step</caption>
<thead class="table-header"> 
    <tr><th>Trace #</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th></tr>
</thead>
<tbody>
    <tr><td style="text-align:center;">0</td><td class="cp">1</td><td class="cf">3</td><td class="cf">3</td><td class="cf">3</td><td class="cf">3</td></tr>
    <tr><td style="text-align:center;">1</td><td class="cp">1</td><td class="cp">0</td><td class="cp">1</td><td class="cp">1</td><td class="cp">0</td></tr>
    <tr><td style="text-align:center;">2</td><td class="cp">1</td><td class="cp">0</td><td class="cp">1</td><td class="cp">0</td><td class="cp">0</td></tr>
    <tr><td style="text-align:center;">3</td><td class="cp">1</td><td>2</td><td class="cp">0</td><td class="cp">1</td><td>2</td></tr>
    <tr><td style="text-align:center;">4</td><td class="cp">1</td><td>2</td><td class="cp">1</td><td>2</td><td>2</td></tr>
</tbody>
</table></html>'''
from IPython.display import HTML, display
from ipywidgets import widgets, Layout, HTML

tbl1 = s
tbl2 = s

box_layout = Layout(display='flex',
                    flex_flow='row',
                    justify_content='space-around',
                    width='450px'
                   )

hbox1 = widgets.Box(children=[widgets.HTML(tbl1),widgets.HTML(tbl2)], layout=box_layout)
display(hbox1)

enter image description here


Update:
I assumed since title was called caption that the original came from Python/Pandas and I have since added here more of that journey to make it easier to try different things, such as how IPython's HTML() seems to yield different look than ipywidget's HTML(). (Somewhat related, maybe very tangentially, is this discussion of the two ways to display HTML.)
The header details where you can get sessions in your browser to try it without touching your own system. Meant for JupyterLab Dark Theme.

Additional resources

This answer to 'Style a dataframe in notebook with indentation' contains some style options with provided code for a Pandas dataframe styler/styling table as well.


Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for that detailed analysis. Interestingly, it was the table styling that fixed the problem. I went on to implement the other changes for improved structure. I also learned that there's a difference between IPython.display.display(IPython.display.HTML(htmlString)) and IPython.display.display(ipywidgets.widgets.HTML(htmlString)). They don't produce exactly the same output as widgets.HTML produced the black spaces and IPython's HTML did not.
Super interesting. In attempting to flesh out the incomplete snippet you had provided, I had just grabbed some old code I had. I tend to work with ipywidgets a lot and so I went that direction. I hadn't noticed I had clobbered IPython display's HTML with the widget HTML until you brought this up. I'll have to explore the difference with IPython.display.HTML(htmlString) more some time with some examples based on these. Thanks for pointing that out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.