前言

MarkText 的侧边栏在鸿蒙 PC 上显示时,存在多处样式问题:图标过小、间距不合理、滚动条样式不统一。这些问题虽然不影响功能,但严重影响用户体验。由于侧边栏是第三方组件,我们无法直接修改源码。

本文将详细记录我们如何通过动态 CSS 注入完美解决这些样式问题,在不修改原有代码的前提下,实现了鸿蒙 PC 的样式适配。

关键词:鸿蒙PC、Electron适配、CSS注入、样式覆盖、动态样式、布局优化

在这里插入图片描述
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/

目录

  1. 鸿蒙PC的样式问题
  2. CSS注入方案
  3. 完整样式实现
  4. 注入方式对比
  5. 总结与展望

鸿蒙PC的样式问题

1.1 问题清单

问题原因影响
图标过小DPI 设置不同难以点击
间距不合理原设计针对标准桌面拥挤
滚动条样式系统默认样式不美观
按钮尺寸未适配触摸操作困难

1.2 无法修改源码

MarkText 侧边栏

  • 来自第三方 Vue 组件
  • 样式定义在组件内部
  • 无法直接修改

解决方案:使用 CSS 优先级覆盖!


CSS注入方案

2.1 四种注入方式

根据 Electron 官方文档

方式实现位置优先级适用场景
<style> 标签渲染进程动态样式
<link> 标签渲染进程外部文件
webContents.insertCSS主进程全局样式
preload 注入Preload早期注入

2.2 选择方案

MarkText 采用:主进程 insertCSS + 渲染进程备用

理由

  • ✅ 注入时机早(页面加载时)
  • ✅ 优先级高(能覆盖组件样式)
  • ✅ 统一管理(主进程控制)

完整样式实现

3.1 样式文件

/* custom-sidebar-style.css */

/**
 * MarkText 鸿蒙适配 - 侧边栏样式覆盖
 */

/* === 侧边栏容器 === */
.sidebar {
  width: 260px !important;
  min-width: 260px !important;
  background: #252526 !important;
}

/* === 文件列表 === */
.file-list {
  padding: 8px !important;
}

.file-item {
  padding: 10px 16px !important;
  margin-bottom: 4px !important;
  border-radius: 4px !important;
  cursor: pointer !important;
  transition: background 0.2s ease !important;
}

.file-item:hover {
  background: #2a2d2e !important;
}

.file-item.active {
  background: #094771 !important;
  color: #ffffff !important;
}

/* === 文件图标 === */
.file-icon {
  width: 20px !important;
  height: 20px !important;
  margin-right: 12px !important;
}

/* === 按钮组 === */
.sidebar-button {
  flex: 1 !important;
  padding: 8px 12px !important;
  background: #3c3c3c !important;
  border: none !important;
  border-radius: 4px !important;
  color: #cccccc !important;
  cursor: pointer !important;
  font-size: 13px !important;
  transition: all 0.2s ease !important;
}

.sidebar-button:hover {
  background: #464646 !important;
  color: #ffffff !important;
}

/* === 滚动条样式 === */
.sidebar::-webkit-scrollbar {
  width: 10px !important;
}

.sidebar::-webkit-scrollbar-track {
  background: #1e1e1e !important;
}

.sidebar::-webkit-scrollbar-thumb {
  background: #424242 !important;
  border-radius: 5px !important;
}

.sidebar::-webkit-scrollbar-thumb:hover {
  background: #4e4e4e !important;
}

/* === 目录树 === */
.toc-item {
  padding: 6px 12px !important;
  border-radius: 3px !important;
  cursor: pointer !important;
  font-size: 13px !important;
  color: #cccccc !important;
}

.toc-item:hover {
  background: #2a2d2e !important;
}

.toc-item.active {
  background: #094771 !important;
  color: #ffffff !important;
  font-weight: 600 !important;
}

3.2 主进程注入

// main.js (主进程)
const { app, BrowserWindow } = require('electron')
const fs = require('fs').promises
const path = require('path')

/**
 * 从文件加载并注入 CSS
 */
async function injectStyleFile(webContents, filename) {
  try {
    const appPath = app.getAppPath()
    const stylePath = path.join(appPath, 'styles', filename)
  
    console.log(`[Styles] 读取样式文件: ${stylePath}`)
  
    const css = await fs.readFile(stylePath, 'utf-8')
  
    const key = await webContents.insertCSS(css)
  
    console.log(`[Styles] 样式注入成功,key: ${key}`)
  
    return key
  } catch (error) {
    console.error(`[Styles] 样式注入失败:`, error)
    throw error
  }
}

/**
 * 创建主窗口
 */
function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 1400,
    height: 900,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })
  
  // 页面加载完成后注入样式
  mainWindow.webContents.on('did-finish-load', async () => {
    console.log('[Main] 页面加载完成,注入自定义样式')
  
    try {
      await injectStyleFile(mainWindow.webContents, 'custom-sidebar-style.css')
      console.log('[Main] 样式注入完成')
    } catch (error) {
      console.error('[Main] 样式注入失败:', error)
    }
  })
  
  mainWindow.loadFile('index.html')
}

app.whenReady().then(createWindow)

3.3 渲染进程备用方案

// custom-sidebar-style.js (渲染进程)

/**
 * 动态注入侧边栏样式(备用方案)
 */
function injectSidebarStyles() {
  // 检查是否已注入
  if (document.getElementById('custom-sidebar-styles')) {
    console.log('[Styles] 侧边栏样式已存在')
    return
  }
  
  console.log('[Styles] 开始注入侧边栏样式')
  
  const style = document.createElement('style')
  style.id = 'custom-sidebar-styles'
  style.textContent = `
    /* 侧边栏样式 */
    .sidebar {
      width: 260px !important;
      background: #252526 !important;
    }
  
    /* 更多样式... */
  `
  
  document.head.appendChild(style)
  
  console.log('[Styles] 侧边栏样式注入完成')
}

// 在适当时机注入
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', injectSidebarStyles)
} else {
  injectSidebarStyles()
}

注入方式对比

4.1 性能对比

方式注入时机加载速度优先级
主进程 insertCSS页面加载完成高 ✅
<style> 标签DOM 准备好高 ✅
<link> 标签异步加载

4.2 实际效果

改进前

  • 图标:16px(太小)
  • 按钮:6px padding(太挤)
  • 滚动条:系统默认(不美观)

改进后

  • 图标:20px(合适)✅
  • 按钮:8px padding(舒适)✅
  • 滚动条:自定义样式(美观)✅

总结与展望

5.1 成果总结

完美适配鸿蒙PC样式
零侵入性(不修改原有代码)
200+ 行精细样式调整
用户体验显著提升
支持主进程和渲染进程双重注入

5.2 关键技术点

  1. !important:提高优先级覆盖组件样式
  2. webContents.insertCSS:主进程注入
  3. <style> 标签:渲染进程备用
  4. 多重保险:确保样式一定生效

5.3 源码地址

完整代码已开源在 MarkText for HarmonyOS 项目中:

  • 项目地址:https://gitcode.com/szkygc/marktext
  • 关键文件
    • custom-sidebar-style.css - 样式文件
    • main.js - 主进程注入逻辑

相关资源

Electron 官方文档

MDN 文档


技术难度:⭐⭐ 初中级

实战价值:⭐⭐⭐⭐ 解决鸿蒙PC样式适配问题

推荐指数:⭐⭐⭐⭐⭐ 样式定制必备技能

Logo

赋能鸿蒙PC开发者,共建全场景原生生态,共享一次开发多端部署创新价值。

更多推荐