Dark mode, custom CSS & other options: Sharing my source code

Hi there!

I’ve been tinkering a bit with the main theme, including placing tags as a sort of categories, and I also managed to add a dark mode.
I’ve also added a JS option to respect French typography (including non-breaking spaces).

I thought it might be useful to someone.
What it looks like: https://einsof.space/
(there are still a few bugs to fix, but the main part is there).

So here are my CSS & JS modifications. You’re free to do whatever you like with them! Have fun!

JS:

// You can steal this script (and the CSS) if you want! Have a great hacking time!

const header = document.querySelector('header');
const divAbout = document.createElement('div');
divAbout.classList.add('about');
const a = document.createElement('a');
a.href = './exorde';
a.setAttribute('aria-label', 'about page');
const spanInfoOff = document.createElement('span');
spanInfoOff.innerHTML = '○';
a.appendChild(spanInfoOff);
const spanInfoOn = document.createElement('span');
spanInfoOn.innerHTML = '☢';
a.appendChild(spanInfoOn);
divAbout.appendChild(a);
header.appendChild(divAbout);

const button = document.createElement('button');
button.classList.add('drkbtn');
button.setAttribute('aria-label', 'dark mode');
const spanButtonOff = document.createElement('span');
spanButtonOff.innerHTML = '◑';
spanButtonOff.classList.add('dk');
button.appendChild(spanButtonOff);
const spanButtonOn = document.createElement('span');
spanButtonOn.innerHTML = '●';
spanButtonOn.classList.add('hide', 'lt');
button.appendChild(spanButtonOn);
header.appendChild(button);

const theme = localStorage.getItem("theme");
const darkButton = document.querySelector(".drkbtn");
const darkSymbol = document.querySelector(".drkbtn .dk");
const lightSymbol = document.querySelector(".drkbtn .lt");
let darkOn = false;

if (theme === 'dark') {
        darkSymbol.classList.add('hide');
        lightSymbol.classList.remove('hide');
        document.documentElement.setAttribute("data-theme", "dark");
        localStorage.setItem("theme", "dark");
        darkOn = true;
} else {
        darkSymbol.classList.remove('hide');
        lightSymbol.classList.add('hide');
        darkOn = false;
}

darkButton.addEventListener("click", (ev) => {
    darkButton.blur();
    ev.preventDefault();
    if (darkOn) {
        darkSymbol.classList.remove('hide');
        lightSymbol.classList.add('hide');
        document.documentElement.setAttribute("data-theme", "light");
        localStorage.setItem("theme", "light");
        
        darkOn = false;
    } else {
        darkSymbol.classList.add('hide');
        lightSymbol.classList.remove('hide');
        document.documentElement.setAttribute("data-theme", "dark");
        localStorage.setItem("theme", "dark");
        darkOn = true;
    }
});

document.addEventListener('DOMContentLoaded', function() {
    times = document.querySelectorAll('time');
    times.forEach((el) => {
        const date = el.dateTime; 
        const d = new Date(date);
        month = '' + (d.getMonth() + 1);
        day = '' + d.getDate();
        year = d.getFullYear();
        if (month.length < 2) month = '0' + month;
        if (day.length < 2) day = '0' + day;
        if (el.querySelector('.u-url')) {
            let link = el.querySelector('.u-url');
            link.innerHTML = [day, month, year].join('');
        } else {
            el.innerHTML = [day, month, year].join('');
        }
        if (!document.querySelector('body#post #title.dated + time')) {
            el.style.display = 'flex';
        }
    });
    
    if (document.querySelector('#paging')) {
    const paging = document.querySelector('#paging');
    const a = paging.querySelectorAll('a');
    a.forEach((el) => {
        if (el.innerHTML === '⇠ Older') {
            el.innerHTML = '🠔 précédents';
        }
        if (el.innerHTML === 'Newer ⇢') {
            el.innerHTML = 'suivants 🠖';
        }
    })
    }
    
    if (document.querySelector('#emailsub form')) {
        const formMsg = document.querySelector('#emailsub form p');
        formMsg.innerHTML = 'Pour recevoir les dernières parutions';
        const formEmail = document.querySelector('#emailsub form > input[type="email"]');
        formEmail.placeholder = 'ton@email.org';
        const formSubmit = document.querySelector('#emailsub form > input[type="submit"]');
        formSubmit.value = 'envoyer';
    }
    
    if (document.querySelector('#emailsub > p')) {
        const subMsg = document.querySelector('#emailsub > p:first-child');
        const link = subMsg.querySelector('a');
        subMsg.innerHTML = '';
        link.innerHTML = 'Se désinscrire de la newsletter.'
        subMsg.appendChild(link);
    }
    
    const frenchTypography = () => {
        
        function allReplace(string, object) {
            for (const o in object) {
                string = string.replace(new RegExp(o, 'g'), object[o]);
            }
            return string;
        };

        const paragraphs = document.querySelectorAll('p');
        paragraphs.forEach((el) => {
            const content = el.innerHTML;
            const listChars = {
                '\'': '’',
                ' »': '&nbsp;»',
                '« ': '«&nbsp;',
                ' :': '&nbsp;:',
                ' ;': '&nbsp;;',
                ' [?]': '&nbsp;?',
                ' !': '&nbsp;!',
            }
            const replace = allReplace( content, listChars );
            el.innerHTML = replace;
        });
    }
    
    frenchTypography();
    
}, false);



CSS:

/*
* Prefixed by https://autoprefixer.github.io
* PostCSS: v8.4.14,
* Autoprefixer: v10.4.7
* Browsers: last 4 version
*/

@import url('https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,400;0,700;1,400;1,700&family=Noto+Sans+Symbols+2&display=swap');

:root {
    --color-background: #ffffff;
    --color-foreground: #000000;
    --color-gray: #cccccc;
    --fonts-stack: "Archivo", "Noto Sans Symbols", "Noto Sans Symbols 2", "Helvetica Neue", Helvetica, Arial, sans-serif;
    --max-width: 50em;
    --margin: 1em;
    --gap: 1em;
    --width-container: 100vw;
    --column1: 5em;
    --column2: auto;
    --margin-l-container: 0;
    --margin-r-container: 0;
    --header-top-margin: 5em;
    --line-height: 1.3;
    --line-height-em: 1.3em;
    --border-size: 2px;
    --font-size: 1.2em;
}


@media (min-width: 50em) {
    :root {
    --width-container: 80vw;
    --column1: 20vw;
    --column2: 60vw;
    --margin-l-container: 0;
    --margin-r-container: 20vw;
    --font-size: 1.6em;
    --header-top-margin: 20vh;
    }
}

@media (min-width: 80em) {
    :root {
    --width-container: 80vw;
    --column1: 20vw;
    --column2: 60vw;
    --margin-l-container: 0;
    --margin-r-container: 20vw;
    --font-size: 2em;
    --header-top-margin: 20vh;
    }
}


[data-theme="dark"] {
    --color-background: #000000;
    --color-foreground: #ffffff;
}

body {
    font-family: var(--fonts-stack);
    width: calc(var(--width-container) - var(--margin) - var(--margin));
    margin: 0 var(--margin-r-container) 0 var(--margin-l-container);
    padding: var(--margin);
    font-size-adjust: unset;
    line-height: var(--line-height);
    font-size: var(--font-size);
    background: var(--color-background);
    color: var(--color-foreground);
}

body h1,
body h2,
body h3 {
    line-height: var(--line-height);
}

body h1 a, body header h2 a {
	color: var(--color-foreground);
	-webkit-transition: unset;
	-o-transition: unset;
	transition: unset;
	-webkit-transition-duration: 0;
	     -o-transition-duration: 0;
	        transition-duration: 0;
}

.hide {
    display: none;
}

#post nav a:not(.home):hover,
header nav a,
a {
    color: var(--color-foreground);
    text-decoration: none;
}

body#subpage .e-content > p:last-child .hashtag,
body#post .e-content > p:last-child .hashtag {
    text-decoration: none;
}

body#subpage .e-content > p:last-child .hashtag:focus,
body#subpage .e-content > p:last-child .hashtag:active,
body#subpage .e-content > p:last-child .hashtag:hover,
body#post .e-content > p:last-child .hashtag:focus,
body#post .e-content > p:last-child .hashtag:active,
body#post .e-content > p:last-child .hashtag:hover {
    -webkit-text-decoration-line:  line-through;
            text-decoration-line:  line-through;
    -webkit-text-decoration-style: solid;
            text-decoration-style: solid;
    -webkit-text-decoration-color: var(--color-foreground);
            text-decoration-color: var(--color-foreground);
    text-decoration-thickness: var(--border-size);
}

.e-content a:not(body#collection .hashtag) {
    -webkit-text-decoration-line:  underline;
            text-decoration-line:  underline;
    -webkit-text-decoration-style: solid;
            text-decoration-style: solid;
    -webkit-text-decoration-color: var(--color-foreground);
            text-decoration-color: var(--color-foreground);
    text-decoration-thickness: var(--border-size);
}

body h1 a, body header h2 a {
	color: unset;
	text-decoration: unset;
}

body #post article h1,
body#post article h1,
body #post article h2,
body#post article h2,
body #post article h3,
body#post article h3,
body #post article h4,
body#post article h4,
body #post article h5,
body#post article h5,
body #post article h6,
body#post article h6 {
	font-size: 1em;
    font-weight: normal;
    margin: var(--margin) 0;
}


body h1 a:focus,
body header h2 a:focus,
body h1 a:active,
body header h2 a:active,
body h1 a:hover,
body header h2 a:hover,
body#collection article .e-content a:focus,
body#collection article .e-content a:active,
body#collection article .e-content a:hover,
body#post article .e-content a:focus,
body#post article .e-content a:active,
body#post article .e-content a:hover,
a:focus,
a:active,
a:hover {
    -webkit-text-decoration-line:  line-through;
            text-decoration-line:  line-through;
    -webkit-text-decoration-style: solid;
            text-decoration-style: solid;
    -webkit-text-decoration-color: var(--color-foreground);
            text-decoration-color: var(--color-foreground);
    text-decoration-thickness: var(--border-size);
    color: var(--color-foreground);
  
}

a.hashtag:hover span + span {
	text-decoration: unset;
}

a.hashtag span:first-child {
	color: var(--color-foreground);
	margin-right: 0;
	font-size: 1em;
	text-decoration: none;
}

body#post header,
body#subpage header,
body#collection header {
  margin: var(--header-top-margin) auto 0;
  padding: 0;
  width: 100%;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: justify;
      -ms-flex-pack: justify;
          justify-content: space-between;
  max-width: var(--max-width);
  -webkit-box-align: start;
      -ms-flex-align: start;
          align-items: flex-start;
}

body#collection #wrapper,
body#subpage #wrapper {
	margin-left: auto;
	margin-right: auto;
	max-width: var(--max-width);
}


header .drkbtn {
    -webkit-box-ordinal-group: 4;
        -ms-flex-order: 3;
            order: 3;
    margin: 0;
    background: none;
	color: inherit;
	border: none;
	padding: 0;
	font: inherit;
	cursor: pointer;
	outline: inherit;
}

.drkbtn:active,
.drkbtn:focus,
.drkbtn:hover {
    cursor: pointer;
}


header .drkbtn:focus span:not(.hide),
header .drkbtn:active span:not(.hide),
header .drkbtn:hover span:not(.hide) {
    display: none;
}

header .drkbtn:focus span.hide,
header .drkbtn:active span.hide,
header .drkbtn:hover span.hide {
    display: inline;
}


body header .about a,
header .about a {
    text-decoration: none;
    font-size: 1em;
    margin-right: 0.3em;
}

@media (min-width: 50em) {
    body header .about a,
    header .about a {
        text-decoration: none;
        font-size: 1em;
        margin-right: 0;
    }
}

body header .about a:focus,
header .about a:active,
header .about a:hover {
    text-decoration: none;
}

.about a span:nth-of-type(2) {
    display: none;
    text-decoration: none;
    font-size: 1.05em;
}

.about a:focus span:nth-of-type(2),
.about a:active span:nth-of-type(2),
.about a:hover span:nth-of-type(2) {
    display: inline;
}

.about a:focus span:nth-of-type(1),
.about a:active span:nth-of-type(1),
.about a:hover span:nth-of-type(1) {
    display: none;
}

#post nav a:not(.home):hover,
header nav a, a {
	color: var(--color-foreground);
	text-decoration: none;
}

body header h1 {
	margin: 0 var(--gap) 0 0;
	font-size: 1em;
	-webkit-box-flex: 0;
	    -ms-flex: 0 0 var(--column1);
	        flex: 0 0 var(--column1);
	display: -webkit-box;
	display: -ms-flexbox;
	display: flex;
	line-height: unset;
	-webkit-box-pack: end;
	    -ms-flex-pack: end;
	        justify-content: flex-end;
	font-weight: normal;
}

body#post header nav .pinned,
body#subpage header nav,
body#collection header nav {
	display: none;
}

header .about {
	color: var(--color-foreground);
	font-size: 1em;
	margin-top: 0;
	line-height: inherit;
	-webkit-box-ordinal-group: 3;
	    -ms-flex-order: 2;
	        order: 2;
	margin: 0;
	-webkit-box-flex: 1;
	    -ms-flex: 1 1 auto;
	        flex: 1 1 auto;
	margin: 0;
	display: -webkit-box;
	display: -ms-flexbox;
	display: flex;
	line-height: unset;
	-webkit-box-pack: end;
	    -ms-flex-pack: end;
	        justify-content: flex-end;
	font-size: 1em;
	height: var(--line-height-em);
}

body#post header h1,
body#subpage header h1 {
	font-size: 1em;
}

body#subpage section#wrapper h1 {
    font-size: 1em;
    font-weight: normal;
    letter-spacing: unset;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-pack: end;
        -ms-flex-pack: end;
            justify-content: flex-end;
    width: var(--column1);
    margin: 0 0 var(--margin);
    padding: 0;
}


body#subpage section#wrapper h1::before {
    content: '#';
}

body footer hr {
    opacity: 0;
    margin: calc(2 * var(--margin)) 0;
    height: 0px;
    background: var(--color-background);
    max-width: 0;
    text-align: center;
}

body footer nav {
    display: none;
}

#post article.norm,
.font.norm,
body#collection article.norm,
body#subpage article.norm,
input#title.norm,
pre.norm,
span.norm,
textarea.norm {
	font-family: var(--fonts-stack);
}

body#post article#post-body,
body#collection #wrapper article,
body#subpage #wrapper article {
    margin-bottom: calc(1 * var(--margin));
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
   line-height: var(--line-height);
}

body#post article#post-body {
    margin-top: var(--margin);
    font-size: 1em;
}

body#post article#post-body .e-content {
    margin-left: var(--gap);
     -webkit-box-flex: 1;
         -ms-flex: 1 1 var(--column2);
             flex: 1 1 var(--column2);
}

body#post article#post-body .dt-published,
body#post article#post-body #title {
    font-size: 1em;
    font-weight: normal;
    -webkit-box-flex: 0;
        -ms-flex: 0 0 var(--column1);
            flex: 0 0 var(--column1);
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-pack: end;
        -ms-flex-pack: end;
            justify-content: flex-end;  
}

body#collection article, body#subpage article {
	padding-top: 0;
	padding-bottom: 0;
}

#post .alert, #post article, body#collection article, body#subpage #wrapper h1, body#subpage article, pre {
	max-width: unset;
	margin: 0;
}

#wrapper.archive ul, .hljs, article, pre {
	padding: 0;
}

body#collection #wrapper h2,
body#subpage #wrapper h2 {
	margin-top: 0;
	margin-bottom: 0;
	margin: 0 var(--gap) 0 0;
	font-size: 1em;
	-webkit-box-flex: 0;
	    -ms-flex: 0 0 var(--column1);
	        flex: 0 0 var(--column1);
	display: -webkit-box;
	display: -ms-flexbox;
	display: flex;
	-webkit-box-pack: end;
	    -ms-flex-pack: end;
	        justify-content: flex-end;
	position: relative;
	font-weight: normal;
}

.post-title a:visited {
	color: var(--color-foreground);
}

body#collection #wrapper h2 + .authors + time,
body#collection #wrapper h2 + time,
body#subpage #wrapper h2 + .authors + time,
body#subpage #wrapper h2 + time {
	display: none;
	margin-top: 0;
	margin-bottom: 0;
}

body#post #title.dated + time {
    display: none;
}

body#collection #wrapper h2 .action,
body#subpage #wrapper h2 .action {
    position: absolute;
    z-index: 1;
    background: var(--color-gray);
    font-size: 0.7em;
    left: 0;
    font-family: var(--fonts-stack);
    margin: 0;
    font-weight: normal;
}

body#collection #wrapper h2 .action:nth-of-type(1),
body#subpage #wrapper h2 .action:nth-of-type(1) {
    top: calc(0 * var(--line-height-em));
}
body#collection #wrapper h2 .action:nth-of-type(2),
body#subpage #wrapper h2 .action:nth-of-type(2) {
    top: calc(0 * var(--line-height-em));
    left: 6em;
}
body#collection #wrapper h2 .action:nth-of-type(3),
body#subpage #wrapper h2 .action:nth-of-type(3) {
    top: calc(1 * var(--line-height-em));
}
body#collection #wrapper h2 .action:nth-of-type(4),
body#subpage #wrapper h2 .action:nth-of-type(4) {
    top: calc(1 * var(--line-height-em));
    left: 6em;
}
body#collection #wrapper h2 .action:nth-of-type(5),
body#subpage #wrapper h2 .action:nth-of-type(5) {
    top: calc(2 * var(--line-height-em));
}
body#collection #wrapper h2 .action:nth-of-type(6),
body#subpage #wrapper h2 .action:nth-of-type(6) {
    top: calc(2 * var(--line-height-em));
    left: 6em;
}

body#collection #wrapper .authors, body#collection #wrapper time, body#subpage #wrapper .authors, body#subpage #wrapper time {
	font-size: 1em;
}

.post-title time, .post-title time a:link, .post-title time a:visited, .post-title + .time {
	color: var(--color-foreground);
	font-weight: normal;
}

.e-content {
    position: relative;
}

body#collection article p,
body#post article p,
body#subpage article p {
	line-height: var(--line-height);
	margin: 0 0 var(--margin);
	-webkit-hyphens: auto;
	    -ms-hyphens: auto;
	        hyphens: auto;
}

.e-content > p:last-child {
	position: absolute;
	top: var(--line-height-em);
	left: calc(-1 * var(--gap));
	-webkit-transform: translateX(-100%);
	    -ms-transform: translateX(-100%);
	        transform: translateX(-100%);
}

.e-content > p:nth-last-child(2) {
    margin-bottom: 0;
}


#beta, .content-container {
	max-width: unset;
	margin: 0;
	font-size: 1em;
}

.views {
    position: fixed;
    top: 0;
    right: 1em;
}

.xtra-feature {
    position: fixed;
    top: 0;
    right: 5em;
}


.unpin {
    position: fixed;
    top: 0;
    right: 7em;
}

body#post header, body#subpage header {
	padding: 0;
	opacity: 1;
	-webkit-filter: unset;
	        filter: unset;
	-webkit-transition: unset;
	-o-transition: unset;
	transition: unset;
}

#post article .authors,
#post article time.dt-published,
#subpage article .authors,
#subpage article time.dt-published,
time {
    display: none;
	color: var(--color-foreground);
	margin-bottom: 0;
}

body#collection #paging, body#subpage #paging {
	overflow: visible;
	padding: 0;
	margin-left: calc(var(--column1) + var(--gap));
}

#paging a:hover {
    -webkit-text-decoration-line: underline;
            text-decoration-line: underline;
}

#emailsub {
    width: calc(100% - var(--margin-r-container) - var(--margin));
    margin: calc(3 * var(--margin)) auto  0 calc(var(--column1) + var(--gap));
}

#emailsub p {
    text-align: left;
}

a.btn, button, input, select.inputform, textarea.inputform {
	padding: 0;
	font-family: var(--fonts-stack);
	font-size: 100%;
	border-radius: 0;
}

#emailsub form {
    text-align: left;
}

input[type="email"], input[type="number"], input[type="password"], input[type="tel"], input[type="text"] {
	border: var(--border-size) solid var(--color-foreground);
    border-radius: 0;
    width: 100%;
    -webkit-box-sizing: border-box;
            box-sizing: border-box;
    background: var(--color-background);
    color: var(--color-foreground);
}

a.btn.cta, a.btn.gentlecta, a.btn.submit, a.btn[type="submit"], button.cta, button.gentlecta, button.submit, button[type="submit"], input.cta, input.gentlecta, input.submit, input[type="submit"], select.inputform.cta, select.inputform.gentlecta, select.inputform.submit, select.inputform[type="submit"], textarea.inputform.cta, textarea.inputform.gentlecta, textarea.inputform.submit, textarea.inputform[type="submit"] {
	border: var(--border-size) solid var(--color-foreground);
	background: var(--color-background);
	color: var(--color-foreground);
    border-radius: 0;
	-webkit-transition: 0;
	-o-transition: 0;
	transition: 0;
    margin-left: 0;
    margin-top: var(--margin);
    width: 100%;
}

@media (min-width: 50em) {
    
#emailsub form {
    text-align: left;
}

input[type="email"], input[type="number"], input[type="password"], input[type="tel"], input[type="text"] {
	border: var(--border-size) solid var(--color-foreground);
    border-radius: 0;
    width: 60%;
}

a.btn.cta, a.btn.gentlecta, a.btn.submit, a.btn[type="submit"], button.cta, button.gentlecta, button.submit, button[type="submit"], input.cta, input.gentlecta, input.submit, input[type="submit"], select.inputform.cta, select.inputform.gentlecta, select.inputform.submit, select.inputform[type="submit"], textarea.inputform.cta, textarea.inputform.gentlecta, textarea.inputform.submit, textarea.inputform[type="submit"] {
	border: var(--border-size) solid var(--color-foreground);
	background: var(--color-background);
	color: var(--color-foreground);
    border-radius: 0;
	-webkit-transition: 0;
	-o-transition: 0;
	transition: 0;
    margin-left: auto;
    margin-top: var(--margin);
    width: 30%;
}
}

#emailsub form > input[type="submit"] {
    -webkit-transition: 0;
    -o-transition: 0;
    transition: 0;
    cursor: pointer;
}

#emailsub form > input[type="submit"]:focus,
#emailsub form > input[type="submit"]:active,
#emailsub form > input[type="submit"]:hover {
    color: var(--color-background);
    background: var(--color-foreground);
    -webkit-transition: 0;
    -o-transition: 0;
    transition: 0;
}


#subscribe-btn {
	margin-left: auto;
}

a.btn, button, input, select.inputform, textarea.inputform {
	padding: .5em;
	font-family: var(--fonts-stack);
	font-size: 100%;
	border-radius: 0;
}

body#collection .flash {
    text-align: center;
    margin: 0 0 var(--margin) calc(var(--column1) + var(--gap));
    overflow: hidden;
}
.alert.success {
  color: var(--color-foreground);
  background-color: var(--color-background);
  border: var(--border-size) solid var(--color-foreground);
}
.alert {
  padding: 1em;
  margin-bottom: 0;
  border: var(--border-size) solid var(--color-foreground);
  border-radius: 0;
}

body#post article#post-body.norm.error-page {
    display: block;
    font-size: 1em;
}


body#post article#post-body.norm.error-page .e-content {
    text-align: left;
    margin-left: calc(var(--column1) + var(--gap));
}


body#post article#post-body.norm.error-page .e-content > p:last-child {
	position: relative;
    top: unset;
    left: unset;
    -webkit-transform: unset;
        -ms-transform: unset;
            transform: unset;
}

.error-page p.msg {
	font-size: 1em;
}

3 Likes

Hi !
One suggestion. Detect on loading whether browser or OS theme is already a dark theme. If so, load the dark key into the localStorage.