From ed5446cccafc84236f4079b683481351673a8e8e Mon Sep 17 00:00:00 2001 From: bits-bytes-nn Date: Thu, 15 Oct 2026 20:57:36 +0900 Subject: [PATCH 1/8] Let the page follow the nav bar's height when its tabs wrap An eighth tab wrapped the bar to two rows at 960px and up, and the fixed bar covered each page's heading; the offset was a fixed 66px. main.js now passes the bar's height as --nav-height. Also: the main landmark's id is main-content, so a '## Content' heading cannot collide with it; the lint allows q, time, var, samp, u, dfn, track and the SVG marker and ellipse; the categories description no longer lists the types. --- _layouts/default.html | 8 ++++---- _sass/_layout.scss | 11 +++++++---- categories.html | 4 ++-- docs/tech-doc.md | 3 +++ js/main.js | 11 +++++++++++ script/lint-posts.rb | 8 ++++---- 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/_layouts/default.html b/_layouts/default.html index bdf5ff7..00fa1be 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -4,15 +4,15 @@ {% include head.html %} - - + {% include header.html %} -
+
{{ content }}
diff --git a/_sass/_layout.scss b/_sass/_layout.scss index b480185..96bde8e 100644 --- a/_sass/_layout.scss +++ b/_sass/_layout.scss @@ -62,14 +62,16 @@ main.page-content { // Whatever the browser scrolls into view clears the fixed 66px header, which // would otherwise cover it: fragment targets (the TOC, /tags/#… from another -// page, the skip link's #content) and the control keyboard focus moves to. +// page, the skip link's #main-content) and the control keyboard focus moves to. // Done here rather than in a click handler so it also holds for links followed // from elsewhere and for ids a CSS selector cannot parse ("#1-서론"). // // No `scroll-behavior: smooth`. A smooth jump passes lazy images that load on // the way and grow the page, so on long posts it stopped short of the heading. +// --nav-height is the bar's real height, set by js/main.js: more tabs than one +// row holds wrap it to two, and the page moves down with it. html { - scroll-padding-top: 80px; + scroll-padding-top: calc(var(--nav-height, 66px) + 14px); } // Visible to assistive technology, not on screen. Used by the copy-button live @@ -560,7 +562,8 @@ blockquote { // from 768px to about 785px, iPad portrait included. The bar wrapped to // two rows, 130px tall, and hid the top of every page beneath it. 1.1em // above it: seven tabs at 1.5em wrapped in the fallback font, before the - // web font arrives. + // web font arrives. A tab past what one row holds still wraps the bar; + // the page follows its height (--nav-height, below). @include media ($tablet) { padding-right: 1em; } @@ -612,7 +615,7 @@ blockquote { * Body */ .page-content { - margin-top: 66px; + margin-top: var(--nav-height, 66px); .wrapper { @include outer-container; diff --git a/categories.html b/categories.html index d0d6a22..54681ec 100644 --- a/categories.html +++ b/categories.html @@ -4,8 +4,8 @@ title: "Categories" permalink: /categories/ description: >- - Every post on this blog grouped by category — Paper Reviews, Paper Summaries, - Paper Surveys, Tech Guides, and Insights. + Every post on this blog grouped by category: paper reviews, summaries and + surveys, tech guides, and insights. --- {%- comment -%} diff --git a/docs/tech-doc.md b/docs/tech-doc.md index 24f1035..59eaed7 100644 --- a/docs/tech-doc.md +++ b/docs/tech-doc.md @@ -144,6 +144,9 @@ _site/paper-reviews/language-models/2025/01/23/.html 달린 모든 페이지**를 찾아 `nav_order` 숫자 순으로 자동 나열한다. 새 탭을 넣고 싶으면 페이지 프런트매터에 두 값을 더하면 된다. 탭 이름은 페이지 `title`이고, `nav_title`이 있으면 그것을 쓴다 — 메뉴 폭이 48em이라 "Paper"로 시작하는 탭 셋이 두 줄로 넘쳤기 때문이다(Summaries·Reviews·Surveys). +탭이 한 줄에 다 들어가지 않으면 메뉴가 두 줄로 내려가고, `js/main.js`가 실제 헤더 높이를 +`--nav-height`로 넘겨 본문과 앵커 위치가 함께 내려간다. 지금 탭 이름은 합쳐 53자이고 한 줄에는 +58자 안팎까지 들어간다. 현재 순서: | nav_order | 페이지 | 소스 | diff --git a/js/main.js b/js/main.js index cf28eb6..ce732f4 100644 --- a/js/main.js +++ b/js/main.js @@ -121,6 +121,17 @@ document.addEventListener('DOMContentLoaded', function () { // Add a class to the nav once the page is scrolled var nav = document.querySelector('.navigation'); if (nav) { + // The page starts below the fixed bar, which grows to two rows when its + // tabs do not fit on one. The phone menu's dropdown is not the bar: there + // the bar stays one row and the open menu covers the page on purpose. + var wide = window.matchMedia('(min-width: 768px)'); + var syncNavHeight = function () { + if (wide.matches) document.documentElement.style.setProperty('--nav-height', nav.offsetHeight + 'px'); + else document.documentElement.style.removeProperty('--nav-height'); + }; + if (window.ResizeObserver) new ResizeObserver(syncNavHeight).observe(nav); + wide.addEventListener('change', syncNavHeight); + syncNavHeight(); window.addEventListener('scroll', function () { nav.classList.toggle('scrolled', window.pageYOffset > 50); }, { passive: true }); diff --git a/script/lint-posts.rb b/script/lint-posts.rb index 27d52b2..b7af120 100644 --- a/script/lint-posts.rb +++ b/script/lint-posts.rb @@ -201,10 +201,10 @@ def self.strip_code(text) # writes, not all of HTML. HTML_ELEMENTS = %w[ a abbr audio b blockquote br caption center cite code col colgroup dd del details - div dl dt em figcaption figure h1 h2 h3 h4 h5 h6 hr i iframe img ins kbd li mark - ol p picture pre script section small source span strong sub summary sup svg - table tbody td tfoot th thead tr ul video wbr - circle defs g line path polygon polyline rect text tspan use + dfn div dl dt em figcaption figure h1 h2 h3 h4 h5 h6 hr i iframe img ins kbd li + mark ol p picture pre q samp script section small source span strong sub summary + sup svg table tbody td tfoot th thead time tr track u ul var video wbr + circle defs ellipse g line marker path polygon polyline rect text tspan use ].to_set # the last row: an inline 's children # Elements that mean nothing bare: or