Using color-scheme and light-dark() to implement dark mode (#154)

* Lint fixes.

* Implement light-dark().

* Lint css with biome, remove stylelint.

* Biome lint fixes.

* Dark mode adjustments.

* Style bug fixes.

* Colour adjustments.

* Move header and footer styles to base.

* Site header adjustments.

* Removing jQuery and umbrella libs. They where great but not needed anymore.

* Add colorScheme to optionally lock light/dark.

* Update README.

* Biome adjustments.
This commit is contained in:
Fredrik Jonsson 2026-05-28 08:18:04 +02:00 • committed by GitHub
commit 16c47eea9d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 276 additions and 2130 deletions

View file

@ -1,8 +1,8 @@
/* Anchor */
.anchor {
--anchor-gap: .5rem;
--anchor-opacity: .4;
--anchor-gap: 0.5rem;
--anchor-opacity: 0.4;
display: grid;
grid-template-columns: auto auto;

View file

@ -33,32 +33,3 @@
.box--gutter {
padding-inline: var(--gutters);
}
.box--inverted {
background: var(--color-border);
color: var(--color-text-bg);
/* Make sure headings etc. also gets inverted. */
* {
color: var(--color-text-bg);
}
a {
&:link {
color: var(--color-link-inverted);
}
&:visited {
color: var(--color-link-visited-inverted);
}
&:hover,
&:focus {
color: var(--color-link-hover-inverted);
}
&:active {
color: var(--color-link-active-inverted);
}
}
}

View file

@ -1,5 +1,3 @@
/* stylelint-disable no-duplicate-selectors */
/* Button */
.button,
@ -11,7 +9,7 @@
text-decoration: none;
text-align: center;
width: fit-content;
padding: .2rem 1rem;
padding: 0.2rem 1rem;
/* Improve usability and consistency of cursor style between image-type `input` and others. */
cursor: pointer;
@ -36,7 +34,7 @@
.button--small {
font-size: var(--fs-xs);
padding: .2rem .75rem;
padding: 0.2rem 0.75rem;
}
.button--alt {
@ -65,7 +63,7 @@
&:active {
color: var(--color-button-text);
background: var(--color-success);
}
}
}
.button--decline {
@ -98,18 +96,19 @@ other variations. */
[type='button'],
[type='submit'] {
&:disabled {
background-color: var(--color-grey-200);
border: 1px solid var(--color-button-disabled);
color: var(--color-disabled);
background-color: var(--color-disabled-alt);
border: 1px solid var(--color-disabled);
background-image: none;
text-shadow: none;
cursor: default;
color: var(--color-button-disabled);
&:hover,
&:focus,
&:active {
/* Override any link underlines and color changes. */
color: var(--color-button-disabled);
color: var(--color-disabled);
background-color: var(--color-disabled-alt);
text-decoration: none;
}
}
@ -127,7 +126,7 @@ textarea {
@media (min-width: 666px) {
input:only-of-type {
&:has(+ [type='submit']) {
margin-inline-end: .5rem;
margin-inline-end: 0.5rem;
}
}
}

View file

@ -42,27 +42,3 @@ A simple cards style. */
.card--gutter {
padding-inline: var(--gutters);
}
.card--inverted {
background: var(--color-border);
color: var(--color-text-bg);
a {
&:link {
color: var(--color-link-inverted);
}
&:visited {
color: var(--color-link-visited-inverted);
}
&:hover,
&:focus {
color: var(--color-link-hover-inverted);
}
&:active {
color: var(--color-link-active-inverted);
}
}
}

View file

@ -4,7 +4,7 @@
display: flex;
flex-flow: wrap;
justify-content: center;
gap: .5rem;
gap: 0.5rem;
position: sticky;
bottom: 0;
width: 100%;
@ -19,7 +19,7 @@
.cookieconsent__actions {
display: flex;
gap: .5rem;
gap: 0.5rem;
}
&[hidden] {

View file

@ -1,13 +1,13 @@
.disabled {
/* Re-set default cursor for disabled elements. */
cursor: default;
color: var(--color-button-disabled);
color: var(--color-disabled);
&:hover,
&:focus,
&:active {
/* Override any link underlines and color changes. */
color: var(--color-button-disabled);
color: var(--color-disabled);
text-decoration: none;
}
}

View file

@ -1,5 +1,5 @@
.flex-inline {
--flex-inline-gap: .5rem;
--flex-inline-gap: 0.5rem;
display: flex;
flex-wrap: wrap;

View file

@ -1,11 +0,0 @@
/* Branding footer */
.footer {
padding-block: var(--gutters);
background-color: var(--color-footer-bg);
text-align: center;
p {
margin: 0;
}
}

View file

@ -1,53 +0,0 @@
/* Branding header */
.header {
--header-gap: var(--spacing-s);
padding-block: min(var(--gutters), var(--spacing-m));
display: flex;
flex-direction: column;
gap: var(--header-gap);
background-color: var(--color-header-bg);
@media (min-width: 666px) {
flex-direction: row;
align-items: center;
}
}
/* Wrapping link for logo. */
.header__logo {
width: fit-content;
}
/* Logo image. */
.header__logo-image {
vertical-align: bottom;
}
/* The name of the website. */
.header__site-name {
margin: 0;
line-height: 1;
}
/* The link around the name of the website. */
.header__site-link {
&:link,
&:visited {
color: var(--color-text);
text-decoration: none;
}
&:hover,
&:focus {
text-decoration: underline;
}
}
/* Wrapper for any blocks placed in the header region. */
.header__region {
@media (min-width: 666px) {
margin-inline-start: auto;
}
}

View file

@ -0,0 +1,45 @@
.htmx-indicator {
position: fixed;
inset: 0;
width: 100%;
height: 4px;
background: linear-gradient(
90deg,
transparent,
var(--color-accent),
transparent,
var(--color-accent),
transparent
);
opacity: 0;
visibility: hidden;
&.htmx-request {
opacity: 1;
visibility: visible;
animation:
--fadein 2s linear forwards,
--slide 1.2s ease-in-out infinite;
}
}
@keyframes --slide {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
@keyframes --fadein {
0% {
opacity: 0;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}

View file

@ -10,7 +10,7 @@
&:focus-visible,
&:hover {
.icon-link {
opacity: .3;
opacity: 0.3;
&:focus-visible,
&:hover {

View file

@ -1,33 +1,42 @@
/* Messages */
.message {
padding: .5rem;
--color-message: var(--color-grey-600);
--color-message-text: light-dark(
oklch(from var(--color-message) l c h),
oklch(from var(--color-message) 100% 0.03 h)
);
--color-message-bg: light-dark(
oklch(from var(--color-message) 100% 0.03 h),
oklch(from var(--color-message) calc(l + 0.07) c h)
);
--color-message-border: light-dark(
oklch(from var(--color-message) calc(l + 0.2) c h),
oklch(from var(--color-message) calc(l - 0.07) c h)
);
padding: 0.5rem;
color: var(--color-message-text);
background-color: var(--color-message-bg);
outline-color: var(--color-message-border);
outline-width: 2px;
outline-style: solid;
width: 95%;
&.success {
background-color: var(--color-success-bg);
color: var(--color-success);
outline-color: var(--color-success);
&.info {
--color-message: var(--color-info);
}
&.info {
background-color: var(--color-info-bg);
color: var(--color-info);
outline-color: var(--color-info);
&.success {
--color-message: var(--color-success);
}
&.warning {
background-color: var(--color-warning-bg);
color: var(--color-warning);
outline-color: var(--color-warning);
--color-message: var(--color-warning);
}
&.error {
background-color: var(--color-error-bg);
color: var(--color-error);
outline-color: var(--color-error);
--color-message: var(--color-error);
}
}
@ -37,6 +46,6 @@
@keyframes --outline-highlight {
50% {
outline-width: .3rem;
outline-width: 0.3rem;
}
}

View file

@ -5,7 +5,7 @@ is available. */
.pagination,
.pager {
--flex-inline-gap: .5rem;
--flex-inline-gap: 0.5rem;
display: flex;
flex-wrap: wrap;
@ -31,9 +31,6 @@ is available. */
padding-inline: 2px;
}
.page-item {
}
.active {
font-weight: var(--fw-bold);
}
@ -42,13 +39,13 @@ is available. */
.page-link {
/* Re-set default cursor for disabled elements. */
cursor: default;
color: var(--color-button-disabled);
color: var(--color-disabled);
&:hover,
&:focus,
&:active {
/* Override any link underlines and color changes. */
color: var(--color-button-disabled);
color: var(--color-disabled);
text-decoration: none;
}
}

View file

@ -1,8 +1,8 @@
.zebra-table {
--table-cell-padding: .5rem;
--table-cell-padding: 0.5rem;
@media (max-width: 666px) {
--table-cell-padding: .3rem;
--table-cell-padding: 0.3rem;
}
th,
@ -30,7 +30,7 @@
}
.responsive-table {
--table-gap: .5rem;
--table-gap: 0.5rem;
@media (max-width: 666px) {
th {