Editor font size change dynamically

Is this an appropriate way to change the font size of the editor dynamically? It seems to work just fine. But was just wondering if there was a more proper way:

function setFontSize(size) {
    editorView.dispatch({
    effects: document.querySelector(".cm-content").style.fontSize = size + 'pt',
    effects: document.querySelector(".cm-gutters").style.fontSize = size + 'pt',
    effects: document.querySelector(".cm-scroller").style.fontSize = size + 'pt',
    });
}

No, that doesn’t make much sense. effects should hold StateEffect objects, not strings. You’ll generally want to use extensions like EditorView.contentAttributes, or editor themes added/removed dynamically to do this kind of thing.

Ok, I think I figured out what you were talking about.

Does this look correct?

const fontSize = new Compartment();

const editorView = new CodeMirror.EditorView({
  doc: "",
  extensions: [
        // stuff 

        fontSize.of([]),

        // more stuff
  ],
  parent: document.body,
});

function setFontSize(size) {
    editorView.dispatch({
    effects: fontSize.reconfigure(
       EditorView.contentAttributes.of({ style: "font-size : " + size + "pt" }),
    )
    });
}

But I’ve found that it doesn’t also change the gutter size to match:

However, when I switch to using EditorView.editorAttributes.of() then it does change the size of the gutter to match, but it also changes the size of the Find & Replace view at the bottom of the editor. I don’t want the Find & Replace view to change size.

How do I change the editor content and gutter, while leaving the Find & Replace view at the default size?

Use a theme to target specific elements (.cm-content and .cm-gutters in this case) with your styles.

Unfortunately I haven’t figured out how to change the theme styles dynamically yet. Haven’t figured out that magic programmer incantation :slight_smile:

Ok, so I have some different code that’s sort of working. But it only changes the editor font size one time despite me passing in different font sizes.

Here’s what I have now:

const theme = new Compartment();

var baseTheme = EditorView.baseTheme({
    "&light": {
    backgroundColor: "white",
        "color-scheme": "light",
    },
    "&dark": {
        "color-scheme": "dark",
    },
});

const editorView = new CodeMirror.EditorView({
  doc: "",
  extensions: [
        // stuff 

        baseTheme,
        theme.of(oneDark),

        // more stuff
  ],
  parent: document.body,
});

function setFontSize(size) {

    baseTheme = EditorView.baseTheme({
        ".cm-content": {
            fontSize : size + "pt",
        },
        ".cm-gutters": {
            fontSize : size + "pt",
        },
    });
    
    editorView.dispatch({
        effects: theme.reconfigure(baseTheme)
    });
}

So I’m calling setFontSize() from a Mac app in Swift. CodeMirror is displayed in a WebKit view.

The font size does change. But only the first time I call it. Is there another way to refresh?

Or is the problem with me re-creating the baseTheme var? I haven’t figured out a way to just reference the baseTheme variable and update the .cm-content and .cm-gutters styles directly. So that’s why I create a new one.

Perhaps there’s a better way? Am I close?

baseThemes are expected to be stable. Use EditorView.theme instead.

So something like this? The problem with this now is I lose the ability to switch between light and dark themes now. I feel like this is overriding the theme and not just changing the font size.

function setFontSize(size) {

    let currentTheme = EditorView.theme({
        ".cm-content": {
            fontSize : size + "pt",
        },
        ".cm-gutters": {
            fontSize : size + "pt",
        },
    });
    
    editorView.dispatch({
        effects: theme.reconfigure(currentTheme)
    });
}

How does one target just the fontSize property of the theme’s cm-content and cm-gutters properties to modify them dynamically?

How does the font size affect the light/dark theming?

Oh, I was just sharing the same button in my test app so when I toggled light and dark mode, it would also toggle between two font sizes. It’s not my real app. Just a test bed. I’ll separate those functions now and see how it goes.

I guess there’s no way to directly modify properties of a theme dynamically without creating a whole new theme object like this then?

let currentTheme = EditorView.theme({
        ".cm-content": {
            fontSize : size + "pt",
        },
        ".cm-gutters": {
            fontSize : size + "pt",
        },
    });

Maybe I’m misunderstanding how TypeScript works (I’ve never used it before). But EditorView.theme({}) looks like a constructor to me. Maybe the properties get merged with the Editor’s theme in the call to theme.reconfigure()? Not sure how it’s all glued together.

Multiple themes can be active in an editor at once, yes.

So I’m calling setFontSize() from a Mac app in Swift. CodeMirror is displayed in a WebKit view

Interesting! I just open sourced a Swift macOS Markdown app, maybe you can take a look: GitHub - MarkEdit-app/MarkEdit: Just like TextEdit on Mac but dedicated to Markdown.

It uses various of techniques to do the styling, including EditorTheme (with Compartments) and vanilla CSS, it features dynamic font sizing (including bigger font size for section headers) and theming.

Not trying to say mine was the best practice, just wanted to give you a sense since I also use WebKit.

Thanks for your reply! MarkEdit is a really great app!

I actually did find your project a week ago or so. Thanks! I’ve been trying to make sense of how you’re doing things like font size adjustments and using a more native Find & Replace UI. I would love to chat with you more about it. I can be reached at brendan at tapzapp dot com if you’re willing to answer a few questions I have about it offline.

It’s very well put together! I’m the developer of a Mac and iOS app called Tap Forms Organizer and I have a scripting engine built-in to it and I was just replacing the current editor I made with Code Mirror 6. I used this project as a start actually:

https://github.com/khoi/codemirror-swift

Using Code Mirror 6, I was able to simply change the font size by changing the parent style with { font-size: 130% }. As well as changing light/dark themes.

I’m using React + MUI so my setup looks like this

<Box sx={{ height: props.height, overflow:'auto', fontSize: props.fontSize || 14 }}>
  <div ref={refContainer}></div>
</Box>

You can see it working here:

Thanks for your response @hepp. I did manage to get a font size slider to work, however, you have the same issue that I have. If you display the Find & Replace panel at the bottom of the editor, when you change the font size, it also changes the font size of that panel at the bottom. But for now I’m just going to live with it. I want to implement a more Mac-native find and replace system anyway. Similar to how the MarkEdit program from @GnohzGniy does it.