Skip to content

ThemeScript

An inline script for the head that applies the stored theme and reader settings before the first paint, so a dark page never flashes light. themeScript() gives the same source as a string for heads that React does not render.

  • ThemeScript

PreviewLink to the section Preview

Live in all three themes. Everything here is interactive.

Light theme, ThemeScript

Rendered on the server as <ThemeScript />, it writes this into the head:

(function(){var r=document.documentElement;try{var t=localStorage.getItem("skribly-theme");if(t==="light"||t==="dark"||t==="contrast")r.setAttribute("data-theme",t)}catch(e){}try{var a=JSON.parse(localStorage.getItem("skribly-a11y")||"null")||{},c=r.classList;if(a.reduceMotion===true)c.add("a11y-reduce-motion");if(a.strongFocus===true)c.add("a11y-strong-focus");if(a.underlineLinks===true){c.add("a11y-underline-links");c.add("[&_a]:underline")}if([110,120,130,140].indexOf(a.textScale)>-1)r.style.fontSize=a.textScale+"%"}catch(e){}})();

Dark theme, ThemeScript

Rendered on the server as <ThemeScript />, it writes this into the head:

(function(){var r=document.documentElement;try{var t=localStorage.getItem("skribly-theme");if(t==="light"||t==="dark"||t==="contrast")r.setAttribute("data-theme",t)}catch(e){}try{var a=JSON.parse(localStorage.getItem("skribly-a11y")||"null")||{},c=r.classList;if(a.reduceMotion===true)c.add("a11y-reduce-motion");if(a.strongFocus===true)c.add("a11y-strong-focus");if(a.underlineLinks===true){c.add("a11y-underline-links");c.add("[&_a]:underline")}if([110,120,130,140].indexOf(a.textScale)>-1)r.style.fontSize=a.textScale+"%"}catch(e){}})();

High contrast theme, ThemeScript

Rendered on the server as <ThemeScript />, it writes this into the head:

(function(){var r=document.documentElement;try{var t=localStorage.getItem("skribly-theme");if(t==="light"||t==="dark"||t==="contrast")r.setAttribute("data-theme",t)}catch(e){}try{var a=JSON.parse(localStorage.getItem("skribly-a11y")||"null")||{},c=r.classList;if(a.reduceMotion===true)c.add("a11y-reduce-motion");if(a.strongFocus===true)c.add("a11y-strong-focus");if(a.underlineLinks===true){c.add("a11y-underline-links");c.add("[&_a]:underline")}if([110,120,130,140].indexOf(a.textScale)>-1)r.style.fontSize=a.textScale+"%"}catch(e){}})();

UsageLink to the section Usage

tsx
import { ThemeScript } from '@skribly/ui/theme'
tsx
<head>
  <ThemeScript nonce={nonce} />
</head>

<script is:inline set:html={themeScript()} />

Every label is a prop, so the app passes its own words in its own language. See no built-in text.

AccessibilityLink to the section Accessibility

  • Prevents a flash of the wrong theme and a jump in text size, both of which disturb readers with light sensitivity or low vision.
  • Accepts a nonce for a strict Content Security Policy.

This demo runs through axe in all three themes on every test run. See what the tests check.

Search this site

Arrows move through the results, Enter opens one, Esc closes. Ctrl K /