Expose sidebar widths through css variables

Use case or problem

currently, sidebars’ widths are only styled with inline styles. this makes it hard to try to match any other element’s width that are floating to the sidebars (namely the status bar). it would be great if the width of the sidebars was either mirrored to a (read-only) css variable, or applied with a css variable.

here’s me trying to make the status bar as long as the side ribbon:
image

obsidian 1.0.0 added a bunch of css variable that helped styling, and i think this addition would help a lot for theme devs.

Proposed solution

1. applying the widths through css variables (pseudo js, because i do not know the entire context of how dragging the resizer is handled)

const sidebarStyleTag = document.createElement("style")
// optionally add an id
document.head.appendChild(sidebarStyleTag )
const leftWidth = 280
const rightWidth = 280

function updateSidebarWidths(left, right) {
    sidebarStyleTag.innerHTML = `:root {
    --left-sidebar-width: ${left}px;
    --right-sidebar-width: ${right}px;
    }`
}

leftSideBar.ondrag = (event) => {
    leftWidth = event.newWidth //pseudocode
    updateSidebarWidths(leftWidth, rightWidth)
}
rightSideBar.ondrag = (event) => {
    rightWidth = event.newWidth //pseudocode
    updateSidebarWidths(leftWidth, rightWidth)
}
// + css code to apply the widths through the above defined css variables

2. mirroring the width to (read-only) css variable that can be referenced

const sidebarStyleTag = document.createElement("style")
// optionally add an id
document.head.appendChild(sidebarStyleTag )
const leftWidth = 280
const rightWidth = 280

function updateSidebarWidths(left, right) {
    sidebarStyleTag.innerHTML = `:root {
    --left-sidebar-width: ${left}px;
    --right-sidebar-width: ${right}px;
    }`
}

leftSideBar.ondrag = (event) => {
    event.target.style.width = event.newWidth
    leftWidth = event.newWidth //pseudocode
    updateSidebarWidths(leftWidth, rightWidth)
}
rightSideBar.ondrag = (event) => {
    event.target.style.width = event.newWidth
    rightWidth = event.newWidth //pseudocode
    updateSidebarWidths(leftWidth, rightWidth)
}
// in this scenario, no additional css code would be needed

in my opinion, 1. would be a more proper way to handle this.

Current workaround (optional)

lock the sidebar width or lock the status bar width/min-width (non ideal)

Related feature requests (optional)

(doesen’t apply)

3 Likes

I’m working on what I thought would be a simple CSS snippet that is related to this request. I think it would be great if there were read-only variables for the widths of all visible sections in the UI, not just the sidebar. Anything that sets style="--var-foo-width: X;" would alleviate a lot of CSS complexity for anyone working on style customization.

For example: I’m trying to make certain elements wider than the file line width (var(--file-line-width)), but no wider than the visible file content section of the UI (.view-content, or possibly .cm-sizer/.cm-contentContainer/.cm-content). In other words, I want to allow an element (<img>, <table>, …) to break out of the main file content container in the middle panel, but not overflow, similar to Minimal’s max/wide line width controls.

This turns out to be non-trivial. I can’t set width to something large than --file-line-width and then max-width to the width of the middle UI section, because there isn’t such a maximum I can easily use.

Without writing an extension to run JavaScript to expose the variables, my only option appears to be to follow the strategy that the Minimal theme follows: manually set .cm-sizer etc. to have a wider width, then manually constrain the inner elements as desired across different view modes. That’s pretty complicated!

I also don’t think I can reliably use something like 100vw, since there aren’t variables for every value I would need to subtract off.

1 Like

I ended up finding a pretty decent for my purposes. It might work for others (but also might break in future):

.cm-scroller {
  container-type: inline-size;
}

This lets you use container query length units like cqw. 100cqw in this case is the width of .cm-scroller.

For example, this will expand images in live preview to 1.25 times the available line width, as long as the file content pane is wider than that:

.is-readable-line-width .cm-scroller {
  container-type: inline-size;
}

.is-readable-line-width .cm-scroller img:not([width]) {
  /* 12px hardcoded scrollbar width for demonstration purposes */
  max-width: calc(100cqw - 12px);
  width: calc(1.25 * var(--file-line-width));
  transform: translateX(
    min(0px, calc(-0.5 * (100% - var(--file-line-width))))
  );
}

Obsidian might apply its own container within .cm-scroller, though, which means the approach would break.

You could also apply this pattern to .view-content and manually account for var(--file-margins).

1 Like