Last modified: Jan 28, 2026 By Alexander Williams

Python HTML Tables That Look Like Excel

Presenting data clearly on the web is a common challenge for developers. While raw data in a Python list or a pandas DataFrame is useful for analysis, sharing it often requires a more polished, visual format. This is where generating HTML tables that resemble familiar Excel spreadsheets becomes invaluable. By leveraging Python's powerful libraries, you can transform datasets into professional, interactive, and stylized tables directly in a web browser, bypassing the need for proprietary software. This guide will walk you through the key techniques to achieve this, from basic HTML generation to advanced styling.

Why Style HTML Tables Like Excel?

Excel's grid layout is a global standard for data presentation. Its clean rows, columns, and subtle visual cues like alternating row colors and borders make data easy to scan and interpret. Replicating this style in HTML offers significant advantages. It enhances user experience by presenting data in a familiar format, improves readability for large datasets, and allows for seamless integration of data analysis results into web applications or automated reports. Instead of sending static files, you can create dynamic, web-native tables that are instantly viewable.

Core Method: Using pandas for Quick Conversion

The pandas library is the cornerstone of data manipulation in Python and provides the simplest path to an Excel-like HTML table. Its to_html method converts a DataFrame directly into an HTML string. While the default output is plain, it includes CSS classes that we can target for styling.


import pandas as pd

# Create a sample DataFrame
data = {
    'Product': ['Laptop', 'Mouse', 'Keyboard', 'Monitor'],
    'Q1 Sales': [120, 300, 150, 90],
    'Q2 Sales': [135, 320, 145, 110],
    'Growth %': [12.5, 6.7, -3.3, 22.2]
}
df = pd.DataFrame(data)

# Convert DataFrame to a basic HTML table
html_string = df.to_html(index=False, classes='excel-table')
print(html_string[:500]) # Print first 500 characters
    

This code generates the raw HTML structure. The classes='excel-table' parameter is crucial, as it adds a custom CSS class to the <table> tag, allowing us to style it. The output is a plain table, which we will soon transform.

Styling with CSS for the Excel Look

The magic happens with Cascading Style Sheets (CSS). By writing CSS rules that target our table, we can replicate Excel's aesthetic. Key styling features include distinct borders, alternating row colors (zebra striping), a highlighted header, and cell padding for readability.


# Let's embed the CSS and HTML together in a complete example
complete_html = f"""
<!DOCTYPE html>
<html>
<head>
    <style>
        table.excel-table {{
            border-collapse: collapse;
            width: 100%;
            font-family: Arial, sans-serif;
        }}
        .excel-table th {{
            background-color: #4CAF50; /* Excel-like green header */
            color: white;
            text-align: center;
            padding: 12px;
            border: 1px solid #ddd;
        }}
        .excel-table td {{
            padding: 10px;
            border: 1px solid #ddd;
            text-align: right; /* Right-align numbers */
        }}
        .excel-table tr:nth-child(even) {{
            background-color: #f2f2f2; /* Zebra striping */
        }}
        .excel-table tr:hover {{
            background-color: #e0f7fa; /* Hover effect */
        }}
    </style>
</head>
<body>
    {df.to_html(index=False, classes='excel-table')}
</body>
</html>
"""

# Save to a file to view in a browser
with open('excel_table.html', 'w') as f:
    f.write(complete_html)
print("HTML file 'excel_table.html' has been created.")
    

When you open the generated HTML file in a browser, you will see a table that closely mimics an Excel sheet: a green header, light gray alternating rows, a hover effect, and clean gridlines. This approach is perfect for static reports. For more complex HTML generation and templating, you can explore the Python HTML Module: Parsing and Generating HTML.

Advanced Technique: Using Jinja2 for Dynamic Templates

For more control and dynamic content, especially in web applications, the Jinja2 templating engine is superior. It separates HTML structure from Python logic. You create a template file with placeholders and then render it with your data.

First, create a template file named table_template.html:


<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="table_style.css">
</head>
<body>
    <h2>Sales Report</h2>
    <table class="excel-table">
        <thead>
            <tr>
                {% for column in columns %}
                <th>{{ column }}</th>
                {% endfor %}
            </tr>
        </thead>
        <tbody>
            {% for row in data %}
            <tr>
                {% for cell in row %}
                <td>{{ cell }}</td>
                {% endfor %}
            </tr>
            {% endfor %}
        </tbody>
    </table>
</body>
</html>
    

Next, use Python to render this template with your data:


from jinja2 import Environment, FileSystemLoader
import pandas as pd

# Load data
df = pd.DataFrame({
    'Product': ['Laptop', 'Mouse'],
    'Q1 Sales': [120, 300],
    'Q2 Sales': [135, 320]
})

# Prepare data for Jinja2: Convert DataFrame to a list of lists
columns = df.columns.tolist()
data = df.values.tolist()

# Set up Jinja2 environment
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('table_template.html')

# Render template with data
output_html = template.render(columns=columns, data=data)

# Save the output
with open('dynamic_table.html', 'w') as f:
    f.write(output_html)
    

This method is incredibly powerful for building web dashboards or reports where the table data changes frequently. The CSS (in a separate table_style.css file) can be reused across multiple pages, ensuring consistency.

Adding Interactivity with JavaScript Libraries

To truly match Excel's functionality, consider adding client-side interactivity. Lightweight JavaScript libraries like DataTables or Handsontable can be integrated into your Python-generated HTML. These libraries provide sorting, filtering, pagination, and even in-cell editing directly in the browser.

The process involves generating the basic HTML table using pandas or Jinja2, as shown above, and then including the library's CSS and JavaScript files in the <head> section, along with a short initialization script. This transforms your static table into a fully-featured, interactive data grid.

Conclusion

Creating Python HTML tables that look like Excel spreadsheets is a straightforward process that significantly enhances data communication. By starting with pandas' simple to_html conversion and applying targeted CSS, you can quickly produce professional-looking static tables. For dynamic, complex applications, combining Jinja2 templating with a separate stylesheet offers maintainability and power. Finally, incorporating JavaScript libraries can bridge the gap to full spreadsheet-like interactivity. Whether for automated reporting, dashboards, or data sharing, these techniques allow you to present your Python data analysis with the clarity and familiarity of an Excel sheet, directly on the web.