-
-
Notifications
You must be signed in to change notification settings - Fork 4
CSS and JavaScript
Each Custom View can have scoped CSS and optional JavaScript. Keep HTML declarative, CSS responsible for layout, and JavaScript only for behavior that cannot be expressed in the template itself.
The CSS field is the best place for view styles. Use normal CSS and Obsidian CSS variables.
.album-view {
color: var(--text-normal);
background: var(--background-primary);
}
.album-view a {
color: var(--link-color);
}Prefer Obsidian variables where possible:
| Variable | Common use |
|---|---|
--background-primary |
Main background. |
--background-secondary |
Secondary panels. |
--text-normal |
Body text. |
--text-muted |
Supporting text. |
--text-faint |
Dividers and faint labels. |
--interactive-accent |
Accent color. |
--background-modifier-border |
Borders. |
The JavaScript field runs after the template is rendered, if Allow JavaScript execution is enabled.
Inside view JavaScript, this is the rendered custom-view container.
const container = this;
const button = container.querySelector("button");
button?.addEventListener("click", () => {
container.classList.toggle("is-expanded");
});Always scope DOM queries to this, not document, unless you intentionally need something global.
Inline <script> tags in templates can also run, but the JavaScript field is easier to maintain. Prefer the JavaScript field for larger behavior.
JavaScript can call network APIs, inspect rendered note data, and mutate the page. Only enable and paste scripts you trust.
For API keys:
- Prefer placeholders in shared templates.
- Do not publish personal keys in screenshots, gists, issues, or wiki pages.
- Keep third-party requests clear to the user.
The Movies and Albums examples sample colors from cover/backdrop images. Canvas sampling can fail if the image is cross-origin and does not allow it. Always provide a fallback palette.
Pattern:
const img = container.querySelector(".album-cover");
function applyFallbackPalette() {
container.style.setProperty("--background-primary", "#100f0f");
}
if (img?.complete && img.naturalWidth > 0) {
// sample image here
} else {
img?.addEventListener("load", () => {
// sample image here
});
img?.addEventListener("error", applyFallbackPalette);
}- Keep JavaScript idempotent; it may run again when switching files.
- Avoid repeated global
document.querySelectorAllscans. - Avoid long synchronous loops over the whole vault.
- Use Bases for related-file querying instead of custom JavaScript vault scans.
- If you fetch remote data, show a small fallback state and cache where appropriate.