Editor type scales for real: drop prosekit typography.css, fix selectors
Deploy / deploy (push) Successful in 1m16s

The earlier rem override never matched: editor.mount() turns the
.prosekit-editor div itself into the .ProseMirror root, so
'.prosekit-editor .ProseMirror p' selected nothing and prosekit
typography.css's fixed 16px kept winning. Verified by mounting the
editor standalone and reading the mount div's classes.

Rather than out-specificity a stylesheet we don't control, stop
loading it: prosekit's typography.css is optional px-based sugar. Our
own rem scale (now selected as direct children of .prosekit-editor)
plus UA em defaults for lists/blockquote/code is the whole editor
typography, all tracking the responsive root.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bendik Aagaard Lynghaug
2026-08-14 23:16:16 +02:00
co-authored by Claude Fable 5
parent 7b5d4dbf52
commit 5b3ffa62e8
2 changed files with 22 additions and 15 deletions
+4 -1
View File
@@ -285,8 +285,11 @@ function buildToolbar(editor) {
}
export function mountEditor(container, hiddenInput, initial) {
// Only the structural stylesheet (placeholder, lists, gap cursor).
// Deliberately NOT prosekit/basic/typography.css: it sizes content in
// fixed px, which fights the app's responsive root font-size. All
// editor typography lives in our own stylesheet, in rem.
ensureStylesheet('https://esm.sh/prosekit/basic/style.css')
ensureStylesheet('https://esm.sh/prosekit/basic/typography.css')
const extension = union(
defineBasicExtension(),
+17 -13
View File
@@ -450,6 +450,7 @@ textarea:focus {
placeholder pseudo-element, which read far dimmer than the
native inputs next to it. */
::placeholder,
.prosekit-editor .prosekit-placeholder::before,
.prosekit-editor.prosekit-placeholder::before {
color: var(--ink-dim);
opacity: 1;
@@ -508,57 +509,60 @@ textarea:focus {
box-shadow: 0 0 0 0.18rem var(--accent-soft);
}
/* ProseKit's typography.css (loaded from esm.sh at mount time) sets
fixed px font sizes on .ProseMirror, so they ignore the responsive
root font-size. Re-state them in rem/em at the same proportions,
with .prosekit-editor prefixed so these win on specificity. */
.prosekit-editor .ProseMirror p {
/* The editor's whole type scale, in rem. ProseKit's own typography.css
is deliberately not loaded (it sizes content in fixed px - see
mountEditor in prosekit-editor.js), so these rules are the only
typography the editor gets, on top of UA defaults (em-based, they
scale fine for lists/blockquote/code). NOTE: editor.mount() turns the
.prosekit-editor div itself into the .ProseMirror root, so content
elements are its direct children - no .ProseMirror in the selector. */
.prosekit-editor p {
font-size: 1rem;
line-height: 1.5;
margin: 0 0 0.6em;
}
.prosekit-editor .ProseMirror p:last-child {
.prosekit-editor p:last-child {
margin-bottom: 0;
}
.prosekit-editor .ProseMirror h1 {
.prosekit-editor h1 {
font-size: 2.5rem;
line-height: 1.1;
margin: 0.9em 0 0.1em;
}
.prosekit-editor .ProseMirror h2 {
.prosekit-editor h2 {
font-size: 1.875rem;
line-height: 1.3;
margin: 1.05em 0 0.13em;
}
.prosekit-editor .ProseMirror h3 {
.prosekit-editor h3 {
font-size: 1.5rem;
line-height: 1.33;
margin: 0.9em 0 0.04em;
}
.prosekit-editor .ProseMirror h4 {
.prosekit-editor h4 {
font-size: 1.25rem;
line-height: 1.3;
margin: 0.8em 0 0.05em;
}
.prosekit-editor .ProseMirror h5 {
.prosekit-editor h5 {
font-size: 1.125rem;
line-height: 1.22;
margin: 0.78em 0 0.06em;
}
.prosekit-editor .ProseMirror h6 {
.prosekit-editor h6 {
font-size: 1rem;
line-height: 1.25;
margin: 0.75em 0 0.06em;
}
.prosekit-editor .ProseMirror :is(h1, h2, h3, h4, h5, h6):first-child {
.prosekit-editor :is(h1, h2, h3, h4, h5, h6):first-child {
margin-top: 0;
}