css格式化一个表格之border-collapse: collapse的使用

我们要完成的表格如下图所示。完成这个任务有许多方法,但是我建议你使用和向导中所用的相似的模式来完成以下的事情。

  • 把标题和包含数字的列数据右对齐
  • 把标题和包含文本的列数据左对齐
  • 添加顶部和底部边框,以及页脚上方的边框
  • 将主表的所有奇数行条纹化

css

table {
    border-collapse: collapse;

    font-size: 75%;
  }
thead th:nth-child(2),
thead th:nth-child(3),
tbody td:nth-child(2),
tbody td:nth-child(3),
tfoot :first-child{
text-align:right;
}
thead th:nth-child(1),
thead th:nth-child(4),
tbody td:nth-child(1),
tbody td:nth-child(4),
tfoot :last-child{
text-align:left;
}

thead {
border-top: solid 1px #c0c0c0;
}
tfoot {
border-bottom:solid 1px #c0c0c0;
border-top: solid 1px #c0c0c0;

}
tbody tr:nth-child(odd) {
background-color: #c0c0c0;
}

注意!!! 

border-collapse: collapse;是关键,不添加thead和tfoot中的boder属性不生效.

 html

 <table>
  <caption>A summary of the UK's most famous punk bands</caption>
  <thead>
    <tr>
      <th scope="col">Band</th>
      <th scope="col">Year formed</th>
      <th scope="col">No. of Albums</th>
      <th scope="col">Most famous song</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Buzzcocks</th>
      <td>1976</td>
      <td>9</td>
      <td>Ever fallen in love (with someone you shouldn't've)</td>
    </tr>
    <tr>
      <th scope="row">The Clash</th>
      <td>1976</td>
      <td>6</td>
      <td>London Calling</td>
    </tr>
    <tr>
      <th scope="row">The Damned</th>
      <td>1976</td>
      <td>10</td>
      <td>Smash it up</td>
    </tr>
    <tr>
      <th scope="row">Sex Pistols</th>
      <td>1975</td>
      <td>1</td>
      <td>Anarchy in the UK</td>
    </tr>
    <tr>
      <th scope="row">Sham 69</th>
      <td>1976</td>
      <td>13</td>
      <td>If the kids are united</td>
    </tr>
    <tr>
      <th scope="row">Siouxsie and the Banshees</th>
      <td>1976</td>
      <td>11</td>
      <td>Hong Kong Garden</td>
    </tr>
    <tr>
      <th scope="row">Stiff Little Fingers</th>
      <td>1977</td>
      <td>10</td>
      <td>Suspect Device</td>
    </tr>
    <tr>
      <th scope="row">The Stranglers</th>
      <td>1974</td>
      <td>17</td>
      <td>No More Heroes</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th scope="row" colspan="2">Total albums</th>
      <td colspan="2">77</td>
    </tr>
  </tfoot>
</table>

文档链接 https://developer.mozilla.org/zh-CN/docs/Learn/CSS/Building_blocks/Advanced_styling_effects

import os import re import markdown from tkinter import Tk, filedialog, Button, Label, messagebox def convert_md_to_html(): md_filepath = filedialog.askopenfilename( title="请选择一个 Markdown 文件", filetypes=[("Markdown 文件", "*.md"), ("所有文件", "*.*")] ) if not md_filepath: return try: with open(md_filepath, 'r', encoding='utf-8') as md_file: md_content = md_file.read() # 转换Markdown为HTML html_body_content = markdown.markdown( md_content, extensions=[ 'markdown.extensions.tables', 'markdown.extensions.fenced_code', 'markdown.extensions.extra', ] ) # 处理Mermaid图表 html_body_content = re.sub( r'<pre><code class="language-mermaid">(.*?)</code></pre>', r'<div class="mermaid">\1</div>', html_body_content, flags=re.DOTALL ) html_body_content = html_body_content.replace('<', '<').replace('>', '>') # 为所有标题添加ID(用于目录锚点) toc_entries = [] heading_counter = {'h1': 0, 'h2': 0, 'h3': 0, 'h4': 0} def add_id_to_heading(match): tag = match.group(1).lower() content = match.group(2) if tag in heading_counter: heading_counter[tag] += 1 id_name = f"{tag}-{heading_counter[tag]}" toc_entries.append((tag, id_name, content)) return f'<{tag} id="{id_name}">{content}</{tag}>' return match.group(0) html_body_content = re.sub( r'<([hH][1-6])>(.*?)</\1>', add_id_to_heading, html_body_content ) # 生成主目录HTML(仅h1和h2) toc_html = '<div class="toc"><h3>目录</h3><ul>' current_h1 = None for tag, id_name, content in toc_entries: if tag == 'h1': current_h1 = id_name toc_html += f'<li><a href="#{id_name}">{content}</a><ul>' elif tag == 'h2' and current_h1: toc_html += f''' <li> <a href="#{id_name}">{content}</a> <span class="detail-icon" onclick="showSubPage('{id_name}')">📖</span> </li> ''' toc_html += '</ul></li></ul></div>' # 添加子页面容器 subpage_html = ''' <div id="subpage" class="subpage"> <div class="subpage-header"> <span class="close-btn" onclick="closeSubPage()">×</span> </div> <div class="subpage-content-container"> <div class="subpage-toc-container"></div> <div class="subpage-content"></div> </div> </div> ''' # 完整HTML结构 html_header = f''' <!DOCTYPE html> <html> <head> <title>Markdown 转 HTML</title> <meta charset="UTF-8"> <style> * {{ box-sizing: border-box; margin: 0; padding: 0; }} body {{ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; display: flex; height: 100vh; overflow: hidden; background-color: #f5f7fa; }} /* 主页面布局 */ .toc-container {{ width: 280px; background: linear-gradient(135deg, #2c3e50, #1a2530); color: #ecf0f1; height: 100vh; overflow-y: auto; padding: 20px 15px; box-shadow: 3px 0 10px rgba(0,0,0,0.1); z-index: 10; }} .toc h3 {{ margin: 0 0 20px 0; padding-bottom: 15px; border-bottom: 1px solid #4a627a; font-size: 1.4em; }} .toc ul {{ list-style: none; padding-left: 15px; }} .toc li {{ margin: 12极狐 0; position: relative; }} .toc a {{ text-decoration: none; color: #bdc3c7; display: block; padding: 8px 5px; border-radius: 4px; transition: all 0.3s ease; }} .toc a:hover {{ background-color: #34495e; color: #fff; padding-left: 10px; }} .detail-icon {{ position: absolute; right: 10px; top: 50%; transform: translateY(-50%); cursor: pointer; color: #3498db; font-size: 1.2em; background: rgba(255,255,255,0.1); border-radius: 50%; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; }} .detail-icon:hover {{ background: rgba(52, 152, 219, 0.3); color: #fff; transform: translateY(-50%) scale(1.1); }} /* 主内容区样式 */ .content-container {{ flex: 1; overflow-y: auto; padding: 30px; height: 100vh; background-color: #fff; }} /* 子页面样式 */ .subpage {{ display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: #fff; z-index: 1000; flex-direction: column; }} .subpage-header {{ height: 60px; background: linear-gradient(135deg, #3498db, #2980b9); display: flex; align-items: center; justify-content: flex-end; padding: 0 25px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }} .close-btn {{ font-size: 36px; font-weight: 300; cursor: pointer; color: #fff; transition: transform 0.2s; }} .close-btn:hover {{ transform: scale(1.2); }} .subpage-content-container {{ display: flex; flex: 1; overflow: hidden; }} .subpage-toc-container {{ width: 240px; background-color: #f8f9fa; height: 100%; overflow-y: auto; padding: 20px; border-right: 1px solid #eaeaea; }} .subpage-content {{ flex: 1; overflow-y: auto; padding: 30px; }} /* 子页面目录样式 */ .sub-toc {{ padding: 15px 0; }} .sub-toc h4 {{ margin: 20px 0 10px 0; color: #2c3e50; padding-bottom: 8px; border-bottom: 1px dashed #ddd; }} .sub-toc ul {{ list-style: none; padding-left: 15px; }} .sub-toc li {{ margin: 10px 0; }} .sub-toc a {{ text-decoration: none; color: #3498db; display: block; padding: 6px 10px; border-radius: 4px; transition: all 0.2s; }} .sub-t极狐 a:hover {{ background-color: #e3f2fd; padding-left: 15px; }} /* 内容样式 */ .content-section {{ margin-bottom: 40px; padding-bottom: 20px; border-bottom: 1px solid #eee; }} h1 {{ font-size: 2.2em; margin-bottom: 20px; padding-bottom: 15px; border-bottom: 2px solid #3498db; color: #2c3e50; }} h2 {{ font-size: 1.8em; margin: 30px 0 15px 0; color: #2980b9; }} h3 {{ font-size: 1.5em; margin: 25px 0 12px 0; color: #3498db; }} h4 {{ font-size: 1.3em; margin: 20px 0 10px 0; color: #2c3e50; }} p {{ font-size: 16px; line-height: 1.8; margin-bottom: 15px; color: #34495e; }} table {{ border-collapse: collapse; width: 100%; margin: 25px 0; box-shadow: 0 2px 5px rgba(0,0,0,0.05); }} th, td {{ border: 1px solid #e0e0e0; padding: 12px 15px; text-align: left; }} th {{ background-color: #f8f9fa; font-weight: 600; color: #2c3e50; }} tr:nth-child(even) {{ background-color: #fcfcfc; }} pre {{ background-color: #2d2d2d; padding: 20px; border-radius: 6px; margin: 20px 0; overflow-x: auto; color: #f8f8f2; }} code {{ font-family: 'Fira Code', monospace; background-color: #f1f1f1; padding: 2px 6px; border-radius: 4px; color: #c7254e; }} /* Mermaid 图表样式 */ .mermaid {{ background-color: white; padding: 25px; margin: 30px 0; border-radius: 8px; overflow: visible !important; text-align: center; box-shadow: 0 4px 12px rgba(0,0,0,0.08); border: 1px solid #eaeaea; }} </style> <link href="https://fonts.googleapis.com/css2?family=Fira+Code&display=swap" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/mermaid.min.js"></script> <script> // 初始化Mermaid document.addEventListener("DOMContentLoaded", function() {{ mermaid.initialize({{ startOnLoad: true, theme: 'default', flowchart: {{ useMaxWidth: false, htmlLabels: true }} }}); // 平滑滚动到锚点 document.querySelectorAll('.toc a, .sub-toc a').forEach(anchor => {{ anchor.addEventListener('click', function(e) {{ e.preventDefault(); const targetId = this.getAttribute('href'); const targetElement = document.querySelector(targetId); if (targetElement) {{ let container = this.closest('.subpage') ? document.querySelector('.subpage-content') : document.querySelector('.content-container'); container.scrollTo({{ top: targetElement.offsetTop - 30, behavior: 'smooth' }}); }} }}); }}); }}); // 显示子页面 function showSubPage(sectionId) {{ const section = document.getElementById(sectionId); if (!section) return; // 获取该部分所有内容 let contentHtml = section.outerHTML; let nextElement = section.nextElementSibling; // 收集直到下一个h1/h2的内容 while (nextElement && !['H1', 'H2'].includes(nextElement.tagName)) {{ contentHtml += nextElement.outerHTML; nextElement = nextElement.nextElementSibling; }} // 获取该部分的三四级标题 const tempDiv = document.createElement('div'); tempDiv.innerHTML = contentHtml; const subHeadings = tempDiv.querySelectorAll('h3, h4'); // 生成子目录 let subTocHtml = '<div class="sub-toc"><h4>内容导航</h4><ul>'; subHeadings.forEach(heading => {{ const id = heading.id; const text = heading.textContent; const tag = heading.tagName.toLowerCase(); // 正确变量名:indent const indent = tag === 'h4' ? 'style="margin-left: 20px;"' : ''; subTocHtml += ` <li ${indent}> <a href="#${id}">${text}</a> </li> `; }}); subTocHtml += '</ul></div>'; // 更新子页面内容 document.querySelector('.subpage-toc-container').innerHTML = subTocHtml; document.querySelector('.subpage-content').innerHTML = contentHtml; // 重新初始化Mermaid图表 mermaid.init(undefined, '.subpage-content .mermaid'); // 显示子页面 document.getElementById('subpage').style.display = 'flex'; }} // 关闭子页面 function closeSubPage() {{ document.getElementById('subpage').style.display = 'none'; }} </script> </head> <body> ''' html_footer = ''' </body> </html> ''' # 构建完整HTML full_html_content = f''' {html_header} <div class="toc-container"> {toc_html} </div> <div class="content-container"> {html_body_content} </div> {subpage_html} {html_footer} ''' # 保存HTML文件 base_name = os.path.basename(md_filepath) html_filename = os.path.splitext(base_name)[0] + '.html' html_filepath = os.path.join(os.path.dirname(md_filepath), html_filename) with open(html_filepath, 'w', encoding='utf-8') as html_file: html_file.write(full_html_content) messagebox.showinfo("成功", f"HTML 文件已成功生成!保存位置:\n{html_filepath}") except Exception as e: messagebox.showerror("错误", f"转换过程中出现错误:\n{str(e)}") def main(): root = Tk() root.title("Markdown 转 HTML 转换工具") root.geometry("400x200") label = Label(root, text="选择 Markdown 文件并生成 HTML 文件:", font=("Arial", 12)) label.pack(pady=20) convert_button = Button(root, text="选择文件并转换", command=convert_md_to_html, font=("Arial", 10)) convert_button.pack(pady=20) root.mainloop() if __name__ == "__main__": main()
最新发布
08-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值