When building the string-strip-html GUI, I wanted: line wrapping, full-screen flexbox layout, with scrollbars on Codemirror box only. That’s a common layout seen on code-oriented sites like Codepen or Stackblitz. I created a minimal proof-of-concept sandbox to prove it works.
For simplicity, we’ll be using @uiw/react-codemirror, raw React and pure CSS:
Let me explain the non-trivial parts of this layout.
Outer layout
We have to ensure that every container, including <html> and <body>, expands to the 100% of the viewport height with the help of CSS vh unit:
html,
body,
#root,
.playground-container {
padding: 0;
margin: 0;
height: 100vh; /* <--- */
background-color: #efefef;
}
The CSS vh unit is supported on all browser versions dated newer than 2013.
Max height via CSS Flexbox
“To let the editor grow until it reaches a maximum height, and scroll from that point on, use
max-heightinstead of height in a setup like the one above.”
In CSS Flexbox layout, there’s no max-height, the container div, which holds the Codemirror instance, expands with the help of CSS style flex: 1.
I could only achieve it via flexbox and setting .cm-scroller to be absolutely positioned and glue its edges to the parent .cm-editor container:
.cm-editor {
/* our container wrapper for Codemirror instance */
flex: 1; /* expand to the maximum */
height: 100%;
position: relative; /* needed for child component .cm-scroller */
}
.cm-scroller {
position: absolute !important;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow-y: auto;
}
It took me a couple of hours to discover this setup. The absolute positioning seems to be the only way to impose scrollbars on Codemirror boxes when its height is unknown and set by CSS Flexbox.
Dark-light themes
If you’re happy with Codemirror default themes, just set the prop theme on the <CodeMirror/> component. Below, we’re using remix-themes so theme comes from let [theme] = useTheme();:
import CodeMirror from "@uiw/react-codemirror";
import { html } from "@codemirror/lang-html";
import { EditorView } from "@codemirror/view";
...
<CodeMirror
className="cm-outer-container"
value={inputStr}
extensions={[html(), EditorView.lineWrapping]}
onChange={onChange}
theme={theme || "dark"}
/>
Line wrapping
“To enable line wrapping, add the
EditorView.lineWrappingextension to your configuration.”—https://codemirror.net/examples/styling/#overflow-and-scrolling
Another challenge is setting up this EditorView.lineWrapping extension. There are no code examples on the Coremirror docs site showing how to import it and where to place it. For an answer, see the example in the previous section above.
To cause lines to wrap, I chose belt-and-braces: to use EditorView.lineWrapping (extensions prop) and to apply CSS directly onto Codemirror elements, as hinted by the documentation (“wrapping can be unreliable if you don’t also set overflow-wrap: anywhere”). By the way, that’s what CSS Codepen uses:
.cm-content {
white-space: pre-wrap;
word-break: normal;
word-wrap: break-word;
}
Takeaway
Feel free to fork the sandbox and use that layout in your code-processing apps.
Sources
- @uiw
react-codemirrornpm page https://www.npmjs.com/package/@uiw/react-codemirror - @uiw
react-codemirrorGitHub page https://github.com/uiwjs/react-codemirror codemirrornpm page https://www.npmjs.com/package/codemirrorcodemirrrorv6 documentation https://codemirror.net/docs/
