Skip to content

fix(theme): prevent white flash during page load#81

Open
Mujojo03 wants to merge 1 commit intobitdevsnbo:masterfrom
Mujojo03:feature
Open

fix(theme): prevent white flash during page load#81
Mujojo03 wants to merge 1 commit intobitdevsnbo:masterfrom
Mujojo03:feature

Conversation

@Mujojo03
Copy link
Copy Markdown
Contributor

No description provided.

@vercel
Copy link
Copy Markdown

vercel bot commented Oct 22, 2025

@Mujojo03 is attempting to deploy a commit to the BitDevsNBO Team on Vercel.

A member of the Team first needs to authorize it.

@Mujojo03
Copy link
Copy Markdown
Contributor Author

Mujojo03 commented Oct 22, 2025

@okjodom
Kindly authorize to deploy to vercel.

@vercel
Copy link
Copy Markdown

vercel bot commented Oct 22, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bitdevsnbo-org Ready Ready Preview, Comment Mar 3, 2026 6:47pm

specs:
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
base64 (0.2.0)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mujojo03 was this change intended to be part of this PR? Looks extraneous and accidental!

@okjodom
Copy link
Copy Markdown
Contributor

okjodom commented Oct 22, 2025

blocked by failing builds. @Mujojo03 please use rebase workflows, and avoid commits like 102de10

@Mujojo03
Copy link
Copy Markdown
Contributor Author

@okjodom
I have resolved the conflicts. You can review.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@okjodom okjodom requested a review from Copilot March 3, 2026 19:00
@okjodom
Copy link
Copy Markdown
Contributor

okjodom commented Mar 3, 2026

Thanks @Mujojo03 for tackling this! The PR has the right intent and introduces some solid patterns (inline <head> script, defer on script tag, CSS custom properties, @use migration). However, there are a few critical bugs that need to be fixed before this can merge.


🔴 Critical: Theme system disconnect — data-theme vs dark-mode class

This is the core bug that breaks the intended fix.

The inline script in <head> sets:

document.documentElement.setAttribute('data-theme', theme);

But the CSS listens for body.dark-mode { }. These two systems never connect — the flash is not actually prevented. The dark-mode class is only applied by script.js after DOMContentLoaded, which is too late.

Fix: Replace body.dark-mode { } in _global.scss with:

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

And update script.js to sync the attribute:

document.documentElement.setAttribute('data-theme', isDarkMode ? 'dark' : 'light');

🔴 Critical: _includes/footer.html introduces invalid nested HTML

The updated partial wraps the footer in a full <body> tag with <header> and <main> placeholders. Since this is a Jekyll _includes file injected into an existing layout, this produces duplicate/nested <body> tags, breaking the page structure and accessibility.

Fix: Revert to just the <footer> element, without the wrapping <body>/<header>/<main> tags.


🟡 Medium: lighten() is a Sass function — invalid as a CSS custom property value

:root {
  --link-hover-color: lighten(#F7931A, 10%); /* ❌ not valid CSS */
}

The browser receives this as a literal string and ignores it. Fix: Pre-compute the value: --link-hover-color: #f8a94e;


🟡 Medium: window load listener nested inside DOMContentLoaded

If load fires before DOMContentLoaded runs (edge case), the loaded class will never be added and all transitions will remain permanently disabled. Fix: Move window.addEventListener('load', ...) to the top level, outside DOMContentLoaded.


🟡 Medium: transition: all 0.1s ease !important on every element

transition: all has performance implications and the !important overrides carefully-scoped transitions elsewhere. Fix: Scope to specific properties like background-color and color.


🟡 Medium: Variable duplication between _variables.scss and style.scss

Breakpoints and color variables are now defined in both files. Remove the duplicates from style.scss and rely solely on _variables.scss.


🟡 Medium: &-logo de-indented out of .Header {} in _header.scss

The &-logo block was accidentally de-indented to the root level, breaking the visual BEM structure.


🟢 Minor: font-weight: bold in _home.scss is unrelated to this PR

Should be in a separate, focused PR.


Not ready to merge. The two critical issues must be addressed. Happy to discuss — great work tackling the FOUC (Flash of Unstyled Content) problem, the approach just needs some wiring fixes!

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +6 to 11
// If the toggleButton doesn't exist, stop gracefully
if (!toggleButton) return;

const savedTheme = localStorage.getItem("theme");
if (savedTheme === "dark") {
body.classList.add("dark-mode");
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The early return prevents applying the saved theme on any page where #theme-toggle is absent, which can reintroduce the flash/mismatched theme. Apply the saved theme regardless, and only guard the parts that read/update toggleButton (click handler + textContent).

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +10
const theme = storedTheme || (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sets data-theme on <html>, but the updated theme CSS in this PR is driven by body.dark-mode and CSS variables (not [data-theme="dark"]). As a result, the “apply before styles load” step won’t actually affect styling unless you either (a) update CSS to key off html[data-theme="dark"] (or similar), or (b) set the same dark-mode class used by the runtime script.

Suggested change
const theme = storedTheme || (prefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
const theme = storedTheme || (prefersDark ? 'dark' : 'light');
// Keep data-theme for compatibility, but also apply the class used by theme CSS
document.documentElement.setAttribute('data-theme', theme);
if (theme === 'dark') {
document.documentElement.classList.add('dark-mode');
if (document.body) {
document.body.classList.add('dark-mode');
}
} else {
document.documentElement.classList.remove('dark-mode');
if (document.body) {
document.body.classList.remove('dark-mode');
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +117 to +122
* {
transition: none !important;
}

body.loaded * {
transition: all 0.1s ease;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forcing transition: none !important on * and then transition: all on body.loaded * is very expensive (forces style recalculation widely) and also overrides intentional component-level transitions (and transition: all is particularly costly). Prefer scoping this to the properties involved in theme changes (e.g., background-color, color, border-color) and/or applying it only to elements that actually animate for theme switching (or using a body class like body:not(.loaded) to selectively disable).

Suggested change
* {
transition: none !important;
}
body.loaded * {
transition: all 0.1s ease;
body:not(.loaded),
body:not(.loaded) * {
transition: none !important;
}
body.loaded,
body.loaded * {
transition: background-color 0.1s ease, color 0.1s ease, border-color 0.1s ease;

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +4
<body>
<header>...</header>
<main>...</main>
<footer class="Footer">
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_includes/footer.html should not introduce <body>, <header>, or <main> tags; this will create invalid HTML (nested/duplicated document structure) when included inside the layout and can break styling and scripts. This include should render only the footer markup (starting at <footer class="Footer">).

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +17
</footer>
</body> No newline at end of file
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_includes/footer.html should not introduce <body>, <header>, or <main> tags; this will create invalid HTML (nested/duplicated document structure) when included inside the layout and can break styling and scripts. This include should render only the footer markup (starting at <footer class="Footer">).

Copilot uses AI. Check for mistakes.
@@ -1,12 +1,19 @@
// header.scss

@use 'variables' as vars;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variables import path is inconsistent with other files (@use './variables' as vars;). Depending on the Sass load path configuration, @use 'variables' may fail to resolve. Align this to the same relative path used elsewhere to avoid build failures.

Suggested change
@use 'variables' as vars;
@use './variables' as vars;

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +10
$base-font-size: 16px !default;

// Colors
$background-color: #000000; // black
$font-color: #ffffff; // white
$primary-color: #FFA500; // orange
$background-color: #000000 !default; // black
$font-color: #ffffff !default; // white
$primary-color: #F7931A !default; // orange
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variables are now split between this file and ./variables, and with Sass @use, variables aren’t implicitly global the way @import was. This makes it easy to end up with duplicated/conflicting configuration and “undefined variable” errors in modules. Consider moving all variable definitions into _variables.scss and either @forward them from a single entrypoint, or have each partial explicitly @use './variables' as vars; and reference vars.$... consistently.

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +26
$small-screen: 400px !default;
$mid-screen: 768px !default;
$large-screen: 1024px !default;

@import './reset';
@import './global';
@import './header';
@import './footer';
@import './home';
@import './post';
@import './blog';
@use './variables' as vars;

// @use './reset';
// @use './global';
// @use './header';
// @use './footer';
// @use './home';
// @use './post';
// @use './blog';
@use './reset';
@use './global';
@use './header';
@use './footer';
@use './home';
@use './post';
@use './blog';
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variables are now split between this file and ./variables, and with Sass @use, variables aren’t implicitly global the way @import was. This makes it easy to end up with duplicated/conflicting configuration and “undefined variable” errors in modules. Consider moving all variable definitions into _variables.scss and either @forward them from a single entrypoint, or have each partial explicitly @use './variables' as vars; and reference vars.$... consistently.

Copilot uses AI. Check for mistakes.
<a href="/feed.xml">RSS Feed</a>
<div class="Footer-inner">
<div class="Footer-source">
<a href="https://github.com/BitDevsNBO/bitdevsnbo.org" target="_blank" rel="noopener nofollow">Source available on Github</a>
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the brand capitalization from "Github" to "GitHub" in the link text.

Suggested change
<a href="https://github.com/BitDevsNBO/bitdevsnbo.org" target="_blank" rel="noopener nofollow">Source available on Github</a>
<a href="https://github.com/BitDevsNBO/bitdevsnbo.org" target="_blank" rel="noopener nofollow">Source available on GitHub</a>

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants