-
|
In my website (in development), the code block is still dark in light mode. Tried solutions
expressiveCode({ Current problematic codeastro.config.mjs// @ts-check
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import sitemap from '@astrojs/sitemap';
import icon from 'astro-icon';
import yaml from '@rollup/plugin-yaml'
import { DEFAULT_LOCALE_SETTING, LOCALES_SETTING } from './src/i18n/locales';
import { remarkTocTrigger } from './src/plugins/remark-toc-trigger.mjs';
import expressiveCode from 'astro-expressive-code';
// https://astro.build/config
export default defineConfig({
// Sitemap
site: 'https://aosankaku.net',
// Integrations
integrations: [react(), icon(), sitemap({
/*
i18n: {
defaultLocale: 'ja',
locales: {
ja: 'ja-JP',
en: 'en-US',
}
}
*/
}), expressiveCode({
themes: ['one-dark-pro', 'one-light'],
useDarkModeMediaQuery: false, // disable auto media query
})],
// i18n
i18n: {
defaultLocale: DEFAULT_LOCALE_SETTING,
locales: Object.keys(LOCALES_SETTING),
routing: {
prefixDefaultLocale: true,
redirectToDefaultLocale: false,
},
},
// Path
trailingSlash: 'always',
markdown: {
remarkPlugins: [remarkTocTrigger],
gfm: true,
},
// Vite
vite: {
plugins: [yaml()],
ssr: {
noExternal: ['styled-components']
},
server: {
watch: {
ignored: ['**/node_modules/**', '**/.git/**'],
}
},
},
});Layout.astro---
import {
useTranslations,
getLocalePaths,
LOCALES,
DEFAULT_LOCALE,
type Lang,
} from "@/types/i18n";
import { SITE_TITLE, SITE_DESCRIPTION } from "@/consts";
const t = useTranslations(Astro.currentLocale as Lang);
const langs = Object.keys(LOCALES);
const defaultLocale = DEFAULT_LOCALE;
---
<!doctype html>
<html lang={DEFAULT_LOCALE}>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="sitemap" href="/sitemap-index.xml" />
<meta name="generator" content={Astro.generator} />
<slot name="head" slot="head" />
<script is:inline>
const getThemePreference = () => {
// 1. Check for saved preference in localStorage
if (
typeof localStorage !== "undefined" &&
localStorage.getItem("theme")
) {
return localStorage.getItem("theme");
}
// 2. Fallback to system preference
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark";
}
// 3. Default to 'light'
return "light";
};
const theme = getThemePreference();
// Apply the class before the browser renders the content
if (theme === "dark") {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
</script>
</head>
<body>
<main id="main-content">
<slot />
</main>
</body>
</html>
<style>
html,
body {
margin: 0;
width: 100%;
height: 100%;
background-color: var(--color-background);
color: var(--color-text);
max-width: 100vw;
overflow-x: hidden;
transition:
background-color 0.5s ease,
color 0.5s ease;
}
:global(a) {
color: var(--color-primary);
}
:root,
.dark {
transition:
--color-text 0.3s ease,
--color-text-sub 0.3s ease,
--color-background 0.3s ease,
--color-primary 0.3s ease,
--color-surface 0.3s ease,
--color-card 0.3s ease,
--color-blogcard 0.3s ease;
}
/* Light theme */
:root {
--color-text: #1a1a1a;
--color-text-sub: rgba(26, 26, 26, 0.75);
--color-background: #ffffff;
--color-primary: #0056b3;
--color-surface: #f4f4f4;
--color-card: #bebebe;
--color-blogcard: #ebebeb;
}
/* Dark theme */
.dark {
--color-text: #f0f0f0;
--color-text-sub: rgba(240, 240, 240, 0.75);
--color-background: #1a1a1a;
--color-primary: #8ab4f8;
--color-surface: #2c2c2c;
--color-card: #696969;
--color-blogcard: #3d3d3d;
}
</style>BlogArticleLayout.astro---
import Layout from "./Layout.astro";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import { Image } from "astro:assets";
import ogDefaultImage from "@/assets/og-default.png";
import formatToJSTDate from "@/utils/formatToJSTDate";
import { Icon } from "astro-icon/components";
import type { MarkdownHeading } from "astro";
interface Props {
frontmatter: any;
headings: MarkdownHeading[];
}
const { frontmatter, headings } = Astro.props;
const { slug } = Astro.params;
const { thumbnail } = frontmatter;
// Thumbnail generation
const images = import.meta.glob<{ default: ImageMetadata }>(
`../content/blog/**/*.{jpeg,jpg,png,gif}`,
{ eager: true },
);
const articleImage =
images[
`../content/blog/${slug}/${thumbnail ? thumbnail.replace(/^\.\//, "") : null}`
]?.default ?? ogDefaultImage;
const articleDate = formatToJSTDate(frontmatter.date);
const lastUpdate = frontmatter.lastUpdate
? formatToJSTDate(frontmatter.lastUpdate)
: null;
// TOC generation
const toc = headings.filter((h) => h.depth > 1 && h.depth < 4);
---
<Layout>
<Header />
<div class="blog-hero">
<Image src={articleImage} alt={frontmatter.alt} />
<p class="category">{frontmatter.category}</p>
<h1>{frontmatter.title}</h1>
<div class="date-container">
<Icon name="mdi:calendar" size="1.1em" /><p class="date">{articleDate}</p>
{
lastUpdate && (
<>
<Icon name="mdi:update" size="1.1em" />
<p class="date">{lastUpdate}</p>
</>
)
}
</div>
</div>
<div class="container">
<slot />
</div>
<Footer />
</Layout>
<style>
h1 {
text-align: center;
margin: 18px 40px 26px 40px;
word-break: auto-phrase;
font-size: 36px;
@media (max-width: 768px) {
font-size: 24px;
margin: 8px 40px 16px 40px;
}
}
.container {
max-width: 768px;
padding: 0 30px 80px;
margin: 0 auto;
p {
max-width: 100vw;
a:first-child {
word-break: break-all;
}
code {
word-break: break-all;
}
}
img {
max-width: 100%;
object-fit: contain;
height: auto;
}
h2 {
margin-top: 60px;
}
}
.blog-hero {
max-width: 1080px;
margin: 0 auto 40px auto;
text-align: center;
img {
max-width: 100%;
object-fit: cover;
aspect-ratio: 1280 / 720;
height: auto;
}
.date {
padding-right: 0.5em;
}
.date-container {
font-size: 0.8em;
color: var(--color-text-sub);
padding: 0 12px;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
height: 1.2em;
color: var(--color-text-sub);
}
.category {
background-color: var(--color-text-sub);
color: var(--color-background);
display: inline-block;
text-align: center;
padding: 0 14px;
margin: 32px 0 0 0;
border-radius: 8px;
font-size: 0.9em;
}
}
</style>
<script is:inline define:vars={{ toc }}>
const container = document.getElementById("article-toc-trigger");
if (container && toc.length > 0) {
const title = document.createElement("h2");
title.innerText = "Table of Contents";
const list = document.createElement("ul");
toc.forEach((h) => {
const li = document.createElement("li");
li.style.marginLeft = `${(h.depth - 2) * 20}px`;
const a = document.createElement("a");
a.href = `#${h.slug}`;
a.innerText = h.text;
li.appendChild(a);
list.appendChild(li);
});
container.appendChild(title);
container.appendChild(list);
}
</script>ResourcesProblematic websiteYou can see the code block is always black even you are in light mode. Reloading won't change anything. https://aosankaku-website-2025.pages.dev/blog/gatsby-graphql-override/ Repository |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 4 replies
-
|
Hi @AoSankaku is this still an issue? I looked at https://aosankaku-website-2025.pages.dev/blog/gatsby-graphql-override/ and the theme seems to toggle as expected. |
Beta Was this translation helpful? Give feedback.
-
|
Thank you for your quick responce, today I implemented force temporary fix on AoSankaku/aosankaku-website-2025@e10bb42, which is redundant and inefficient. The problematic deploy is available on https://5f2da7b5.aosankaku-website-2025.pages.dev/blog/gatsby-graphql-override/ and this is build based on AoSankaku/aosankaku-website-2025@730b617 . Note that the syntax highlighing is disabled just because I forgot to change the syntax of the code block title, it worked fine. |
Beta Was this translation helpful? Give feedback.
-
|
In my opinion, the issue is that you're using a light theme as the default on your site (without any You need to change the order of themes in your EC config so that it matches your site setup. The light theme needs to come first. In addition, you need to configure the themeCssSelector as suggested by delucis so that it also reacts to the |
Beta Was this translation helpful? Give feedback.
-
|
OK, after research (and with help by Gemini because my English is not so good), I managed to solve this with: themes: ['one-light', 'one-dark-pro'],
useDarkModeMediaQuery: false,
themeCssSelector: (theme, { styleVariants }) => {
// 2. If the theme is 'one-dark-pro', trigger it when .dark class is on <html>
if (theme.name === 'one-dark-pro') return '.dark';
// Otherwise, it's the default theme (one-light)
return false;
},And the crucial concepts are:
May I update the docs ( https://github.com/expressive-code/expressive-code/tree/main/docs ) and create pull request to pubilsh this guide for following beginners? If any of the hints are incorrect even partially, tell me as soon as possible. Thank you again for very quick and helpful responses! |
Beta Was this translation helpful? Give feedback.
OK, after research (and with help by Gemini because my English is not so good), I managed to solve this with:
And the crucial concepts are:
useDarkModeMediaQuerymust be disabled in order not to let EC respond to@mediaquery (This is the very first time to implement lightβ¦