From 8d6d84738721aaa528e3a43c731d0f86a7cb9751 Mon Sep 17 00:00:00 2001 From: Mujojo03 Date: Tue, 30 Dec 2025 10:26:31 +0300 Subject: [PATCH] fix(theme): prevent white flash during page load --- Gemfile.lock | 24 +++++------ _includes/footer.html | 26 +++++++----- _includes/head.html | 12 ++++++ _layouts/default.html | 2 +- assets/css/_footer.scss | 12 +++--- assets/css/_global.scss | 82 ++++++++++++++++++++++++-------------- assets/css/_header.scss | 68 +++++++++++++++++++------------ assets/css/_home.scss | 1 + assets/css/_variables.scss | 13 ++++++ assets/css/style.scss | 37 +++++++---------- assets/js/script.js | 7 ++++ 11 files changed, 177 insertions(+), 107 deletions(-) create mode 100644 assets/css/_variables.scss diff --git a/Gemfile.lock b/Gemfile.lock index 2757d63..0afaf61 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,18 +3,18 @@ GEM specs: addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) - base64 (0.2.0) - bigdecimal (3.1.9) + base64 (0.3.0) + bigdecimal (3.3.1) colorator (1.1.0) concurrent-ruby (1.3.5) - csv (3.3.2) + csv (3.3.5) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) eventmachine (1.2.7) - ffi (1.17.1) + ffi (1.17.2) forwardable-extended (2.6.0) - google-protobuf (4.29.3) + google-protobuf (4.33.0) bigdecimal rake (>= 13) http_parser.rb (0.8.0) @@ -50,7 +50,7 @@ GEM jekyll (>= 3.7, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - json (2.10.1) + json (2.15.1) kramdown (2.5.1) rexml (>= 3.3.9) kramdown-parser-gfm (1.1.0) @@ -62,16 +62,16 @@ GEM mercenary (0.4.0) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (6.0.1) - rake (13.2.1) + public_suffix (6.0.2) + rake (13.3.0) rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rexml (3.4.1) - rouge (4.5.1) + rexml (3.4.4) + rouge (4.6.1) safe_yaml (1.0.5) - sass-embedded (1.85.0) - google-protobuf (~> 4.29) + sass-embedded (1.93.2) + google-protobuf (~> 4.31) rake (>= 13) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) diff --git a/_includes/footer.html b/_includes/footer.html index 123f9e2..6da4384 100755 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -1,13 +1,17 @@ - + \ No newline at end of file diff --git a/_includes/head.html b/_includes/head.html index 66f38c6..1d6366b 100755 --- a/_includes/head.html +++ b/_includes/head.html @@ -1,5 +1,17 @@ + + {% if page.title == "Home" %} {{ site.data.settings.title }} | {{ site.data.settings.tagline }} diff --git a/_layouts/default.html b/_layouts/default.html index 45c7641..5bd5990 100755 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -16,7 +16,7 @@ </div> <!-- ✅ Load theme toggle script --> - <script src="{{ '/assets/js/script.js' | relative_url }}"></script> + <script src="{{ '/assets/js/script.js' | relative_url }}" defer></script> </body> diff --git a/assets/css/_footer.scss b/assets/css/_footer.scss index 881b812..3486800 100644 --- a/assets/css/_footer.scss +++ b/assets/css/_footer.scss @@ -1,6 +1,6 @@ .Footer { margin-top: 2rem; - color: $font-color; + color: var(--font-color); padding: 2rem; text-align: center; @@ -9,7 +9,7 @@ margin-bottom: 1em; overflow: hidden; user-select: none; - color: $font-color; + color: var(--font-color); } &-inner { @@ -19,16 +19,16 @@ gap: 1rem; a { - color: $primary-color; // orange + color: var(--primary-color); opacity: 1; text-decoration: none; font-weight: 500; - transition: opacity 0.2s ease, color 0.2s ease; + transition: opacity 0.1s ease, color 0.1s ease; &:hover { opacity: 0.9; - color: lighten($primary-color, 10%); + color: var(--link-hover-color, var(--primary-color)); } } } -} +} \ No newline at end of file diff --git a/assets/css/_global.scss b/assets/css/_global.scss index e2fe2fc..3c3b0d3 100644 --- a/assets/css/_global.scss +++ b/assets/css/_global.scss @@ -1,18 +1,31 @@ -$background-light: #ffffff; -$font-light: #000000; -$primary-color-light: #ff7f00; - -$background-dark: #000000; -$font-dark: #ffffff; -$primary-color-dark: #ff7f00; +@use './variables' as vars; + +$large-screen: 1100px !default; +$mid-screen: 800px !default; +$small-screen: 480px !default; + +:root { + /* light theme defaults */ + --background-color: #ffffff; + --font-color: #000000; + --primary-color: #F7931A; + --link-hover-color: lighten(#F7931A, 10%); +} +/* dark theme runtime overrides */ +body.dark-mode { + --background-color: #000000; + --font-color: #ffffff; + --primary-color: #F7931A; +} -html, body { - font-family: $body-font; +html, +body { + font-family: vars.$body-font; font-size: 16px; line-height: 1.5; - background-color: $background-color; - color: $font-color; + background-color: var(--background-color); + color: var(--font-color); transition: background-color 0.4s ease, color 0.4s ease; @@ -27,41 +40,42 @@ html, body { @media (max-width: $small-screen) { font-size: 12px; } -} + /* ✅ Ensures each page fills the viewport height */ + min-height: 100vh; + /* Helps prevent layout shift when footer is short */ + display: flex; + flex-direction: column; +} + +/* ✅ Make sure the body expands correctly for content and footer */ body { - background-color: $background-light; - color: $font-light; + background-color: var(--background-color); + color: var(--font-color); + flex: 1; /* allow content area to grow */ + box-sizing: border-box; } a { - color: $primary-color-light; + color: var(--primary-color); text-decoration: none; transition: color 0.3s ease; &:hover { - color: lighten($primary-color-light, 10%); - } -} - -body.dark-mode { - background-color: $background-dark; - color: $font-dark; -} - -body.dark-mode a { - color: $primary-color-dark; - - &:hover { - color: lighten($primary-color-dark, 10%); + color: var(--link-hover-color, var(--primary-color)); } } +/* ✅ Keeps layout centered and responsive */ .Site { max-width: 880px; margin: 0 auto; padding: 2rem; + background-color: var(--background-color); + color: var(--font-color); + flex: 1; /* fills remaining height between header and footer */ + transition: background-color 0.4s ease, color 0.4s ease; } p { @@ -98,4 +112,12 @@ h4 { font-size: 1.2rem; margin-top: 0.5rem; margin-bottom: 0.5rem; -} \ No newline at end of file +} + +* { + transition: none !important; +} + +body.loaded * { + transition: all 0.1s ease; +} diff --git a/assets/css/_header.scss b/assets/css/_header.scss index 56058e0..77f11ae 100644 --- a/assets/css/_header.scss +++ b/assets/css/_header.scss @@ -1,12 +1,19 @@ +// header.scss + +@use 'variables' as vars; + .Header { margin-bottom: 0.75rem; + background-color: var(--background-color); + color: var(--font-color); + transition: background-color 0.4s ease, color 0.4s ease; &-border { opacity: 0.3; margin-top: 0.4rem; overflow: hidden; user-select: none; - color: $font-color; + color: var(--font-color); } &-inner { @@ -16,53 +23,64 @@ padding: 1rem 0; } - &-logo { - font-size: 2.2rem; - color: $font-color; +&-logo { + font-size: 2.2rem; + color: #F7931A; // static orange color + transition: color 0.3s ease; - @media (max-width: $small-screen) { - font-size: 1.8rem; - } + @media (max-width: vars.$small-screen) { + font-size: 1.8rem; } - .theme-toggle { - background: none; - border: 1px solid $primary-color-dark; - color: $primary-color-dark; - border-radius: 8px; - padding: 0.4rem 0.8rem; - cursor: pointer; - margin-left: 1.5rem; - font-size: 1.1rem; - transition: background 0.2s ease, color 0.2s ease; + a { + color: #F7931A; // ensure link inherits orange color + text-decoration: none; + transition: color 0.3s ease; - &:hover { - background: $primary-color-dark; - color: #000; + &:hover { + color: darken(#F7931A, 10%); // slightly darker orange on hover + } } } + .theme-toggle { + background: none; + border: 1px solid var(--primary-color); + color: var(--primary-color); + border-radius: 8px; + padding: 0.4rem 0.8rem; + cursor: pointer; + margin-left: 1.5rem; + font-size: 1.1rem; + transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease; + + &:hover { + background: var(--primary-color); + color: var(--background-color); /* stays readable in both modes */ + } + } &-nav { display: flex; font-size: 1.3rem; + transition: color 0.3s ease; - @media (max-width: $small-screen) { + @media (max-width: vars.$small-screen) { font-size: 1.1rem; } a { - color: $primary-color; + color: var(--primary-color); opacity: 1; margin-left: 1.5rem; text-decoration: none; font-weight: 500; - transition: opacity 0.2s ease, color 0.2s ease; + transition: opacity 0.1s ease, color 0.1s ease; &:hover { - color: lighten($primary-color, 10%); + color: var(--link-hover-color, var(--primary-color)); opacity: 0.9; } } } -} +} \ No newline at end of file diff --git a/assets/css/_home.scss b/assets/css/_home.scss index 28fde34..65cb76f 100644 --- a/assets/css/_home.scss +++ b/assets/css/_home.scss @@ -1,6 +1,7 @@ .Home { &-about { font-size: 1.2rem; + font-weight: bold; } &-posts { diff --git a/assets/css/_variables.scss b/assets/css/_variables.scss new file mode 100644 index 0000000..6e1e475 --- /dev/null +++ b/assets/css/_variables.scss @@ -0,0 +1,13 @@ +// Typography +$body-font: 'Source Code Pro', monospace !default; +$base-font-size: 16px !default; + +// Colors +$background-color: #000000 !default; // black +$font-color: #ffffff !default; // white +$primary-color: #FFA500 !default; // orange + +// Screen size for responsiveness +$small-screen: 400px !default; +$mid-screen: 768px !default; +$large-screen: 1024px !default; \ No newline at end of file diff --git a/assets/css/style.scss b/assets/css/style.scss index 653427d..a6f7008 100755 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -2,32 +2,25 @@ --- // Typography -$body-font: 'Source Code Pro', monospace; -$base-font-size: 16px; +$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 // Screen size for responsiveness -$small-screen: 400px; -$mid-screen: 768px; -$large-screen: 1024px; +$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'; diff --git a/assets/js/script.js b/assets/js/script.js index 073c4d5..15020fc 100755 --- a/assets/js/script.js +++ b/assets/js/script.js @@ -3,6 +3,9 @@ document.addEventListener("DOMContentLoaded", () => { const toggleButton = document.getElementById("theme-toggle"); const body = document.body; + // If the toggleButton doesn't exist, stop gracefully + if (!toggleButton) return; + const savedTheme = localStorage.getItem("theme"); if (savedTheme === "dark") { body.classList.add("dark-mode"); @@ -18,4 +21,8 @@ document.addEventListener("DOMContentLoaded", () => { localStorage.setItem("theme", isDarkMode ? "dark" : "light"); toggleButton.textContent = isDarkMode ? "☀️" : "🌙"; }); + + window.addEventListener('load', () => { + document.body.classList.add('loaded'); +}); }); \ No newline at end of file