Style guide
How Blockleaf is styled, what you are expected to override, and why installing an editor does not change how you write CSS.
Blockleaf ships one stylesheet. It is plain CSS, it is driven by --bl-*
custom properties, and it has no build step, no prose class and no
framework underneath it.
import '@blockleaf/editor/styles.css';That is a product promise rather than a preference. Installing a text editor should not decide how the rest of your application is styled, so nothing here requires Tailwind, and nothing here fights it either.
The two wrappers
Every rule is scoped to one of two classes, and both the editor and the renderer produce the same pair:
<div class="blockleaf-editor">
<div class="blockleaf-editor__content">
<!-- blocks -->
</div>
</div>.blockleaf-editordeclares the custom properties, the background and the base type. It is also the positioning context the drag handle is measured against..blockleaf-editor__contentis what every prose rule is scoped to —h1,ul,blockquote,tableand the rest.
The editor component writes both for you. When you render a stored document
with RenderDocument or renderToHTML you write them yourself. One without
the other gets you the colours with no typography, or the typography with no
colours.
Three levels of change
Pick the shallowest one that does the job.
1. Custom properties
Most themes are a handful of declarations:
.blockleaf-editor {
--bl-color-accent: #3b82f6;
--bl-color-bg: #fbfbfd;
--bl-font-body: 'Inter', system-ui, sans-serif;
--bl-radius: 10px;
}Fifty-seven properties cover the content surface, the slash menu, the bubble menu, the block menu, the drag handle and the table menu. The full list is in theming.
2. Class selectors
Class names are stable and BEM-flavoured, so your own stylesheet can target them directly:
.blockleaf-editor__content blockquote {
border-inline-start-width: 4px;
font-style: normal;
}A single class is specificity 0,1,0 and the scoped prose rules are 0,1,1,
so .blockleaf-editor__content blockquote in your own sheet, loaded after
ours, wins on order. No !important is needed anywhere, and the package
contains none.
3. Replace the component
The chrome is a set of React components, and every one of them is replaceable without touching CSS at all. See the chrome.
Scoping to one editor
className is appended to .blockleaf-editor, so one instance can be
themed without touching the others:
<BlockleafEditor className="comment-box" />.blockleaf-editor.comment-box {
--bl-font-size: 0.9375rem;
--bl-content-padding: 0.75rem;
}Dark mode
The stylesheet follows prefers-color-scheme out of the box, and
data-theme="dark" or data-theme="light" on .blockleaf-editor overrides
it. The mechanics, and the one place it does not reach yet, are in
theming.
With a framework
Blockleaf has no opinion, but the two questions that come up are always the same:
- With Tailwind — mapping your theme tokens onto
--bl-*, and why Preflight does not fight the stylesheet. - With shadcn/ui — one block of CSS that makes the editor read from the same variables your buttons do.