Skip to content

Instantly share code, notes, and snippets.

@mike-moreau
Created March 12, 2025 15:36
Show Gist options
  • Save mike-moreau/35877ecca05f66cc9b67355cae852ce7 to your computer and use it in GitHub Desktop.
Save mike-moreau/35877ecca05f66cc9b67355cae852ce7 to your computer and use it in GitHub Desktop.
TailwindCSS 4 Typography Plugin Replacement Utility
@layer base {
:root {
--tw-prose-body: var(--color-gray-900);
--tw-prose-headings: var(--color-brand-blue);
--tw-prose-lead: var(--color-gray-900);
--tw-prose-links: var(--color-brand-cyan-a11y-any);
--tw-prose-bold: var(--tw-prose-body);
--tw-prose-counters: var(--tw-prose-body);
--tw-prose-bullets: var(--color-brand-gold);
--tw-prose-hr: var(--color-gray-400);
--tw-prose-quotes: var(--color-brand-blue);
--tw-prose-quote-borders: var(--color-brand-blue);
--tw-prose-captions: var(--tw-prose-body);
--tw-prose-kbd: var(--tw-prose-body);
--tw-prose-kbd-shadows: NaN NaN NaN;
--tw-prose-code: var(--tw-prose-body);
--tw-prose-pre-code: var(--tw-prose-body);
--tw-prose-pre-bg: var(--color-gray-100);
--tw-prose-th-borders: var(--color-gray-400);
--tw-prose-td-borders: var(--color-gray-400);
--tw-prose-invert-body: var(--color-white);
--tw-prose-invert-headings: var(--color-white);
--tw-prose-invert-lead: var(--tw-prose-invert-body);
--tw-prose-invert-links: var(--tw-prose-invert-body);
--tw-prose-invert-bold: var(--tw-prose-invert-body);
--tw-prose-invert-counters: var(--tw-prose-invert-body);
--tw-prose-invert-bullets: var(--tw-prose-invert-body);
--tw-prose-invert-hr: var(--color-gray-400);
--tw-prose-invert-quotes: var(--color-brand-cyan);
--tw-prose-invert-quote-borders: var(--color-brand-cyan);
--tw-prose-invert-captions: var(--tw-prose-invert-body);
--tw-prose-invert-kbd: var(--tw-prose-invert-body);
--tw-prose-invert-kbd-shadows: 255 255 255;
--tw-prose-invert-code: var(--tw-prose-invert-body);
--tw-prose-invert-pre-code: var(--tw-prose-invert-body);
--tw-prose-invert-pre-bg: var(--color-black);
--tw-prose-invert-th-borders: var(--color-gray-400);
--tw-prose-invert-td-borders: var(--color-gray-400);
--prose-gap: 1.25rem;
--prose-headings-font-weight: 900;
--prose-margin-media: 2em;
}
}
@utility prose {
/* Base / Default Styles */
color: var(--tw-prose-body);
max-width: 65ch;
font-size: 1rem;
line-height: 1.75;
/* p, .lead */
& :where(p) {
margin-top: var(--prose-gap);
margin-bottom: var(--prose-gap);
}
& :where([class~="lead"]) {
color: var(--tw-prose-lead);
margin-top: 1.2em;
margin-bottom: 1.2em;
font-size: 1.25em;
line-height: 1.6;
}
/* a, strong */
& :where(a) {
color: var(--tw-prose-links);
text-underline-offset: 0.35em;
text-decoration: underline;
-webkit-text-decoration-color: color-mix(
in srgb,
currentColor 50%,
transparent 100%
);
text-decoration-color: color-mix(
in srgb,
currentColor 50%,
transparent 100%
);
font-weight: 500;
transition: all 0.2s ease-in-out;
}
& :where(a:hover) {
text-decoration-line: none;
}
& :where(strong) {
color: var(--tw-prose-bold);
font-weight: 600;
}
& :where(a strong),
& :where(blockquote strong),
& :where(thead th strong) {
color: inherit;
}
/* ol, ul, dl */
& :where(ol) {
margin-top: var(--prose-gap);
margin-bottom: var(--prose-gap);
padding-inline-start: 1.625em;
list-style-type: decimal;
}
& :where(ul) {
margin-top: var(--prose-gap);
margin-bottom: var(--prose-gap);
padding-inline-start: 1.625em;
list-style-type: disc;
}
& :where(li) {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
& :where(ol > li),
& :where(ul > li) {
padding-inline-start: 0.375em;
}
& :where(ol > li) {
color: var(--tw-prose-counters);
font-weight: 400;
}
& :where(ul > li) {
color: var(--tw-prose-bullets);
}
& :where(ul > li)::marker {
color: var(--tw-prose-bullets);
}
& :where(.prose > ul > li p){
margin-top: 0.75em;
margin-bottom: 0.75em;
}
& :where(.prose > ul > li > p:first-child){
margin-top: 1.25em;
}
& :where(.prose > ul > li > p:last-child){
margin-bottom: 1.25em;
}
& :where(.prose > ol > li > p:first-child){
margin-top: 1.25em;
}
& :where(.prose > ol > li > p:last-child){
margin-bottom: 1.25em;
}
& :where(ul ul, ul ol, ol ul, ol ol){
margin-top: 0.75em;
margin-bottom: 0.75em;
}
& :where(dl) {
margin-top: 1.25em;
margin-bottom: 1.25em;
}
& :where(dd) {
margin-top: 0.5em;
padding-inline-start: 1.625em;
}
& :where(dt) {
color: var(--tw-prose-headings);
margin-top: 1.25em;
font-weight: 600;
}
/* hr */
& :where(hr) {
border-color: var(--tw-prose-hr);
border-top-width: 1px;
margin-top: 3em;
margin-bottom: 3em;
}
/* blockquote */
& :where(blockquote){
color: var(--tw-prose-quotes);
border-inline-start-width: 0.25rem;
border-inline-start-color: var(--tw-prose-quote-borders);
quotes: "“" "”" "‘" "’";
margin-top: 1.6em;
margin-bottom: 1.6em;
padding-inline-start: 1em;
font-style: italic;
font-weight: 500;
}
& :where(blockquote p:first-of-type):before {
content: open-quote;
}
& :where(blockquote p:last-of-type):after {
content: close-quote;
}
/* h1 - h6 */
& :where(h1) {
color: var(--tw-prose-headings);
margin-top: 0;
margin-bottom: 0.888889em;
font-size: 2.25em;
font-weight: var(--prose-headings-font-weight);
line-height: 1.11111;
}
& :where(h1 strong){
color: inherit;
font-weight: 900;
}
& :where(h2) {
color: var(--tw-prose-headings);
margin-top: var(--prose-gap);
margin-bottom: var(--prose-gap);
font-size: 2.3rem;
font-weight: var(--prose-headings-font-weight);
line-height: 1.33333;
}
& :where(h2 strong){
color: inherit;
font-weight: 900;
}
& :where(h3) {
color: var(--tw-prose-headings);
margin-top: var(--prose-gap);
margin-bottom: var(--prose-gap);
font-size: 1.77rem;
font-weight: var(--prose-headings-font-weight);
line-height: 1.6;
}
& :where(h3 strong){
color: inherit;
font-weight: 900;
}
& :where(h4) {
color: var(--tw-prose-headings);
margin-top: var(--prose-gap);
margin-bottom: var(--prose-gap);
font-size: 1.3rem;
font-weight: var(--prose-headings-font-weight);
line-height: 1.5;
}
& :where(h4 strong){
color: inherit;
font-weight: 900;
}
& :where(h5) {
color: var(--tw-prose-headings);
margin-top: var(--prose-gap);
margin-bottom: var(--prose-gap);
font-size: 1.25rem;
font-weight: var(--prose-headings-font-weight);
}
& :where(h6) {
color: var(--tw-prose-headings);
margin-top: var(--prose-gap);
margin-bottom: var(--prose-gap);
font-size: 1.11rem;
font-weight: var(--prose-headings-font-weight);
}
/* media img, picture, video, figure */
& :where(img) {
margin-top: var(--prose-margin-media);
margin-bottom: var(--prose-margin-media);
}
& :where(picture) {
margin-top: var(--prose-margin-media);
margin-bottom: var(--prose-margin-media);
display: block;
}
& :where(picture > img){
margin-top: 0;
margin-bottom: 0;
}
& :where(video) {
margin-top: var(--prose-margin-media);
margin-bottom: var(--prose-margin-media);
}
& :where(kbd) {
color: var(--tw-prose-kbd);
box-shadow: 0 0 0 1px rgb(var(--tw-prose-kbd-shadows) / 10%), 0 3px
rgb(var(--tw-prose-kbd-shadows) / 10%);
padding-top: 0.1875em;
padding-inline-end: 0.375em;
padding-bottom: 0.1875em;
border-radius: var(--radius-md);
padding-inline-start: 0.375em;
font-family: inherit;
font-size: 0.875em;
font-weight: 500;
}
& :where(figure) {
margin-top: 2em;
margin-bottom: 2em;
}
& :where(figure > *){
margin-top: 0;
margin-bottom: 0;
}
& :where(figcaption){
color: var(--tw-prose-captions);
margin-top: 0.857143em;
font-size: 0.875em;
line-height: 1.42857;
}
/* code */
& :where(code) {
color: var(--tw-prose-code);
font-size: 0.875em;
font-weight: 600;
}
& :where(code):before,
& :where(code):after {
content: "`";
}
& :where(a code),
& :where(h1 code) {
color: inherit;
}
& :where(h2 code) {
color: inherit;
font-size: 0.875em;
}
& :where(h3 code) {
color: inherit;
font-size: 0.9em;
}
& :where(h4 code),
& :where(blockquote code),
& :where(thead th code){
color: inherit;
}
& :where(pre) {
color: var(--tw-prose-pre-code);
background-color: var(--tw-prose-pre-bg);
padding-top: 0.857143em;
padding-inline-end: 1.14286em;
padding-bottom: 0.857143em;
border-radius: var(--radius-md);
margin-top: 1.71429em;
margin-bottom: 1.71429em;
padding-inline-start: 1.14286em;
font-size: 0.875em;
font-weight: 400;
line-height: 1.71429;
overflow-x: auto;
}
& :where(pre code) {
font-weight: inherit;
color: inherit;
font-size: inherit;
font-family: inherit;
line-height: inherit;
background-color: #0000;
border-width: 0;
border-radius: 0;
padding: 0;
}
& :where(pre code):before,
& :where(pre code):after {
content: none;
}
/* table */
& :where(table) {
table-layout: auto;
width: 100%;
margin-top: 2em;
margin-bottom: 2em;
font-size: 0.875em;
line-height: 1.71429;
}
& :where(thead) {
border-bottom-width: 1px;
border-bottom-color: var(--tw-prose-th-borders);
}
& :where(thead th) {
color: var(--tw-prose-headings);
vertical-align: bottom;
padding-inline-end: 0.571429em;
padding-bottom: 0.571429em;
padding-inline-start: 0.571429em;
font-weight: 600;
}
& :where(thead th) {
color: var(--tw-prose-headings);
vertical-align: bottom;
padding-inline-end: 0.571429em;
padding-bottom: 0.571429em;
padding-inline-start: 0.571429em;
font-weight: 600;
}
& :where(tbody tr) {
border-bottom-width: 1px;
border-bottom-color: var(--tw-prose-td-borders);
}
& :where(tbody tr:last-child){
border-bottom-width: 0;
}
& :where(tbody td) {
vertical-align: baseline;
}
& :where(tfoot) {
border-top-width: 1px;
border-top-color: var(--tw-prose-th-borders);
}
& :where(tfoot td) {
vertical-align: top;
}
& :where(th, td) {
text-align: start;
}
& :where(tfoot td) {
vertical-align: top;
}
& :where(th, td) {
text-align: start;
}
& :where(thead th:first-child){
padding-inline-start: 0;
}
& :where(thead th:last-child){
padding-inline-end: 0;
}
& :where(tbody td, tfoot td){
padding-top: 0.571429em;
padding-inline-end: 0.571429em;
padding-bottom: 0.571429em;
padding-inline-start: 0.571429em;
}
& :where(tbody td:first-child, tfoot td:first-child){
padding-inline-start: 0;
}
& :where(tbody td:last-child, tfoot td:last-child){
padding-inline-end: 0;
}
/* margin overrides */
& :where(hr + *),
& :where(h2 + *),
& :where(h3 + *),
& :where(h4 + *) {
margin-top: 0;
}
& :where(.prose > :first-child){
margin-top: 0;
}
& :where(.prose > :last-child){
margin-bottom: 0;
}
/* Custom */
& :where(.text-tiny){
font-size: 0.66rem;
}
& :where(.text-small){
font-size: 0.75rem;
}
& :where(.text-big){
font-size: 1.33rem;
}
& :where(.text-huge){
font-size: 1.75rem;
}
}
@utility prose-lg {
/* Base / Default Styles */
font-size: 1.125rem;
line-height: 1.77778;
/* p, .lead */
& :where(p) {
margin-top: 1.33333em;
margin-bottom: 1.33333em;
}
& :where([class~="lead"]){
margin-top: 1.09091em;
margin-bottom: 1.09091em;
font-size: 1.22222em;
line-height: 1.45455;
}
/* ol, ul, dl */
& :where(ol),
& :where(ul) {
margin-top: 1.33333em;
margin-bottom: 1.33333em;
padding-inline-start: 1.55556em;
}
& :where(li) {
margin-top: 0.666667em;
margin-bottom: 0.666667em;
}
& :where(ol > li),
& :where(ul > li) {
padding-inline-start: 0.444444em;
}
& :where(.prose-lg > ul > li p){
margin-top: 0.888889em;
margin-bottom: 0.888889em;
}
& :where(.prose-lg > ul > li > p:first-child){
margin-top: 1.33333em;
}
& :where(.prose-lg > ul > li > p:last-child){
margin-bottom: 1.33333em;
}
& :where(.prose-lg > ol > li > p:first-child){
margin-top: 1.33333em;
}
& :where(.prose-lg > ol > li > p:last-child){
margin-bottom: 1.33333em;
}
& :where(ul ul, ul ol, ol ul, ol ol){
margin-top: 0.888889em;
margin-bottom: 0.888889em;
}
& :where(dl) {
margin-top: 1.33333em;
margin-bottom: 1.33333em;
}
& :where(dt) {
margin-top: 1.33333em;
}
& :where(dd) {
margin-top: 0.666667em;
padding-inline-start: 1.55556em;
}
/* h1 - h6 */
& :where(h1) {
margin-top: 0;
margin-bottom: 0.833333em;
font-size: 2.66667em;
line-height: 1;
}
& :where(h2) {
margin-top: 1.86667em;
margin-bottom: 1.06667em;
font-size: 1.66667em;
line-height: 1.33333;
}
& :where(h3) {
margin-top: 1.66667em;
margin-bottom: 0.666667em;
font-size: 1.33333em;
line-height: 1.5;
}
& :where(h4) {
margin-top: 1.77778em;
margin-bottom: 0.444444em;
line-height: 1.55556;
}
/* blockquote */
& :where(blockquote){
margin-top: 1.66667em;
margin-bottom: 1.66667em;
padding-inline-start: 1em;
}
/* media - img, picture, video */
& :where(img),
& :where(picture) {
margin-top: 1.77778em;
margin-bottom: 1.77778em;
}
& :where(picture > img){
margin-top: 0;
margin-bottom: 0;
}
& :where(video) {
margin-top: 1.77778em;
margin-bottom: 1.77778em;
}
& :where(kbd) {
padding-top: 0.222222em;
padding-inline-end: 0.444444em;
padding-bottom: 0.222222em;
border-radius: var(--radius-md);
padding-inline-start: 0.444444em;
font-size: 0.888889em;
}
& :where(figure) {
margin-top: 1.77778em;
margin-bottom: 1.77778em;
}
& :where(figure > *){
margin-top: 0;
margin-bottom: 0;
}
& :where(figcaption){
margin-top: 1em;
font-size: 0.888889em;
line-height: 1.5;
}
/* code */
& :where(code) {
font-size: 0.888889em;
}
& :where(h2 code) {
font-size: 0.866667em;
}
& :where(h3 code) {
font-size: 0.875em;
}
& :where(pre) {
padding-top: 1em;
padding-inline-end: 1.5em;
padding-bottom: 1em;
border-radius: var(--radius-md);
margin-top: 2em;
margin-bottom: 2em;
padding-inline-start: 1.5em;
font-size: 0.888889em;
line-height: 1.75;
}
/* hr */
& :where(hr) {
margin-top: 3.11111em;
margin-bottom: 3.11111em;
}
& :where(hr + *),
& :where(h2 + *),
& :where(h3 + *),
& :where(h4 + *) {
margin-top: 0;
}
/* table */
& :where(table) {
font-size: 0.888889em;
line-height: 1.5;
}
& :where(thead th) {
padding-inline-end: 0.75em;
padding-bottom: 0.75em;
padding-inline-start: 0.75em;
}
& :where(thead th:first-child){
padding-inline-start: 0;
}
& :where(thead th:last-child){
padding-inline-end: 0;
}
& :where(tbody td, tfoot td){
padding-top: 0.75em;
padding-inline-end: 0.75em;
padding-bottom: 0.75em;
padding-inline-start: 0.75em;
}
& :where(tbody td:first-child, tfoot td:first-child){
padding-inline-start: 0;
}
& :where(tbody td:last-child, tfoot td:last-child){
padding-inline-end: 0;
}
/* margin overrides */
& :where(.prose-lg > :first-child){
margin-top: 0;
}
& :where(.prose-lg > :last-child){
margin-bottom: 0;
}
}
@utility prose-sm {
/* Base / Default Styles */
font-size: 0.875rem;
line-height: 1.71429;
/* p, .lead */
& :where(p) {
margin-top: 1.14286em;
margin-bottom: 1.14286em;
}
& :where([class~="lead"]){
margin-top: 0.888889em;
margin-bottom: 0.888889em;
font-size: 1.28571em;
line-height: 1.55556;
}
/* ol, ul, dl */
& :where(ol),
& :where(ul) {
margin-top: 1.14286em;
margin-bottom: 1.14286em;
padding-inline-start: 1.57143em;
}
& :where(li) {
margin-top: 0.285714em;
margin-bottom: 0.285714em;
}
& :where(ol > li),
& :where(ul > li) {
padding-inline-start: 0.428571em;
}
& :where(.prose-sm > ul > li p){
margin-top: 0.571429em;
margin-bottom: 0.571429em;
}
& :where(.prose-sm > ul > li > p:first-child){
margin-top: 1.14286em;
}
& :where(.prose-sm > ul > li > p:last-child){
margin-bottom: 1.14286em;
}
& :where(.prose-sm > ol > li > p:first-child){
margin-top: 1.14286em;
}
& :where(.prose-sm > ol > li > p:last-child){
margin-bottom: 1.14286em;
}
& :where(ul ul, ul ol, ol ul, ol ol){
margin-top: 0.571429em;
margin-bottom: 0.571429em;
}
& :where(dl) {
margin-top: 1.14286em;
margin-bottom: 1.14286em;
}
& :where(dt) {
margin-top: 1.14286em;
}
& :where(dd) {
margin-top: 0.285714em;
padding-inline-start: 1.57143em;
}
/* blockquote */
& :where(blockquote){
margin-top: 1.33333em;
margin-bottom: 1.33333em;
padding-inline-start: 1.11111em;
}
/* h1 - h6 */
& :where(h1) {
margin-top: 0;
margin-bottom: 0.8em;
font-size: 2.14286em;
line-height: 1.2;
}
& :where(h2) {
margin-top: 1.6em;
margin-bottom: 0.8em;
font-size: 1.42857em;
line-height: 1.4;
}
& :where(h3) {
margin-top: 1.55556em;
margin-bottom: 0.444444em;
font-size: 1.28571em;
line-height: 1.55556;
}
& :where(h4) {
margin-top: 1.42857em;
margin-bottom: 0.571429em;
line-height: 1.42857;
}
/* media - img, picture, video */
& :where(img),
& :where(picture) {
margin-top: 1.71429em;
margin-bottom: 1.71429em;
}
& :where(picture > img){
margin-top: 0;
margin-bottom: 0;
}
& :where(video) {
margin-top: 1.71429em;
margin-bottom: 1.71429em;
}
& :where(kbd) {
padding-top: 0.142857em;
padding-inline-end: 0.357143em;
padding-bottom: 0.142857em;
border-radius: var(--radius-md);
padding-inline-start: 0.357143em;
font-size: 0.857143em;
}
& :where(figure) {
margin-top: 1.71429em;
margin-bottom: 1.71429em;
}
& :where(figure > *){
margin-top: 0;
margin-bottom: 0;
}
& :where(figcaption){
margin-top: 0.666667em;
font-size: 0.857143em;
line-height: 1.33333;
}
/* code */
& :where(code) {
font-size: 0.857143em;
}
& :where(h2 code) {
font-size: 0.9em;
}
& :where(h3 code) {
font-size: 0.888889em;
}
& :where(pre) {
padding-top: 0.666667em;
padding-inline-end: 1em;
padding-bottom: 0.666667em;
border-radius: var(--radius-sm);
margin-top: 1.66667em;
margin-bottom: 1.66667em;
padding-inline-start: 1em;
font-size: 0.857143em;
line-height: 1.66667;
}
/* hr */
& :where(hr) {
margin-top: 2.85714em;
margin-bottom: 2.85714em;
}
& :where(hr + *),
& :where(h2 + *),
& :where(h3 + *),
& :where(h4 + *) {
margin-top: 0;
}
/* table */
& :where(table) {
font-size: 0.857143em;
line-height: 1.5;
}
& :where(thead th) {
padding-inline-end: 1em;
padding-bottom: 0.666667em;
padding-inline-start: 1em;
}
& :where(thead th:first-child){
padding-inline-start: 0;
}
& :where(thead th:last-child){
padding-inline-end: 0;
}
& :where(tbody td, tfoot td){
padding-top: 0.666667em;
padding-inline-end: 1em;
padding-bottom: 0.666667em;
padding-inline-start: 1em;
}
& :where(tbody td:first-child, tfoot td:first-child){
padding-inline-start: 0;
}
& :where(tbody td:last-child, tfoot td:last-child){
padding-inline-end: 0;
}
/* margin overrides */
& :where(.prose-sm > :first-child){
margin-top: 0;
}
& :where(.prose-sm > :last-child){
margin-bottom: 0;
}
}
@utility prose-invert {
--tw-prose-body: var(--tw-prose-invert-body);
--tw-prose-headings: var(--tw-prose-invert-headings);
--tw-prose-lead: var(--tw-prose-invert-lead);
--tw-prose-links: var(--tw-prose-invert-links);
--tw-prose-bold: var(--tw-prose-invert-bold);
--tw-prose-counters: var(--tw-prose-invert-counters);
--tw-prose-bullets: var(--tw-prose-invert-bullets);
--tw-prose-hr: var(--tw-prose-invert-hr);
--tw-prose-quotes: var(--tw-prose-invert-quotes);
--tw-prose-quote-borders: var(--tw-prose-invert-quote-borders);
--tw-prose-captions: var(--tw-prose-invert-captions);
--tw-prose-kbd: var(--tw-prose-invert-kbd);
--tw-prose-kbd-shadows: var(--tw-prose-invert-kbd-shadows);
--tw-prose-code: var(--tw-prose-invert-code);
--tw-prose-pre-code: var(--tw-prose-invert-pre-code);
--tw-prose-pre-bg: var(--tw-prose-invert-pre-bg);
--tw-prose-th-borders: var(--tw-prose-invert-th-borders);
--tw-prose-td-borders: var(--tw-prose-invert-td-borders);
}
@mike-moreau
Copy link
Author

Tailwind's Typography CSS would be good to reference also https://github.com/tailwindlabs/tailwindcss.com/blob/main/src/app/typography.css

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment