mrkeyoor.com_
Sat 08 Aug 17:40 UTC
npmWeb Frontendupdated 08 Aug 2026

react-syntax-highlighter

React component that turns source code into a highlighted React element tree using either highlight.js through lowlight or Prism through refractor. It ships JavaScript theme objects, line numbering, per-line props, custom renderers, and full, light, and asynchronous builds. Unlike highlighters that inject an HTML string after mount, it builds React nodes from a syntax tree, so updates stay inside React's rendering model and do not require dangerouslySetInnerHTML.

Verdict

A capable choice for interactive React code blocks, especially when per-line rendering matters. Do not accept the default full bundle casually; most products should use a light build or highlight code before it reaches the browser.

API stability4/5The central component contract has stayed recognizable across releases: language, style, children, line numbers, line wrapping, custom tags, and renderer hooks are all documented together. Version 16.1.1 did include an ESM path correction, and consumers still choose among several build-specific exports, so import paths are a more likely source of breakage than component props.
Docs3/5The README documents every important prop and includes separate examples for highlight.js, Prism, light builds, async builds, and custom languages. It also states real tradeoffs such as the temporary unhighlighted async state. The presentation is dated, the demo is separate, TypeScript guidance is only an install command, and versioned migration guidance is thin.
Maintenance3/5The repository is not archived, version 16.1.1 was released and pushed on February 26, 2026, and that release fixed a concrete ESM packaging problem. Activity is much quieter than the package's download volume might suggest, while the repository still has a substantial public backlog of issues and pull requests, so fixes may not arrive quickly.
Ecosystem4/5The package recorded 7,286,223 downloads in the measured week and supports both of the dominant browser grammar ecosystems through lowlight and refractor. Its separate virtualized renderer, broad style catalog, custom language registration, and React-friendly syntax tree output make it easy to fit into existing code viewers, although TypeScript types remain external.

Use it if

  • You need highlighted code blocks whose lines can receive React props for diffs, selections, annotations, or click handling
  • You want a choice between highlight.js language detection and Prism grammar coverage behind nearly the same component API
  • You need inline JavaScript themes and do not want to load a separate syntax-highlighting stylesheet
  • You will use a light build and explicitly register the few languages your product actually displays
Skip it if

Setup reality

The basic install is one runtime package, but a TypeScript project is expected to add @types/react-syntax-highlighter separately. The default export uses highlight.js; JSX and other Prism-oriented grammars usually mean importing Prism as the component and a theme from dist/esm/styles/prism. That path choice matters because highlight.js styles and Prism styles are not interchangeable. The normal build includes a broad language set and measured at about 520.2 KB gzipped in the registry size check, so production apps should usually choose Light or PrismLight, import each grammar from dist/esm/languages, and call registerLanguage before rendering. Light builds do not include a default theme. Async variants reduce initial work but require a bundler that supports dynamic import, and the README says code appears temporarily without highlighting while language chunks load. Line-level styling also has a hidden switch: lineProps does nothing useful until wrapLines is true. Setting useInlineStyles to false changes output to class names, which means you must supply compatible CSS yourself. The package requires Node 16.20.2 or newer for installation tooling and has React as a peer dependency, while React Native needs a different package.

Patterns

Render a highlight.js code blockhighlight-javascript

import SyntaxHighlighter from 'react-syntax-highlighter';
import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs';

export function CodeBlock({ code }) {
  return (
    <SyntaxHighlighter language="javascript" style={docco}>
      {code}
    </SyntaxHighlighter>
  );
}

The default component uses highlight.js through lowlight, so import a theme from the hljs style directory.

Use Prism for JSXhighlight-jsx-with-prism

import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';

<SyntaxHighlighter language="jsx" style={vscDarkPlus}>
  {source}
</SyntaxHighlighter>

Prism themes must come from the prism style directory; mixing a Prism component with an hljs theme produces the wrong token keys.

Keep the bundle focused with Lightregister-light-language

import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
import javascript from 'react-syntax-highlighter/dist/esm/languages/hljs/javascript';
import docco from 'react-syntax-highlighter/dist/esm/styles/hljs/docco';

SyntaxHighlighter.registerLanguage('javascript', javascript);

export const Block = ({ code }) => (
  <SyntaxHighlighter language="javascript" style={docco}>{code}</SyntaxHighlighter>
);

Light has no default style or automatic grammar catalog; every used language must be imported and registered.

Register JSX with PrismLightregister-prism-language

import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
import jsx from 'react-syntax-highlighter/dist/esm/languages/prism/jsx';
import prism from 'react-syntax-highlighter/dist/esm/styles/prism/prism';

SyntaxHighlighter.registerLanguage('jsx', jsx);

<SyntaxHighlighter language="jsx" style={prism}>{source}</SyntaxHighlighter>

Register the grammar before the component renders, preferably once in a module rather than inside a React component.

Defer grammar loadingload-async-build

import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';

<SyntaxHighlighter language="typescript" style={atomDark} showLineNumbers>
  {source}
</SyntaxHighlighter>

The bundler must support dynamic import, and the code may render briefly without highlighting while chunks load.

Start line numbers at an offsetshow-line-numbers

<SyntaxHighlighter
  language="python"
  style={theme}
  showLineNumbers
  startingLineNumber={40}
>
  {source}
</SyntaxHighlighter>

startingLineNumber has visible effect only when showLineNumbers is enabled.

Mark changed linesstyle-specific-lines

const changed = new Set([3, 4]);

<SyntaxHighlighter
  language="diff"
  style={theme}
  wrapLines
  lineProps={(line) => ({
    style: changed.has(line) ? { background: '#3b1f2b' } : undefined,
  })}
>
  {source}
</SyntaxHighlighter>

lineProps requires wrapLines because each source line needs its own wrapper element.

Wrap long source lineswrap-long-lines

<SyntaxHighlighter
  language="json"
  style={theme}
  wrapLongLines
  customStyle={{ maxWidth: '100%', margin: 0 }}
>
  {json}
</SyntaxHighlighter>

wrapLongLines changes white-space to pre-wrap, which improves narrow layouts but no longer preserves horizontal code alignment.

Use external highlight.js CSSuse-css-classes

import 'highlight.js/styles/github-dark.css';

<SyntaxHighlighter language="shell" useInlineStyles={false}>
  {command}
</SyntaxHighlighter>

Disabling inline styles emits class names, but the component does not load the CSS file for you.

Replace the outer and code tagscustomize-tags

<SyntaxHighlighter
  language="css"
  style={theme}
  PreTag="div"
  CodeTag="span"
  codeTagProps={{ className: 'source-code' }}
>
  {css}
</SyntaxHighlighter>

Changing semantic tags can hurt accessibility, so keep a code role or equivalent structure when the content is source code.

Pass attributes to the outer elementadd-pre-attributes

<SyntaxHighlighter
  language="sql"
  style={theme}
  aria-label="SQL query"
  data-testid="query-source"
  customStyle={{ borderRadius: 8 }}
>
  {sql}
</SyntaxHighlighter>

Unknown component props are spread onto the outer pre element; codeTagProps targets the inner code element instead.

Check the bundled language listinspect-supported-languages

import SyntaxHighlighter from 'react-syntax-highlighter';

const canHighlight = SyntaxHighlighter.supportedLanguages.includes(language);

<SyntaxHighlighter language={canHighlight ? language : 'text'}>
  {source}
</SyntaxHighlighter>

Light builds contain only registered grammars, so application code should maintain its own allowed-language list there.

Alternatives

PackageRegistryPick it when
prism-react-renderernpmYou want a smaller React-focused Prism renderer and are comfortable owning the code-block markup
react-code-blocksnpmYou want batteries-included code blocks with copy controls and themes more than low-level rendering control
lowlightnpmYou need a highlight.js syntax tree but can render it yourself or process it during a Markdown build