Styling of ::selection does not work in edit mode

Steps to reproduce

Add the following CSS as a snippet and activate that snippet:

.CodeMirror-line::selection,
.CodeMirror-line > span::selection,
.CodeMirror-line > span > span::selection,
::selection {
  background-color: red;
  color: white;
  text-decoration: underline;
}

.HyperMD-codeblock.CodeMirror-line::selection,
.HyperMD-codeblock.CodeMirror-line > span::selection,
.HyperMD-codeblock.CodeMirror-line > span > span::selection,
::selection {
  background-color: blue;
  color: white;
  text-decoration: underline;
}

Alternatively, add it to a theme’s CSS file and restart Obsidian.

Expected result

Text selection should be red with white text outside of code blocks and blue with white text inside code blocks.

Actual result

Text selection does not change (i.e. light blue for the “None” theme).

Environment

  • Operating system: macOS Big Sur
  • Obsidian version: v0.11.3

Do we maybe need a CodeMirror addon like this one?

I think the fact that ::selection is in both rules is throwing you off a little. You’re basically wiping out the first statement with the second (for the generic ‘selection’ anyhow).

Maybe someone can beat me to it, but a simple way (in the editor) to change the selection in code blocks is

code::selection {
  color: white;
  background-color: blue;
}

Anything not in code blocks is ‘highlighted’ as usual.

In preview there is an added class, so it’s a bit to tricky for me to delve into at the moment. IIRC the rule is that ::selection usually has to be on a parent element, and not a class.

Ow, sorry, that was a copy-paste error when I added this to a snippet from the theme I was tweaking. Same behavior when I use this:

.HyperMD-codeblock.CodeMirror-line::selection,
.HyperMD-codeblock.CodeMirror-line > span::selection,
.HyperMD-codeblock.CodeMirror-line > span > span::selection,
code::selection {
  background-color: blue;
  color: white;
  text-decoration: underline;
}

I totally forgot to test in preview mode (I don’t use that a lot), but there these rules do work. So it’s only in edit mode that they don’t

You’re right, I had preview/edit backwards. Sorry about that.
Class names are harder to target for ::selection.

I’ll keep digging, but someone more knowledgeable might have to help out.

CodeMirror doesn’t really select anything: it fakes it by creating a highlight in the background of the text. You can style that highlight shape, but you can’t use that to change the styling of the text, only the background layer underneath the text.

The latest version of CodeMirror (used on Obsidian mobile and eventually Obsidian desktop) does allow using the “real” selection (via content-editable), but even that only applies for single selection, not multiple selection. Multiple selection is still emulated via a background highlight layer even in CodeMirror 6.

tl;dr: target your CSS at CodeMirror’s background selection layer, not the ::selection, as CodeMirror doesn’t use the browser for text selection. (Well, it may do it in its invisible textarea, I suppose.)

2 Likes

this is pretty much like @pjeby said.

Thanks for that answer, it pointed me back to this answer on Stack Overflow, which now makes more sense to me. I now use this for edit mode (not with red of course):

.CodeMirror-selected {background:red !important;}

And as mentioned before, the other selectors do work for preview mode.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.