# Theme Switcher in Nginx

DevFeed: [Theme Switcher in Nginx](<https://devfeed.tech/articles/theme-switcher-in-nginx-30839.md>)

Original publisher: [Read original article](<https://hookrace.net/blog/theme-switcher-nginx/>)

Published: 2019-01-08T23:00:00Z

Content type: tutorial

Language: en

Sources: [Dennis Felsing](<https://devfeed.tech/sources/dennis-felsing.md>)

Topics: [Dark Mode](<https://devfeed.tech/topics/dark-mode.md>), [nginx](<https://devfeed.tech/topics/nginx.md>), [CSS](<https://devfeed.tech/topics/css.md>), [modern web development](<https://devfeed.tech/topics/modern-web-development.md>)

Tags: [color](<https://devfeed.tech/tags/color.md>), [css](<https://devfeed.tech/tags/css.md>), [nginx](<https://devfeed.tech/tags/nginx.md>), [performance](<https://devfeed.tech/tags/performance.md>)

## AI overview

This article explains a dark-mode theme switcher implemented with static HTML, a cookie, CSS, and Nginx. It replaces a JavaScript-based switcher with server-side CSS selection, avoiding rendering flicker. The article also describes an inline CSS alternative and notes that the approach prevents the CSS file from being cached.

## Source excerpt

Some people really liked the dark DDNet theme for Halloween by Soreu, so we decided to keep it possible to use the default bright or the dark theme. Thanks to xse we got a JavaScript based theme switcher. After some improvements I finally I switched it away from JavaScript entirely and finally am also using it on this blog with an OLED friendly dark theme. The final result is quite simple, and only requires static HTML, a cookie for the theme and Nginx for setting and returning the correct CSS file for it. You can try it out by clicking on the Switch Theme button at the top of this page, which just redirects you to /switch-theme/. Doing the CSS decision server-side instead of in JavaScript has the advantage that you don't get any flicker on rendering, no matter what theme you chose. The entire nginx logic is: location /switch-theme/ { if ($http_cookie ~* "user_theme=/public/css-dark.css") { add_header Set-Cookie "user_theme=/public/css-empty.css;path=/;domain=hookrace.net"; return 302 $http_referer; } add_header Set-Cookie "user_theme=/public/css-dark.css;path=/;domain=hookrace.net"; return 302 $http_referer; } location /public/css-dark.css { if ($http_cookie ~* "user_theme=/public/css-dark.css") { return 302 /public/css/css-dark.css; } return 302 /public/css/css-empty.css; } Note that the /switch-theme/ location sends the user back to the $http_referer. /public/css-dark.css is statically included on each page, but what it does depends on the cookie value. The 302 Moved Temporarily response makes the client send another request, adding another roundtrip to the page rendering. If the CSS is small enough you can just pull it directly into the Nginx config: location /public/css-dark.css { if ($http_cookie ~* "user_theme=/public/css-dark.css") { return 200 "body {color: #fff; background-color: #000;} .page-title, .post-title, .post-title a, h1, h2, h3, h4, h5, h6 {color: #ccc;} .masthead-title a {color: #bbb;}"; } return 200 ""; } One side effect of this entire approach