Maintainers
Pricing
Enterprise
More
More
Documentation
Try Live
Rankings
Install
Blog
Docs7
Ask
New
Add Docs
Tailwind CSS Typography
https://github.com/tailwindlabs/tailwindcss-typography
Admin
Beautiful typographic defaults for HTML you don't control.
Tokens:
27,354
Snippets:
202
Trust Score:
9.3
License:
MIT
Update:
3 weeks ago
Context
Chat
Benchmark
87.92
Latest
Show doc for...
Code
Info
Show Results
Tokens:
Raw
Copy
Link
Tokens:
Raw
Copy
Link
### Install and configure plugin for Tailwind v4 Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md For Tailwind CSS v4, install the plugin from npm and add it to your main `style.css` file using the `@plugin` directive. ```shell npm install -D @tailwindcss/typography ``` ```diff @import "tailwindcss"; + @plugin "@tailwindcss/typography"; ``` -------------------------------- ### commonTrailingPseudos usage example Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Shows the internal call path for commonTrailingPseudos with two example selectors and their expected return values. The first returns the common trailing pseudo and the rebuilt selector; the second returns null and the original selector because the pseudo-elements differ. ```js const { commonTrailingPseudos } = require('./utils') commonTrailingPseudos('ol li::marker, ul li::marker') // → ['::marker', 'ol li, ul li'] commonTrailingPseudos('ol li::before, ul li::after') // → [null, 'ol li::before, ul li::after'] // differing pseudos: untouched ``` -------------------------------- ### Plugin constructor options examples (v3 defaults and custom) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Shows the default plugin usage and a custom configuration with className 'wysiwyg' and target 'legacy'. The target option changes selector generation strategy. ```javascript // v3 — defaults plugins: [require('@tailwindcss/typography')] // v3 — custom class name and legacy target plugins: [require('@tailwindcss/typography')({ className: 'wysiwyg', target: 'legacy' })] ``` -------------------------------- ### Pass plugin options via @plugin block (v4 equivalent) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Equivalent to the v3 custom options example, but using the CSS-first @plugin syntax. Sets className to 'wysiwyg' and target to 'legacy'. ```css /* v4 — same via @plugin options */ @plugin "@tailwindcss/typography" { className: wysiwyg; target: legacy; } ``` -------------------------------- ### Example output for inWhere Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Example output of `inWhere('blockquote p:first-of-type::before', { className: 'prose', modifier: 'DEFAULT', prefix })`. Shows the resulting selector with `:where(...)` and the `not-prose` escape hatch, with the trailing pseudo-element moved outside the wrapper. ```css .prose :where(blockquote p:first-of-type):not(:where([class~='not-prose'], [class~='not-prose'] *))::before ``` -------------------------------- ### HTML paragraph example Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/demo/components/MarkdownSampleShort.mdx A simple HTML paragraph element used to demonstrate the typography plugin's styling of prose content. ```html <p> But a recent study shows that the celebrated appetizer may be linked to a series of rabies cases springing up around the country. </p> ``` -------------------------------- ### merge example - merging two objects Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Example usage of the merge function. Merges two objects, deep-merging the 'p' property and overwriting 'color' with the source value. The output is shown in the comment. ```javascript const { merge } = require('./utils') merge({ p: { marginTop: '1em' }, color: 'red' }, { p: { marginBottom: '1em' }, color: 'blue' }) // { p: { marginTop: '1em', marginBottom: '1em' }, color: 'blue' } ``` -------------------------------- ### Use plugin in Tailwind config Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Two usage examples of the plugin in a Tailwind config. The first shows the common call without options; the second shows calling with an options object to set className and target. ```js // Called without options (most common): plugins: [require('@tailwindcss/typography')] // Called with an options object: plugins: [require('@tailwindcss/typography')({ className: 'wysiwyg', target: 'legacy' })] ``` -------------------------------- ### Using the prose class in HTML Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/demo/components/MarkdownSample.mdx Apply the prose class to a block of vanilla HTML content to turn it into a well-formatted document. The example shows an article element with the prose class containing headings and paragraphs. ```html <article class="prose"> <h1>Garlic bread with cheese: What the science tells us</h1> <p> For years parents have espoused the health benefits of eating garlic bread with cheese to their children, with the food earning such an iconic status in our culture that kids will often dress up as warm, cheesy loaf for Halloween. </p> <p> But a recent study shows that the celebrated appetizer may be linked to a series of rabies cases springing up around the country. </p> <!-- ... --> </article> ``` -------------------------------- ### Create custom color theme with @utility prose-pink Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Define a custom color theme for the Tailwind CSS Typography plugin using a `@utility` directive in your CSS file. This example creates a `prose-pink` utility with all the necessary CSS custom properties for body, headings, links, code, and inverted styles. ```css @utility prose-pink { --tw-prose-body: var(--color-pink-800); --tw-prose-headings: var(--color-pink-900); --tw-prose-lead: var(--color-pink-700); --tw-prose-links: var(--color-pink-900); --tw-prose-bold: var(--color-pink-900); --tw-prose-counters: var(--color-pink-600); --tw-prose-bullets: var(--color-pink-400); --tw-prose-hr: var(--color-pink-300); --tw-prose-quotes: var(--color-pink-900); --tw-prose-quote-borders: var(--color-pink-300); --tw-prose-captions: var(--color-pink-700); --tw-prose-code: var(--color-pink-900); --tw-prose-pre-code: var(--color-pink-100); --tw-prose-pre-bg: var(--color-pink-900); --tw-prose-th-borders: var(--color-pink-300); --tw-prose-td-borders: var(--color-pink-200); --tw-prose-invert-body: var(--color-pink-200); --tw-prose-invert-headings: var(--color-white); --tw-prose-invert-lead: var(--color-pink-300); --tw-prose-invert-links: var(--color-white); --tw-prose-invert-bold: var(--color-white); --tw-prose-invert-counters: var(--color-pink-400); --tw-prose-invert-bullets: var(--color-pink-600); --tw-prose-invert-hr: var(--color-pink-700); --tw-prose-invert-quotes: var(--color-pink-100); --tw-prose-invert-quote-borders: var(--color-pink-700); --tw-prose-invert-captions: var(--color-pink-400); --tw-prose-invert-code: var(--color-white); --tw-prose-invert-pre-code: var(--color-pink-300); --tw-prose-invert-pre-bg: rgb(0 0 0 / 50%); --tw-prose-invert-th-borders: var(--color-pink-600); --tw-prose-invert-td-borders: var(--color-pink-700); } ``` -------------------------------- ### Pass plugin options inline in @plugin block (Tailwind v4) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Options can be passed inline within the @plugin block. This example sets the className option to 'wysiwyg'. ```css @plugin "@tailwindcss/typography" { className: wysiwyg; } ``` -------------------------------- ### Customizing plugin styles in tailwind.config.js Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Example tailwind.config.js file that customizes the typography plugin's default styles via the 'typography' and 'css' keys. Place this file in your project root and ensure the '@config' directive points to it. ```js /** @type {import('tailwindcss').Config} */ module.exports = { theme: { extend: { typography: { DEFAULT: { css: { color: '#333', a: { color: '#3182ce', '&:hover': { color: '#2c5282', }, }, }, }, }, }, }, } ``` -------------------------------- ### Consumer code using typography variables Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/styles.md Tailwind v4 custom @utility that overrides typography CSS variables. The variables are the stable contract; this example shows overriding --tw-prose-body and --tw-prose-headings, with a comment indicating all 18 base and 18 invert variables. ```css /* Custom `@utility` theme (Tailwind v4) — variables are the stable contract */ @utility prose-pink { --tw-prose-body: var(--color-pink-800); --tw-prose-headings: var(--color-pink-900); /* …all 18 base + 18 invert variables… */ } ``` -------------------------------- ### Create plugin with plugin.withOptions Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Default export of the plugin, created with plugin.withOptions. The first argument is an options function that returns a handler receiving addVariant, addComponents, theme, and prefix; the second provides the theme configuration with typography styles. ```js module.exports = plugin.withOptions( ({ className = 'prose', target = 'modern' } = {}) => { return function ({ addVariant, addComponents, theme, prefix }) { // ... (see "handler" below) } }, () => { return { theme: { typography: styles }, } } ) ``` -------------------------------- ### plugin(options?) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/types.md The main exported plugin function. It accepts an optional options object and returns a Tailwind plugin object with a handler function. ```APIDOC ## plugin(options?) ### Description Callable plugin function that configures the typography plugin. Accepts optional options to customize the base class name and target mode. ### Method Function call ### Endpoint N/A (TypeScript function) ### Parameters #### Options - **className** (string) - Optional - Base class name for generated components and variants. Default: `'prose'`. - **target** ('modern' | 'legacy') - Optional - Styling strategy. `'modern'` uses `:where()`-wrapped selectors, `'legacy'` uses descendant scoping. Default: `'modern'`. ### Return Value Returns an object with a `handler` function that is invoked by Tailwind's build pipeline. ### Example ```ts import typography = require('@tailwindcss/typography') const plugin = typography({ className: 'prose', target: 'modern' }) ``` ``` -------------------------------- ### Private helper functions in src/styles.js Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/styles.md Module-local helpers in src/styles.js (lines 3-27) used to compute static theme values. round() trims trailing zeros from 7-decimal numbers; rem() converts px to rem (px/16); em() converts px to em (px/base); opacity() returns rgb(r g b / opacity) for 3- or 6-digit hex colors and color-mix(in oklab, ...) for non-hex colors. ```javascript const round = (num) => num .toFixed(7) .replace(/(\.[0-9]+?)0+$/, '$1') .replace(/\.0$/, '') const rem = (px) => `${round(px / 16)}rem` const em = (px, base) => `${round(px / base)}em` const opacity = (color, opacity) => { /* … */ } ``` -------------------------------- ### Usage with custom className Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Shows how to use the custom class name from the configuration. The 'not-wysiwyg' class prevents the typography styles from applying to that section. ```html <article class="wysiwyg wysiwyg-slate lg:wysiwyg-xl"> <h1>My Heading</h1> <p>...</p> <div class="not-wysiwyg"> <!-- Some example or demo that needs to be prose-free --> </div> <p>...</p> <!-- ... --> </article> ``` -------------------------------- ### Enable @config for custom CSS Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Diff showing the lines to add to your CSS file to enable the JavaScript-based theme API via the '@config' directive. The plus-marked line is the addition. ```diff @import "tailwindcss"; @plugin "@tailwindcss/typography"; + @config "./tailwind.config.js"; ``` -------------------------------- ### Select stone gray scale with prose-stone Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Use the `prose-stone` modifier for the Stone gray scale. Must include the base `prose` class. ```html <article class="prose prose-stone">{{ markdown }}</article> ``` -------------------------------- ### Select gray scale with prose-slate Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Choose a gray scale modifier (e.g., `prose-slate`) to match your project's gray palette. Must be used together with the base `prose` class. ```html <article class="prose prose-slate">{{ markdown }}</article> ``` -------------------------------- ### Import internal utilities from src/utils.js Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Imports the internal utility functions from the module file. These helpers are not part of the public API and are used by the plugin entry point. ```javascript const { commonTrailingPseudos, isObject, isPlainObject, merge, castArray } = require('./utils') ``` -------------------------------- ### Import the typography plugin for Tailwind v3 and v4 Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Shows how to import the typography plugin in Tailwind v3 via JavaScript (using the package name or a relative path) and in Tailwind v4 via the CSS @plugin directive. Use this to add the plugin to your Tailwind configuration. ```javascript // Tailwind v3 (tailwind.config.js) const typography = require('@tailwindcss/typography') // or relative const typography = require('./src/index.js') // Tailwind v4 (CSS) @plugin "@tailwindcss/typography"; ``` -------------------------------- ### Full declaration file src/index.d.ts Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/types.md Complete declaration file for the package. Defines the plugin function type, a namespace member, and a CommonJS-style export. Use this as the authoritative type reference for the package. ```ts declare function plugin(options?: Partial<{ className: string; target: 'modern' | 'legacy' }>): { handler: () => void } declare namespace plugin { const __isOptionsFunction: true } export = plugin ``` -------------------------------- ### Replicating internal theme shape via require Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/styles.md Replicates the internal theme shape by requiring src/styles.js directly. Note that this subpath is not a documented public entry; styles.js is shipped in the npm tarball but not listed in the package's files allowlist. ```javascript // Reading the exact defaults the plugin ships with: const { DEFAULT, slate, base } = require('@tailwindcss/typography/src/styles') // (not a supported package subpath — use node_modules file paths or the // `require('@tailwindcss/typography')` plugin + theme('typography') instead) ``` -------------------------------- ### Basic registration (Tailwind v3) - config and usage Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Basic registration for Tailwind v3. The JavaScript config registers the plugin with require('@tailwindcss/typography') and the HTML shows the default prose class usage with responsive and dark mode variants. ```js // tailwind.config.js /** @type {import('tailwindcss').Config} */ module.exports = { content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], theme: { extend: {}, }, plugins: [require('@tailwindcss/typography')], } ``` ```html <article class="prose lg:prose-xl dark:prose-invert">…</article> ``` -------------------------------- ### Configure custom color theme in tailwind.config.js (Tailwind v3) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md For Tailwind v3, configure a custom color theme by extending the `typography` section in `tailwind.config.js`. Provide your colors under the `css` key, following the structure shown for a pink theme. ```js /** @type {import('tailwindcss').Config} */ module.exports = { theme: { extend: { typography: () => ({ pink: { css: { '--tw-prose-body': 'var(--color-pink-800)', '--tw-prose-headings': 'var(--color-pink-900)', '--tw-prose-lead': 'var(--color-pink-700)', '--tw-prose-links': 'var(--color-pink-900)', '--tw-prose-bold': 'var(--color-pink-900)', '--tw-prose-counters': 'var(--color-pink-600)', '--tw-prose-bullets': 'var(--color-pink-400)', '--tw-prose-hr': 'var(--color-pink-300)', '--tw-prose-quotes': 'var(--color-pink-900)', '--tw-prose-quote-borders': 'var(--color-pink-300)', '--tw-prose-captions': 'var(--color-pink-700)', '--tw-prose-code': 'var(--color-pink-900)', '--tw-prose-pre-code': 'var(--color-pink-100)', '--tw-prose-pre-bg': 'var(--color-pink-900)', '--tw-prose-th-borders': 'var(--color-pink-300)', '--tw-prose-td-borders': 'var(--color-pink-200)', '--tw-prose-invert-body': 'var(--color-pink-200)', '--tw-prose-invert-headings': 'var(--color-white)', '--tw-prose-invert-lead': 'var(--color-pink-300)', '--tw-prose-invert-links': 'var(--color-white)', '--tw-prose-invert-bold': 'var(--color-white)', '--tw-prose-invert-counters': 'var(--color-pink-400)', '--tw-prose-invert-bullets': 'var(--color-pink-600)', '--tw-prose-invert-hr': 'var(--color-pink-700)', '--tw-prose-invert-quotes': 'var(--color-pink-100)', '--tw-prose-invert-quote-borders': 'var(--color-pink-700)', '--tw-prose-invert-captions': 'var(--color-pink-400)', '--tw-prose-invert-code': 'var(--color-white)', '--tw-prose-invert-pre-code': 'var(--color-pink-300)', '--tw-prose-invert-pre-bg': 'rgb(0 0 0 / 50%)', '--tw-prose-invert-th-borders': 'var(--color-pink-600)', '--tw-prose-invert-td-borders': 'var(--color-pink-700)', }, }, }), }, }, } ``` -------------------------------- ### commonTrailingPseudos(selector) utility Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Parses a selector list and lifts common trailing ::-prefixed pseudo-elements out of the selector so the plugin can suffix them outside the :where(...) wrapper. Returns a tuple [trailingPseudos, rebuiltSelector]; if pseudo-elements differ, the selector is returned untouched. Called from inWhere for every selector object under the target: 'modern' code path. ```js /** * @param {string} selector */ commonTrailingPseudos(selector) { let ast = parseSelector.astSync(selector) /** @type {import('postcss-selector-parser').Pseudo[][]} */ let matrix = [] // Put the pseudo elements in reverse order in a sparse, column-major 2D array for (let [i, sel] of ast.nodes.entries()) { for (const [j, child] of [...sel.nodes].reverse().entries()) { // We only care about pseudo elements if (child.type !== 'pseudo' || !child.value.startsWith('::')) { break } matrix[j] = matrix[j] || [] matrix[j][i] = child } } let trailingPseudos = parser.selector() // At this point the pseudo elements are in a column-major 2D array // This means each row contains one "column" of pseudo elements from each selector // We can compare all the pseudo elements in a row to see if they are the same for (const pseudos of matrix) { // It's a sparse 2D array so there are going to be holes in the rows // We skip those if (!pseudos) { continue } let values = new Set(pseudos.map((p) => p.value)) // The pseudo elements are not the same if (values.size > 1) { break } pseudos.forEach((pseudo) => pseudo.remove()) trailingPseudos.prepend(pseudos[0]) } if (trailingPseudos.nodes.length) { return [trailingPseudos.toString(), ast.toString()] } return [null, selector] } ``` -------------------------------- ### isUsableColor(color, values) utility Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Returns true when values is a plain object, the color name is not 'gray', and a 600 shade exists. Not referenced anywhere in src/*.js in this version; it is a retained vestige of an earlier color-theme-generation strategy. ```js isUsableColor(color, values) { return isPlainObject(values) && color !== 'gray' && values[600] } ``` -------------------------------- ### Define HandlerContext interface for plugin options function Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/types.md Describes the handler context object passed to the plugin's options function. It includes addVariant and addComponents functions, a theme function for accessing configuration, and a prefix function for selector manipulation. ```ts interface HandlerContext { addVariant: Function // Tailwind v3: registers custom variants addComponents: Function theme: (path: string) => any // called as theme('typography') prefix: (selector: string) => string } ``` -------------------------------- ### PluginOptions interface Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/types.md Inline-expanded parameter type for the plugin options. Both fields are optional. className defaults to 'prose', target defaults to 'modern'. ```ts interface PluginOptions { className?: string // default 'prose' (source: src/index.js:66) target?: 'modern' | 'legacy' // default 'modern' (source: src/index.js:66) } ``` -------------------------------- ### Use typography config in Tailwind v4 with @config Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Shows how to use the same JS config shape in Tailwind v4 with `@config`. This CSS snippet imports Tailwind, the typography plugin, and points to the JavaScript config file. ```css @import "tailwindcss"; @plugin "@tailwindcss/typography"; @config "./tailwind.config.js"; ``` -------------------------------- ### Advanced: custom class name + legacy target Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Advanced configuration with custom class name and legacy target. With target: 'legacy', selectors are generated as .wysiwyg h1 (descendant scoping) instead of the modern :where() form. Note that the not-${className} escape hatch is only produced by inWhere, which is bypassed in legacy mode, so not-wysiwyg does not exclude elements in legacy output. ```js // tailwind.config.js module.exports = { plugins: [ require('@tailwindcss/typography')({ className: 'wysiwyg', // default: 'prose' target: 'legacy', // default: 'modern' — scoped selectors, higher specificity }), ], } ``` ```html <article class="wysiwyg wysiwyg-slate"> <h1>Rendered markdown</h1> <div class="not-wysiwyg">…unstyled sandbox…</div> </article> ``` -------------------------------- ### Adapt to dark mode with prose-invert Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Trigger the dark mode version of the default color theme by adding the `prose-invert` class, typically combined with `dark:` for dark mode. ```html <article class="prose dark:prose-invert">{{ markdown }}</article> ``` -------------------------------- ### Declare plugin.__isOptionsFunction namespace constant Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/types.md Declares a namespace constant that serves as a static marker flag. Tailwind recognizes this flag when the plugin is referenced in a CSS @plugin directive (v4). It is read by the consumer, not by the package's runtime. ```ts declare namespace plugin { const __isOptionsFunction: true } ``` -------------------------------- ### Require and inject typography theme Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/styles.md Shows how the default typography theme is required and injected into the Tailwind config's theme key. The comment references the internal usage in src/index.js. ```javascript // Consumed internally: const styles = require('./styles') // src/index.js:2 // configFn injects it into the theme: // theme: { typography: styles } (src/index.js:133-135) ``` -------------------------------- ### Plugin handler function with addVariant, addComponents, theme, prefix Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md The handler function returned by the plugin options function, invoked by Tailwind at build time. It receives Tailwind v3 APIs: addVariant, addComponents, theme, and prefix. It reads the typography theme and registers element variants and component classes. ```javascript function ({ addVariant, addComponents, theme, prefix }) { let modifiers = theme('typography') let options = { className, prefix } // ...registers element variants and component classes } ``` -------------------------------- ### Default tailwind.config.js Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/demo/components/MarkdownSample.mdx A default Tailwind CSS configuration file as shown in the documentation. It includes empty purge, theme, variants, and plugins arrays. ```js module.exports = { purge: [], theme: { extend: {}, }, variants: {}, plugins: [], } ``` -------------------------------- ### Using css array to layer typography rules Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/styles.md Shows the css option as an array of objects to layer rules; each entry is deep-merged in order. This is a supported way to combine multiple style objects. ```javascript typography: { DEFAULT: { css: [ { color: 'var(--color-gray-800)' }, { a: { color: '#3182ce', '&:hover': { color: '#2c5282' } } }, ], }, } ``` -------------------------------- ### Custom color theme with @utility in Tailwind v4 Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Defines a custom color theme in Tailwind v4 using the `@utility` directive. The block must define all 18 `--tw-prose-*` and 18 `--tw-prose-invert-*` variables to satisfy the full variable contract. ```css @utility prose-pink { --tw-prose-body: var(--color-pink-800); --tw-prose-headings: var(--color-pink-900); /* … remaining 16 base + 18 invert variables … */ --tw-prose-invert-td-borders: var(--color-pink-700); } ``` -------------------------------- ### Apply prose-lg type scale Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Apply the `prose-lg` size modifier for a larger type scale. Must include the base `prose` class. ```html <article class="prose prose-lg">{{ markdown }}</article> ``` -------------------------------- ### Import typography plugin in TypeScript Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/types.md Two ways to import the plugin in TypeScript. The first uses CommonJS-style require, the second uses ES module import with esModuleInterop enabled. ```ts import typography = require('@tailwindcss/typography') // or, with esModuleInterop: import typography from '@tailwindcss/typography' ``` -------------------------------- ### inWhere function implementation Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Defines the `inWhere` function used by the typography plugin to generate specificity-sandboxed selectors. It wraps the given selector in `:where(...)` and appends a `:not(:where(...))` escape hatch for `not-${className}`. Handles `>`-prefixed selectors by prepending the component class and lifts common trailing pseudo-elements via `commonTrailingPseudos`. ```js function inWhere(selector, { className, modifier, prefix }) { let prefixedNot = prefix(`.not-${className}`).slice(1) let selectorPrefix = selector.startsWith('>') ? `${modifier === 'DEFAULT' ? `.${className}` : `.${className}-${modifier}`} ` : '' // Parse the selector, if every component ends in the same pseudo element(s) then move it to the end let [trailingPseudo, rebuiltSelector] = commonTrailingPseudos(selector) if (trailingPseudo) { return `:where(${selectorPrefix}${rebuiltSelector}):not(:where([class~="${prefixedNot}"],[class~="${prefixedNot}"] *))${trailingPseudo}` } return `:where(${selectorPrefix}${selector}):not(:where([class~="${prefixedNot}"],[class~="${prefixedNot}"] *))` } ``` -------------------------------- ### addComponents object for typography theme keys Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md The object passed to addComponents for each key of the typography theme. It generates the component class name based on the modifier, using the default className or a suffixed variant, and converts the configuration to CSS. ```javascript { [modifier === 'DEFAULT' ? `.${className}` : `.${className}-${modifier}`]: configToCss(modifiers[modifier], { target, className, modifier, prefix }), } ``` -------------------------------- ### Register @tailwindcss/typography in Tailwind CSS v3 (JS config) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Use this JavaScript configuration to enable the typography plugin in a Tailwind CSS v3 project. Add the plugin to the plugins array in tailwind.config.js. ```javascript // tailwind.config.js module.exports = { plugins: [require('@tailwindcss/typography')], } ``` -------------------------------- ### merge(target, ...sources) - Deep merge objects Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Deep-merges source objects into a mutable target object, returning the same reference. Plain-object values are recursively merged; arrays are merged positionally, recursively merging only when both items are plain objects. Other values are assigned directly. Consumed by configToCss to merge css array entries and computed results. ```javascript function merge(target, ...sources) { if (!sources.length) return target const source = sources.shift() if (isObject(target) && isObject(source)) { for (const key in source) { if (Array.isArray(source[key])) { if (!target[key]) target[key] = [] source[key].forEach((item, index) => { if (isPlainObject(item) && isPlainObject(target[key][index])) { target[key][index] = merge(target[key][index], item) } else { target[key][index] = item } }) } else if (isPlainObject(source[key])) { if (!target[key]) target[key] = {} merge(target[key], source[key]) } else { target[key] = source[key] } } } return merge(target, ...sources) } ``` -------------------------------- ### Use prose class for basic typography Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Use the `prose` class on a container element to apply sensible typography styles to vanilla HTML content. The `lg:prose-xl` modifier adjusts the size at large breakpoints. This is the basic usage pattern. ```html <article class="prose lg:prose-xl"> <h1>Garlic bread with cheese: What the science tells us</h1> <p> For years parents have espoused the health benefits of eating garlic bread with cheese to their children, with the food earning such an iconic status in our culture that kids will often dress up as warm, cheesy loaf for Halloween. </p> <p> But a recent study shows that the celebrated appetizer may be linked to a series of rabies cases springing up around the country. </p> <!-- ... --> </article> ``` -------------------------------- ### Responsive type scale with md:prose-lg lg:prose-xl Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Combine size modifiers with responsive breakpoint prefixes to change the typography size at different viewport widths. Uses `md:prose-lg` and `lg:prose-xl`. ```html <article class="prose md:prose-lg lg:prose-xl">{{ markdown }}</article> ``` -------------------------------- ### Element variants usage Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Element variants usage. Adds prose-${name}:${utility} variants for every HTML element typography styles cover (prose-headings, prose-p, prose-pre, prose-lead, …), plus prose-lead targeting [class~="lead"]. ```html <article class="prose prose-a:text-blue-600 prose-headings:underline prose-img:rounded-xl"> {{ markdown }} </article> ``` -------------------------------- ### merge(target, ...sources) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Utility function to merge objects with deep-merge and positional array merging. ```APIDOC ## `merge(target, ...sources)` ### Description Merges source objects into a target object. The target is mutated in place and returned. Plain-object values are deep-merged recursively; array values are merged positionally; other values are assigned directly by key. ### Parameters - `target` (Object) - Required - Mutable destination object (mutated in place and returned) - `...sources` (Object[]) - Optional - Source objects merged into `target` in order ### Returns - `Object` - The merged object (same reference as `target`). ### Example ```js const { merge } = require('./utils') merge({ p: { marginTop: '1em' }, color: 'red' }, { p: { marginBottom: '1em' }, color: 'blue' }) // { p: { marginTop: '1em', marginBottom: '1em' }, color: 'blue' } ``` ``` -------------------------------- ### plugin Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md The default export of @tailwindcss/typography. A Tailwind plugin created with plugin.withOptions that accepts an optional options object and returns a plugin object with a handler function. ```APIDOC ## [PLUGIN] plugin ### Description The default export of @tailwindcss/typography. A Tailwind plugin created with plugin.withOptions that accepts an optional options object and returns a plugin object with a handler function. ### Method PLUGIN ### Endpoint plugin ### Parameters #### Options - **className** (string) - Optional - Default: `'prose'` - Base class name for all generated typography classes (`prose`, `prose-lg`, …) and the negated `not-${className}` escape hatch. - **target** ('modern' | 'legacy') - Optional - Default: `'modern'` - Selector generation strategy: `'modern'` wraps selectors in `:where(...)` for zero specificity; `'legacy'` scopes selectors with descendant combinator `& <selector>` for higher specificity. ### Return Value A Tailwind plugin object of shape `{ handler: () => void }`. When Tailwind processes `plugins: [...]`, it invokes the handler with a context object `{ addVariant, addComponents, theme, prefix }`. ### Usage Examples ```js // Called without options (most common): plugins: [require('@tailwindcss/typography')] // Called with an options object: plugins: [require('@tailwindcss/typography')({ className: 'wysiwyg', target: 'legacy' })] ``` ### Notes - The module is `plugin.withOptions(...)`, so it can be used in the options-function form. - The namespace member `plugin.__isOptionsFunction` is a static marker flag that tells Tailwind how to treat the plugin when referenced by name inside a CSS file (v4 `@plugin` directive). It is never read or written by the package's runtime code. ``` -------------------------------- ### Configure plugin with custom className Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Registers the typography plugin in Tailwind CSS v4 with a custom class name instead of the default 'prose'. Replace 'wysiwyg' with any desired class name; all default prose classes will use this prefix. ```css @import 'tailwindcss'; @plugin "@tailwindcss/typography" { className: wysiwyg; } ``` -------------------------------- ### Apply prose classes to HTML container Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Use on any vanilla HTML you don't control, such as Markdown output or CMS content. The `lg:prose-xl` modifier increases the size at the `lg` breakpoint. ```html <article class="prose lg:prose-xl">{{ markdown }}</article> ``` -------------------------------- ### computed constant (empty registry) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Module-local constant in src/index.js:5-8. It is an empty registry; any key in a modifier's config that also exists in computed would be replaced with the return value of computed[key](config[key]) before merging (see configToCss). Currently no keys exist, so this path is inert. ```js const computed = { // Reserved for future "magic properties", for example: // bulletColor: (color) => ({ 'ul > li::before': { backgroundColor: color } }), } ``` -------------------------------- ### Apply prose-xl type scale Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Apply the `prose-xl` size modifier to increase the overall typography size. Must be used with the base `prose` class. ```html <article class="prose prose-xl">{{ markdown }}</article> ``` -------------------------------- ### isPlainObject(value) Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Utility function to check if a value is a plain object. ```APIDOC ## `isPlainObject(value)` ### Description Determines whether a given value is a plain object. Returns `true` only for plain objects: `[object Object]` tag, and a prototype chain that terminates at `Object.prototype` (or a `null` prototype). Arrays, `Date`, regexes, class instances, etc. return `false`. ### Parameters - `value` (any) - Required - Value to test ### Returns - `boolean` - `true` only for plain objects, `false` otherwise. ``` -------------------------------- ### Using CSS variables in typography config Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Alternative tailwind.config.js configuration using CSS variables for theme access. The 'css' property can reference variables like 'var(--color-gray-800)' to link with your Tailwind theme. ```js /** @type {import('tailwindcss').Config} */ module.exports = { theme: { extend: { typography: { DEFAULT: { css: { color: 'var(--color-gray-800)', // ... }, }, }, }, }, } ``` -------------------------------- ### Define TypographyTheme interface for Tailwind v3 config Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/types.md Defines the shape of the typography theme entry used in Tailwind v3 config under theme.typography or theme.extend.typography. The modifier key 'DEFAULT' maps to the base class, while other keys generate class names like .${className}-${key}. ```ts interface TypographyTheme { [modifier: string]: { css: CSSObject | CSSObject[] // CSS-in-JS syntax (Tailwind plugin rule objects) } } // `modifier` is 'DEFAULT' for the base class; any other key becomes `.${className}-${key}` ``` -------------------------------- ### Entry shapes for size and color modifiers Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/styles.md Illustrates the two shapes of the css property: size modifiers use an array of two objects (size rules plus zero-margin rules for first/last child), while color themes use a single object of CSS variables. ```javascript // Audio size modifier entry: { css: [ { fontSize: '0.875rem', lineHeight: '1.7142857', p: { marginTop: '1.1428571em', … } }, { '> :first-child': { marginTop: '0' }, '> :last-child': { marginBottom: '0' } }, ], } // Color theme entry: { css: { '--tw-prose-body': colors.slate[700], '--tw-prose-headings': colors.slate[900], // … }, } ``` -------------------------------- ### configToCss: merge and rewrite selectors Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/index.md Merges a modifier's theme value (config.css) with any computed magic properties and rewrites selectors via updateSelector. For modern targets, object values with nested objects are wrapped with inWhere and recursively processed; legacy targets and array values keep keys unchanged. The computed object is currently empty, so the merge effectively becomes merge({}, ...castArray(config.css || {})). ```js function configToCss(config = {}, { target, className, modifier, prefix }) { function updateSelector(k, v) { if (target === 'legacy') { return [k, v] } if (Array.isArray(v)) { return [k, v] } if (isObject(v)) { let nested = Object.values(v).some(isObject) if (nested) { return [ inWhere(k, { className, modifier, prefix }), v, Object.fromEntries(Object.entries(v).map(([k, v]) => updateSelector(k, v))), ] } return [inWhere(k, { className, modifier, prefix }), v] } return [k, v] } return Object.fromEntries( Object.entries( merge( {}, ...Object.keys(config) .filter((key) => computed[key]) .map((key) => computed[key](config[key])), ...castArray(config.css || {}) ) ).map(([k, v]) => updateSelector(k, v)) ) } ``` -------------------------------- ### Undo typography styles with not-prose class Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Use the `not-prose` class to sandbox a block of markup so it does not inherit `prose` styles. Note that you cannot nest new `prose` instances within a `not-prose` block. Even when using a prefix for your utilities, `not-prose` should not have a prefix. ```html <article class="prose"> <h1>My Heading</h1> <p>...</p> <div class="not-prose"> <!-- Some example or demo that needs to be prose-free --> </div> <p>...</p> <!-- ... --> </article> ``` -------------------------------- ### Plugin function type declaration Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/types.md The plugin function type. Accepts an optional options object with className and target fields. Returns a Tailwind plugin object with a handler function. ```ts declare function plugin(options?: Partial<{ className: string; target: 'modern' | 'legacy' }>): { handler: () => void } ``` -------------------------------- ### Customize typography theme in Tailwind v3 JS config Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Shows how to customize the typography plugin in a Tailwind CSS v3 JavaScript config. Customizations go under `theme.extend.typography.<modifier>.css` and are deep-merged over the defaults. The `css` property can be an object or an array; nested syntax like `&:hover` is supported. ```js /** @type {import('tailwindcss').Config} */ module.exports = { theme: { extend: { typography: { DEFAULT: { css: { color: '#333', a: { color: '#3182ce', '&:hover': { color: '#2c5282' }, // nested syntax (&) supported }, }, }, // Overriding a size modifier: lg: { css: [ { h1: { fontWeight: '900' } }, { blockquote: { borderInlineStartWidth: '0.5rem' } }, ], }, }, }, }, plugins: [require('@tailwindcss/typography')], } ``` -------------------------------- ### isObject type guard Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/api-reference/utils.md Type guard that returns true for any non-null object, including arrays and class instances. Used by configToCss.updateSelector to detect nested rule objects. ```javascript function isObject(value) { return typeof value === 'object' && value !== null } ``` -------------------------------- ### Override Prose Max-Width with max-w-none Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/README.md Use this HTML snippet to override the baked-in `max-width` of prose content by adding `max-w-none` to the article. This is useful when you want the content to fill the full width of its container, as shown in a grid layout. ```html <div class="grid grid-cols-4"> <div class="col-span-1"> <!-- ... --> </div> <div class="col-span-3"> <article class="prose max-w-none">{{ markdown }}</article> </div> </div> ``` -------------------------------- ### Register @tailwindcss/typography in Tailwind CSS v4 Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Use this CSS to enable the typography plugin in a Tailwind CSS v4 project. The @plugin directive triggers Tailwind's inspection of the plugin's __isOptionsFunction static flag. ```css @import "tailwindcss"; @plugin "@tailwindcss/typography"; ``` -------------------------------- ### Typography theme TypeScript structure Source: https://github.com/tailwindlabs/tailwindcss-typography/blob/main/_autodocs/configuration.md Defines the TypeScript structure for the `typography` theme configuration. The `css` property can be a single CSS object or an array of CSS objects, and the modifier key determines the generated class name. ```ts type CSSObject = Record<string, string | number | CSSObject> // Tailwind CSS-in-JS rule object interface TypographyTheme { // 'DEFAULT' → base class `.${className}`; any other key → `.${className}-${key}` [modifier: string]: { css: CSSObject | CSSObject[] } } ```