> **本文回答**：控件 / Popup / Marker 显示异常 —— 缺 vjmap 主题 CSS。

## 一、症状

- 缩放控件 `+` / `-` 按钮没边框、没图标
- Popup 尖角不对 / 颜色全白 / 字体异常
- 比例尺、全屏按钮错位
- vjmapext 的命令行 UI 空白（`createUI` 未调用的典型表现）

## 二、根因：未引入 CSS

vjmap 的内置 UI 依赖样式表：

```html
<link rel="stylesheet" href="https://vjmap.com/demo/js/vjmap/vjmap.min.css" />
```

npm：

```js
import 'vjmap/dist/vjmap.min.css';
```

**vjmapext 没有独立 CSS 文件**（`dist/` 只有 `vjmapext.min.js` + `vjmapext.d.ts`）——它的 UI 样式由 `createUI` 内置主题管理器用 JS 注入 `<style data-mapcad-theme>`（`buildCSS()` 生成，`mapcad-ui` / `data-theme` / `mapcad-*` 前缀），不需要也不能 import css。

## 三、检查是否已加载

DevTools → Network 过滤 CSS → 应看到：

- `vjmap.min.css` 200

（vjmapext 样式不走网络——在 Elements 里找 `<style data-mapcad-theme>` 节点；没有则说明 `createUI` 没被调用。）

## 四、npm 方式

`main.js`：

```js
import 'vjmap/dist/vjmap.min.css';
import * as vjmap from 'vjmap';
```

Vite 下这样就会自动打包 CSS。

## 五、按需加载

如果不用 vjmapext UI，只用核心功能：

```js
import * as vjmapext from 'vjmapext';
```

用 UI 组件也只是调 `createUI()`——样式由 JS 注入，无需额外 import。

## 六、CSS 类名命名

vjmap 内置 UI 元素一律使用 `vjmapgis-*` 前缀的 CSS 类名，如：

```
.vjmapgis-map
.vjmapgis-canvas-container
.vjmapgis-canvas
.vjmapgis-popup
.vjmapgis-popup-content
.vjmapgis-popup-tip
.vjmapgis-popup-close-button
.vjmapgis-ctrl
.vjmapgis-ctrl-group
.vjmapgis-marker
```

自定义样式时用这些类名覆写 —— 而不是改名。

> vjmapext UI 用另一套前缀：`mapcad-*`（容器 `mapcad-ui`、主题属性 `data-theme="dark|light"`、注入节点 `style[data-mapcad-theme]`）。

## 七、Scoped CSS 陷阱

Vue scoped 样式不会作用于动态插入的 DOM：

```vue
<style scoped>
.vjmapgis-popup { border: 1px solid red; }  /* 不生效 */
</style>
```

修法：

```vue
<style scoped>
::v-deep .vjmapgis-popup { border: 1px solid red; }
</style>
```

或用全局样式：

```vue
<style>
.vjmapgis-popup { border: 1px solid red; }
</style>
```

## 八、主题变量

某些场景下 vjmap UI 支持 CSS 变量切换主题：

```css
:root {
  --vj-primary: #2188ff;
  --vj-bg: #fff;
  --vj-text: #222;
}

[data-theme="dark"] {
  --vj-primary: #4fc3f7;
  --vj-bg: #1e1e1e;
  --vj-text: #ddd;
}
```

切换 `<html data-theme="dark">` 即可换色（UI 组件支持时有效）。

## 九、createUI 自定义 UI

vjmapext 的 `createUI` 方法生成命令行 / 工具栏 DOM，并把主题样式以 `<style data-mapcad-theme>` 注入容器：

```js
import * as vjmapext from 'vjmapext';

const mapcadLayer = new vjmapext.MapCadLayer();
map.addControl(mapcadLayer);
const ui = mapcadLayer.createUI({ theme: 'dark' });  // 'dark' | 'light'，生成命令栏等 DOM + 注入样式
// 运行期换肤：ui.setTheme('light') / ui.getTheme()
```

**`createUI` 返回 `ToolbarManager`**（不接收返回值就丢掉控制面）——程序化控制内置 UI：

```js
ui.showToolbar() / hideToolbar() / toggleToolbar() / isToolbarVisible()
ui.setToolbarPinned(pinned) / isToolbarCollapsed()
ui.showPropertyPanel() / hidePropertyPanel() / togglePropertyPanel()
ui.showCommandInput() / hideCommandInput() / setAutoShowCommandInput(auto)
ui.showDrawOptions() / hideDrawOptions()          // 绘图选项面板
ui.showAll() / ui.hideAll()
ui.setExportDwgCallback(cb)                        // 接管导出 DWG 完成回调（不再弹默认对话框）
```

`mapcadLayer.getUI()` 可取回上一次 `createUI()` 创建的同一实例。

如果 `createUI` 没被调用（或容器被重建后样式节点丢失）→ DOM 在但样式全无 → 看起来"UI 错乱"。重建 UI 时**先销毁旧实例**：`createUI()` 每次都 new 一个 `ToolbarManager` 挂上去，不会释放上一个（重复工具栏 + eventBus 上残留旧监听）：

```js
mapcadLayer.getUI()?.dispose();            // 摘 DOM + off 掉它挂的 eventBus 监听
mapcadLayer.createUI({ theme: 'dark' });
```

## 十、CDN vs npm 共存冲突

同一页同时 CDN 加 vjmap.min.css，npm 里又 import → 两份 CSS，后加载的胜出。一般无害，但注意版本一致。

## 十一、主题 CSS 重写顺序

```html
<link rel="stylesheet" href="https://vjmap.com/demo/js/vjmap/vjmap.min.css" />
<link rel="stylesheet" href="./my-theme.css" />       <!-- 后加载，可覆盖 -->
```

npm：

```js
import 'vjmap/dist/vjmap.min.css';
import './my-theme.css';
```

后加载的优先级高。

## 十二、第三方 UI 冲突

Ant Design / Element 的 `.ant-btn` 可能和 vjmap `.vjmapgis-ctrl` 样式冲突：

```css
.ant-btn { all: unset; ... }
```

这种全局 reset 会破坏 vjmap 控件。修法：

```css
.my-app .ant-btn { ... }           /* 限定作用域 */
```

或用 ID / 类作为"沙箱"。

## 十三、常见坑

1. **生产环境没打包 CSS**：Vite 把开发时 CSS import 进了 HMR 但未打进产物；检查 `dist/` 下有没有 css。
2. **CSS 404**：URL 错；浏览器没警告但样式全失。
3. **用了 `* { box-sizing: border-box; }` 全局 reset**：vjmap 某些布局受影响；用类限制作用域。
4. **iframe 里 CSS 没继承**：iframe 独立 DOM，需独立 import CSS。
5. **小程序 / WebView 环境**：CSS 路径需相对，检查打包产物。

## 相关

- 安装 → [setup/install](../../../vjmap/references/setup/install.md)
- 控件 → [interaction/controls](../../../vjmap/references/interaction/controls.md)
- Popup 样式 → [popup/styling](../../../vjmap/references/popup/styling.md)
