25 CSS Blockquotes21 / 25
IDE Code Comment Style Blockquote CSS
A quote typeset as a JSDoc block comment inside a believable editor pane — line numbers generated by CSS counters (zero markup, renumbers itself when you edit), syntax tinting via a handful of token spans, a title bar with traffic lights, an active-line highlight, and a blinking caret. For developer blogs and changelogs, quoting a maxim as a docblock is native dress — and the counters technique is the actually-reusable part, the same trick that numbers real code blocks without a highlight library.
Published Updated
The code
<section class="bq-21" aria-label="IDE code comment style blockquote demo">
<div class="bq-21__stage">
<figure class="bq-21__editor">
<div class="bq-21__bar">
<span class="bq-21__dots" aria-hidden="true"><i></i><i></i><i></i></span>
<p class="bq-21__file">principles.ts — engineering-handbook</p>
<span class="bq-21__lang" aria-hidden="true">TypeScript</span>
</div>
<blockquote class="bq-21__quote">
<code>
<span class="bq-21__line"><span class="bq-21__cmt">/**</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * Every sufficiently senior engineer eventually</span></span>
<span class="bq-21__line bq-21__line--active"><span class="bq-21__cmt"> * rewrites the same sentence:</span> <span class="bq-21__str">"make it work,"</span></span>
<span class="bq-21__line"><span class="bq-21__str"> * "make it right, make it fast"</span> <span class="bq-21__cmt">— in that order,</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * and never all in the same pull request.</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> *</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * </span><span class="bq-21__tag">@author</span><span class="bq-21__cmt"> Kent Beck (paraphrasing generations)</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * </span><span class="bq-21__tag">@since</span><span class="bq-21__cmt"> forever</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> */</span><span class="bq-21__caret" aria-hidden="true"></span></span>
</code>
</blockquote>
<figcaption class="bq-21__status"><span>UTF-8</span><span>Ln 9, Col 4</span><span>Spaces: 2</span></figcaption>
</figure>
<p class="bq-21__chip" aria-hidden="true">counter(line) gutter · user-select:none · steps(1) caret</p>
</div>
</section><section class="bq-21" aria-label="IDE code comment style blockquote demo">
<div class="bq-21__stage">
<figure class="bq-21__editor">
<div class="bq-21__bar">
<span class="bq-21__dots" aria-hidden="true"><i></i><i></i><i></i></span>
<p class="bq-21__file">principles.ts — engineering-handbook</p>
<span class="bq-21__lang" aria-hidden="true">TypeScript</span>
</div>
<blockquote class="bq-21__quote">
<code>
<span class="bq-21__line"><span class="bq-21__cmt">/**</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * Every sufficiently senior engineer eventually</span></span>
<span class="bq-21__line bq-21__line--active"><span class="bq-21__cmt"> * rewrites the same sentence:</span> <span class="bq-21__str">"make it work,"</span></span>
<span class="bq-21__line"><span class="bq-21__str"> * "make it right, make it fast"</span> <span class="bq-21__cmt">— in that order,</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * and never all in the same pull request.</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> *</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * </span><span class="bq-21__tag">@author</span><span class="bq-21__cmt"> Kent Beck (paraphrasing generations)</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * </span><span class="bq-21__tag">@since</span><span class="bq-21__cmt"> forever</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> */</span><span class="bq-21__caret" aria-hidden="true"></span></span>
</code>
</blockquote>
<figcaption class="bq-21__status"><span>UTF-8</span><span>Ln 9, Col 4</span><span>Spaces: 2</span></figcaption>
</figure>
<p class="bq-21__chip" aria-hidden="true">counter(line) gutter · user-select:none · steps(1) caret</p>
</div>
</section>.bq-21,
.bq-21 *,
.bq-21 *::before,
.bq-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.bq-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
--bg: oklch(0.17 0.012 270);
--pane: oklch(0.21 0.014 270);
--bar: oklch(0.25 0.016 270);
--ink: oklch(0.9 0.01 260);
--lineno: oklch(0.48 0.015 265);
--cmt: oklch(0.68 0.06 150);
--tag: oklch(0.72 0.12 300);
--str: oklch(0.78 0.12 75);
--sel: oklch(0.3 0.03 265);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
}
.bq-21__stage {
width: 100%;
height: 100vh;
height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: 24px;
padding: clamp(20px,5vw,56px);
background: radial-gradient(80% 60% at 50% -10%,oklch(0.22 0.03 280/.6),transparent),var(--bg);
overflow-y: auto;
}
.bq-21__editor {
width: min(100%,620px);
border-radius: 14px;
overflow: hidden;
background: var(--pane);
border: 1px solid oklch(1 0 0/.09);
box-shadow: 0 26px 60px oklch(0 0 0/.5);
}
.bq-21__bar {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
background: var(--bar);
border-bottom: 1px solid oklch(0 0 0/.25);
}
.bq-21__dots {
display: flex;
gap: 7px;
}
.bq-21__dots i {
width: 11px;
height: 11px;
border-radius: 99px;
}
.bq-21__dots i:nth-child(1) {
background: oklch(0.65 0.18 25);
}
.bq-21__dots i:nth-child(2) {
background: oklch(0.8 0.15 90);
}
.bq-21__dots i:nth-child(3) {
background: oklch(0.72 0.17 145);
}
.bq-21__file {
font-size: 12px;
color: oklch(0.72 0.015 265);
margin-inline: auto;
}
.bq-21__lang {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--lineno);
}
.bq-21__quote {
padding: 16px 0 14px;
}
.bq-21__quote code {
display: block;
font-family: ui-monospace,Menlo,Consolas,'Cascadia Code',monospace;
font-size: 13.5px;
line-height: 1.7;
counter-reset: bq21-line;
}
.bq-21__line {
display: block;
padding-right: 16px;
counter-increment: bq21-line;
}
.bq-21__line::before {
content: counter(bq21-line);
display: inline-block;
width: 3.4ch;
margin-right: 1.8ch;
text-align: right;
color: var(--lineno);
user-select: none;
-webkit-user-select: none;
}
.bq-21__line--active {
background: var(--sel);
}
.bq-21__line--active::before {
color: var(--ink);
}
.bq-21__cmt {
color: var(--cmt);
}
.bq-21__tag {
color: var(--tag);
font-weight: 600;
}
.bq-21__str {
color: var(--str);
}
.bq-21__caret {
display: inline-block;
width: 2px;
height: 1.1em;
background: var(--ink);
vertical-align: -.18em;
margin-left: 2px;
animation: bq21-blink 1.1s steps(1,end) infinite;
}
@keyframes bq21-blink {
0%,
49% {
opacity: 1;
}
50%,
100% {
opacity: 0;
}
}
.bq-21__status {
display: flex;
gap: 18px;
justify-content: flex-end;
padding: 8px 14px;
background: var(--bar);
border-top: 1px solid oklch(0 0 0/.25);
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--lineno);
}
.bq-21__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: oklch(0.6 0.02 265);
padding: 7px 13px;
border: 1px solid oklch(1 0 0/.12);
border-radius: 99px;
}
@media (prefers-reduced-motion: reduce) {
.bq-21 * {
transition-duration: .01ms !important;
}
.bq-21__caret {
animation: none;
}
}.bq-21,
.bq-21 *,
.bq-21 *::before,
.bq-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.bq-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
--bg: oklch(0.17 0.012 270);
--pane: oklch(0.21 0.014 270);
--bar: oklch(0.25 0.016 270);
--ink: oklch(0.9 0.01 260);
--lineno: oklch(0.48 0.015 265);
--cmt: oklch(0.68 0.06 150);
--tag: oklch(0.72 0.12 300);
--str: oklch(0.78 0.12 75);
--sel: oklch(0.3 0.03 265);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
}
.bq-21__stage {
width: 100%;
height: 100vh;
height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: 24px;
padding: clamp(20px,5vw,56px);
background: radial-gradient(80% 60% at 50% -10%,oklch(0.22 0.03 280/.6),transparent),var(--bg);
overflow-y: auto;
}
.bq-21__editor {
width: min(100%,620px);
border-radius: 14px;
overflow: hidden;
background: var(--pane);
border: 1px solid oklch(1 0 0/.09);
box-shadow: 0 26px 60px oklch(0 0 0/.5);
}
.bq-21__bar {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
background: var(--bar);
border-bottom: 1px solid oklch(0 0 0/.25);
}
.bq-21__dots {
display: flex;
gap: 7px;
}
.bq-21__dots i {
width: 11px;
height: 11px;
border-radius: 99px;
}
.bq-21__dots i:nth-child(1) {
background: oklch(0.65 0.18 25);
}
.bq-21__dots i:nth-child(2) {
background: oklch(0.8 0.15 90);
}
.bq-21__dots i:nth-child(3) {
background: oklch(0.72 0.17 145);
}
.bq-21__file {
font-size: 12px;
color: oklch(0.72 0.015 265);
margin-inline: auto;
}
.bq-21__lang {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--lineno);
}
.bq-21__quote {
padding: 16px 0 14px;
}
.bq-21__quote code {
display: block;
font-family: ui-monospace,Menlo,Consolas,'Cascadia Code',monospace;
font-size: 13.5px;
line-height: 1.7;
counter-reset: bq21-line;
}
.bq-21__line {
display: block;
padding-right: 16px;
counter-increment: bq21-line;
}
.bq-21__line::before {
content: counter(bq21-line);
display: inline-block;
width: 3.4ch;
margin-right: 1.8ch;
text-align: right;
color: var(--lineno);
user-select: none;
-webkit-user-select: none;
}
.bq-21__line--active {
background: var(--sel);
}
.bq-21__line--active::before {
color: var(--ink);
}
.bq-21__cmt {
color: var(--cmt);
}
.bq-21__tag {
color: var(--tag);
font-weight: 600;
}
.bq-21__str {
color: var(--str);
}
.bq-21__caret {
display: inline-block;
width: 2px;
height: 1.1em;
background: var(--ink);
vertical-align: -.18em;
margin-left: 2px;
animation: bq21-blink 1.1s steps(1,end) infinite;
}
@keyframes bq21-blink {
0%,
49% {
opacity: 1;
}
50%,
100% {
opacity: 0;
}
}
.bq-21__status {
display: flex;
gap: 18px;
justify-content: flex-end;
padding: 8px 14px;
background: var(--bar);
border-top: 1px solid oklch(0 0 0/.25);
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--lineno);
}
.bq-21__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: oklch(0.6 0.02 265);
padding: 7px 13px;
border: 1px solid oklch(1 0 0/.12);
border-radius: 99px;
}
@media (prefers-reduced-motion: reduce) {
.bq-21 * {
transition-duration: .01ms !important;
}
.bq-21__caret {
animation: none;
}
}Here's a working CSS Blockquote from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: IDE Code Comment Style Blockquote CSS
Source: https://codefronts.com/snippets/css-blockquotes/code-comment/
A quote typeset as a JSDoc block comment inside a believable editor pane — line numbers generated by CSS counters (zero markup, renumbers itself when you edit), syntax tinting via a handful of token spans, a title bar with traffic lights, an active-line highlight, and a blinking caret. For developer blogs and changelogs, quoting a maxim as a docblock is native dress — and the counters technique is the actually-reusable part, the same trick that numbers real code blocks without a highlight library.
## HTML
```html
<section class="bq-21" aria-label="IDE code comment style blockquote demo">
<div class="bq-21__stage">
<figure class="bq-21__editor">
<div class="bq-21__bar">
<span class="bq-21__dots" aria-hidden="true"><i></i><i></i><i></i></span>
<p class="bq-21__file">principles.ts — engineering-handbook</p>
<span class="bq-21__lang" aria-hidden="true">TypeScript</span>
</div>
<blockquote class="bq-21__quote">
<code>
<span class="bq-21__line"><span class="bq-21__cmt">/**</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * Every sufficiently senior engineer eventually</span></span>
<span class="bq-21__line bq-21__line--active"><span class="bq-21__cmt"> * rewrites the same sentence:</span> <span class="bq-21__str">"make it work,"</span></span>
<span class="bq-21__line"><span class="bq-21__str"> * "make it right, make it fast"</span> <span class="bq-21__cmt">— in that order,</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * and never all in the same pull request.</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> *</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * </span><span class="bq-21__tag">@author</span><span class="bq-21__cmt"> Kent Beck (paraphrasing generations)</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * </span><span class="bq-21__tag">@since</span><span class="bq-21__cmt"> forever</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> */</span><span class="bq-21__caret" aria-hidden="true"></span></span>
</code>
</blockquote>
<figcaption class="bq-21__status"><span>UTF-8</span><span>Ln 9, Col 4</span><span>Spaces: 2</span></figcaption>
</figure>
<p class="bq-21__chip" aria-hidden="true">counter(line) gutter · user-select:none · steps(1) caret</p>
</div>
</section>
```
## CSS
```css
.bq-21,
.bq-21 *,
.bq-21 *::before,
.bq-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.bq-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
--bg: oklch(0.17 0.012 270);
--pane: oklch(0.21 0.014 270);
--bar: oklch(0.25 0.016 270);
--ink: oklch(0.9 0.01 260);
--lineno: oklch(0.48 0.015 265);
--cmt: oklch(0.68 0.06 150);
--tag: oklch(0.72 0.12 300);
--str: oklch(0.78 0.12 75);
--sel: oklch(0.3 0.03 265);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
}
.bq-21__stage {
width: 100%;
height: 100vh;
height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: 24px;
padding: clamp(20px,5vw,56px);
background: radial-gradient(80% 60% at 50% -10%,oklch(0.22 0.03 280/.6),transparent),var(--bg);
overflow-y: auto;
}
.bq-21__editor {
width: min(100%,620px);
border-radius: 14px;
overflow: hidden;
background: var(--pane);
border: 1px solid oklch(1 0 0/.09);
box-shadow: 0 26px 60px oklch(0 0 0/.5);
}
.bq-21__bar {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
background: var(--bar);
border-bottom: 1px solid oklch(0 0 0/.25);
}
.bq-21__dots {
display: flex;
gap: 7px;
}
.bq-21__dots i {
width: 11px;
height: 11px;
border-radius: 99px;
}
.bq-21__dots i:nth-child(1) {
background: oklch(0.65 0.18 25);
}
.bq-21__dots i:nth-child(2) {
background: oklch(0.8 0.15 90);
}
.bq-21__dots i:nth-child(3) {
background: oklch(0.72 0.17 145);
}
.bq-21__file {
font-size: 12px;
color: oklch(0.72 0.015 265);
margin-inline: auto;
}
.bq-21__lang {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--lineno);
}
.bq-21__quote {
padding: 16px 0 14px;
}
.bq-21__quote code {
display: block;
font-family: ui-monospace,Menlo,Consolas,'Cascadia Code',monospace;
font-size: 13.5px;
line-height: 1.7;
counter-reset: bq21-line;
}
.bq-21__line {
display: block;
padding-right: 16px;
counter-increment: bq21-line;
}
.bq-21__line::before {
content: counter(bq21-line);
display: inline-block;
width: 3.4ch;
margin-right: 1.8ch;
text-align: right;
color: var(--lineno);
user-select: none;
-webkit-user-select: none;
}
.bq-21__line--active {
background: var(--sel);
}
.bq-21__line--active::before {
color: var(--ink);
}
.bq-21__cmt {
color: var(--cmt);
}
.bq-21__tag {
color: var(--tag);
font-weight: 600;
}
.bq-21__str {
color: var(--str);
}
.bq-21__caret {
display: inline-block;
width: 2px;
height: 1.1em;
background: var(--ink);
vertical-align: -.18em;
margin-left: 2px;
animation: bq21-blink 1.1s steps(1,end) infinite;
}
@keyframes bq21-blink {
0%,
49% {
opacity: 1;
}
50%,
100% {
opacity: 0;
}
}
.bq-21__status {
display: flex;
gap: 18px;
justify-content: flex-end;
padding: 8px 14px;
background: var(--bar);
border-top: 1px solid oklch(0 0 0/.25);
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--lineno);
}
.bq-21__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: oklch(0.6 0.02 265);
padding: 7px 13px;
border: 1px solid oklch(1 0 0/.12);
border-radius: 99px;
}
@media (prefers-reduced-motion: reduce) {
.bq-21 * {
transition-duration: .01ms !important;
}
.bq-21__caret {
animation: none;
}
}
```Here's a working CSS Blockquote from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: IDE Code Comment Style Blockquote CSS
Source: https://codefronts.com/snippets/css-blockquotes/code-comment/
A quote typeset as a JSDoc block comment inside a believable editor pane — line numbers generated by CSS counters (zero markup, renumbers itself when you edit), syntax tinting via a handful of token spans, a title bar with traffic lights, an active-line highlight, and a blinking caret. For developer blogs and changelogs, quoting a maxim as a docblock is native dress — and the counters technique is the actually-reusable part, the same trick that numbers real code blocks without a highlight library.
## HTML
```html
<section class="bq-21" aria-label="IDE code comment style blockquote demo">
<div class="bq-21__stage">
<figure class="bq-21__editor">
<div class="bq-21__bar">
<span class="bq-21__dots" aria-hidden="true"><i></i><i></i><i></i></span>
<p class="bq-21__file">principles.ts — engineering-handbook</p>
<span class="bq-21__lang" aria-hidden="true">TypeScript</span>
</div>
<blockquote class="bq-21__quote">
<code>
<span class="bq-21__line"><span class="bq-21__cmt">/**</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * Every sufficiently senior engineer eventually</span></span>
<span class="bq-21__line bq-21__line--active"><span class="bq-21__cmt"> * rewrites the same sentence:</span> <span class="bq-21__str">"make it work,"</span></span>
<span class="bq-21__line"><span class="bq-21__str"> * "make it right, make it fast"</span> <span class="bq-21__cmt">— in that order,</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * and never all in the same pull request.</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> *</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * </span><span class="bq-21__tag">@author</span><span class="bq-21__cmt"> Kent Beck (paraphrasing generations)</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> * </span><span class="bq-21__tag">@since</span><span class="bq-21__cmt"> forever</span></span>
<span class="bq-21__line"><span class="bq-21__cmt"> */</span><span class="bq-21__caret" aria-hidden="true"></span></span>
</code>
</blockquote>
<figcaption class="bq-21__status"><span>UTF-8</span><span>Ln 9, Col 4</span><span>Spaces: 2</span></figcaption>
</figure>
<p class="bq-21__chip" aria-hidden="true">counter(line) gutter · user-select:none · steps(1) caret</p>
</div>
</section>
```
## CSS
```css
.bq-21,
.bq-21 *,
.bq-21 *::before,
.bq-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.bq-21 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
--bg: oklch(0.17 0.012 270);
--pane: oklch(0.21 0.014 270);
--bar: oklch(0.25 0.016 270);
--ink: oklch(0.9 0.01 260);
--lineno: oklch(0.48 0.015 265);
--cmt: oklch(0.68 0.06 150);
--tag: oklch(0.72 0.12 300);
--str: oklch(0.78 0.12 75);
--sel: oklch(0.3 0.03 265);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
}
.bq-21__stage {
width: 100%;
height: 100vh;
height: 100svh;
display: grid;
place-items: center;
align-content: center;
gap: 24px;
padding: clamp(20px,5vw,56px);
background: radial-gradient(80% 60% at 50% -10%,oklch(0.22 0.03 280/.6),transparent),var(--bg);
overflow-y: auto;
}
.bq-21__editor {
width: min(100%,620px);
border-radius: 14px;
overflow: hidden;
background: var(--pane);
border: 1px solid oklch(1 0 0/.09);
box-shadow: 0 26px 60px oklch(0 0 0/.5);
}
.bq-21__bar {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
background: var(--bar);
border-bottom: 1px solid oklch(0 0 0/.25);
}
.bq-21__dots {
display: flex;
gap: 7px;
}
.bq-21__dots i {
width: 11px;
height: 11px;
border-radius: 99px;
}
.bq-21__dots i:nth-child(1) {
background: oklch(0.65 0.18 25);
}
.bq-21__dots i:nth-child(2) {
background: oklch(0.8 0.15 90);
}
.bq-21__dots i:nth-child(3) {
background: oklch(0.72 0.17 145);
}
.bq-21__file {
font-size: 12px;
color: oklch(0.72 0.015 265);
margin-inline: auto;
}
.bq-21__lang {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--lineno);
}
.bq-21__quote {
padding: 16px 0 14px;
}
.bq-21__quote code {
display: block;
font-family: ui-monospace,Menlo,Consolas,'Cascadia Code',monospace;
font-size: 13.5px;
line-height: 1.7;
counter-reset: bq21-line;
}
.bq-21__line {
display: block;
padding-right: 16px;
counter-increment: bq21-line;
}
.bq-21__line::before {
content: counter(bq21-line);
display: inline-block;
width: 3.4ch;
margin-right: 1.8ch;
text-align: right;
color: var(--lineno);
user-select: none;
-webkit-user-select: none;
}
.bq-21__line--active {
background: var(--sel);
}
.bq-21__line--active::before {
color: var(--ink);
}
.bq-21__cmt {
color: var(--cmt);
}
.bq-21__tag {
color: var(--tag);
font-weight: 600;
}
.bq-21__str {
color: var(--str);
}
.bq-21__caret {
display: inline-block;
width: 2px;
height: 1.1em;
background: var(--ink);
vertical-align: -.18em;
margin-left: 2px;
animation: bq21-blink 1.1s steps(1,end) infinite;
}
@keyframes bq21-blink {
0%,
49% {
opacity: 1;
}
50%,
100% {
opacity: 0;
}
}
.bq-21__status {
display: flex;
gap: 18px;
justify-content: flex-end;
padding: 8px 14px;
background: var(--bar);
border-top: 1px solid oklch(0 0 0/.25);
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 10.5px;
color: var(--lineno);
}
.bq-21__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11.5px;
color: oklch(0.6 0.02 265);
padding: 7px 13px;
border: 1px solid oklch(1 0 0/.12);
border-radius: 99px;
}
@media (prefers-reduced-motion: reduce) {
.bq-21 * {
transition-duration: .01ms !important;
}
.bq-21__caret {
animation: none;
}
}
```How this works
Line numbers without markup — each line is a plain element; counters do the numbering:
.editor code{ counter-reset:bq21-line; }
.editor .line{ counter-increment:bq21-line; }
.editor .line::before{
content:counter(bq21-line);
display:inline-block; width:2.6ch;
margin-right:1.6ch; text-align:right;
color:var(--line-no);
user-select:none; /* copy code, not numbers */
}Insert, delete or reorder lines and the gutter renumbers itself — this is why counters beat hand-written spans and beat CSS-generated background images. user-select:none on the pseudo-element keeps the numbers out of the clipboard, the detail that separates docs sites people love from ones they curse.
The quote itself lives in real docblock grammar — /**, leading *, @author and @since tags — with each token type on a span tinted from the theme's map (comment green-gray, tag purple, string amber). The blinking caret is a 2px ::after animated in steps(1) — a real terminal caret snaps rather than fades — and it holds steady under reduced motion. The pane is still a semantic <figure>/<blockquote>: the costume is monospace, the markup is a citation.
Make it yours
- Theme: the whole editor reads from six --tok-* custom properties — port your VS Code theme's hexes in and the pane re-skins (a One Dark and a light Solarized set are commented in the CSS).
- Language dress: swap the docblock for a Python docstring ('''…''') or a Rust //! module comment — change the token spans, keep the counter gutter.
- Active line: move the .is-active class to any line; the highlight bar + brighter number follow. Wire it to :hover per line for an interactive read-along feel.
- Real code blocks: lift the counter gutter verbatim onto your pre>code blocks — it composes with any syntax highlighter that emits line elements.
Gotchas — read before shipping
- Counters reset per counter-reset scope: nest two editors and forgetting a fresh counter-reset on the inner one continues the outer numbering.
- Generated content is read by some screen readers despite user-select:none — add aria-hidden to the gutter via speak:never fallbacks, or accept numbers being announced; test your audience.
- Monospace at small sizes needs MORE line-height, not less — 1.7 here; tight code quotes read as a wall.
- steps(1) caret animation must be end-aligned (steps(1,end)) or the caret spends half its cycle invisible on load.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 113+ | 111+ |
CSS counters are CSS 2.1 — universal. Everything else is cosmetics; the floor is oklch tokens. No JS, no highlight library.