feat(typography): extend typography system with Google Fonts and font packs

This commit is contained in:
George Cushen committed 2026-03-03 00:30:27 +00:00
1 parent 4fcfe33cc0
commit 24dc36f6d7
28 files changed
+669 -127

No files matched your search

File renamed without changes.
+3 -3
View File
@@ -85,7 +85,7 @@
.hb-ruby-name rt {
/* Elegant, subdued annotation text */
font-size: 0.45em;
font-weight: 500;
font-weight: var(--hb-font-weight-body-bold, 600);
letter-spacing: 0.08em;
line-height: 1.2;
@@ -125,7 +125,7 @@
/* Latin-optimized variant - smaller annotation for romanization over CJK */
.hb-ruby-name--latin rt {
font-size: 0.4em;
font-weight: 500;
font-weight: var(--hb-font-weight-body-bold, 600);
text-transform: none;
}
@@ -278,4 +278,4 @@
background-image:
radial-gradient(at 20% 25%, hsla(212, 35%, 15%, 1) 0px, transparent 50%), radial-gradient(at 75% 30%, hsla(160, 35%, 15%, 1) 0px, transparent 50%),
radial-gradient(at 25% 80%, hsla(280, 35%, 15%, 1) 0px, transparent 50%), radial-gradient(at 75% 85%, hsla(30, 35%, 15%, 1) 0px, transparent 50%);
}
}
+21 -2
View File
@@ -322,8 +322,27 @@
/* Note: Providing these palettes in @theme ensures theme-pack mappings like var(--color-rose-600) always resolve */
/* Font family */
/* Font families */
--font-family-sans: inter var, ui-sans-serif, system-ui, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji;
--font-heading: var(--font-family-sans);
--font-body: var(--font-family-sans);
--font-code: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--font-nav: var(--font-heading);
/* Font weights */
--font-weight-heading: 700;
--font-weight-body: 400;
--hb-font-weight-body-bold: 600;
/* Line heights */
--font-leading-heading: 1.2;
--font-leading-body: 1.6;
--font-leading-code: 1.5;
/* Letter spacing */
--font-tracking-heading: -0.02em;
--font-tracking-body: 0;
--font-tracking-caps: 0.05em;
/* Font sizes */
--font-size-xs: 0.75rem;
@@ -336,4 +355,4 @@
--font-size-4xl: 2.25rem;
--font-size-5xl: 3rem;
--font-size-6xl: 4rem;
}
}
+28 -3
View File
@@ -4,15 +4,40 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizelegibility;
/* Apply the runtime font vars injected by Hugo's typography partial */
font-family: var(--font-body);
}
body {
line-height: 1.5;
font-family: var(--font-body);
font-weight: var(--font-weight-body, 400);
line-height: var(--font-leading-body, 1.6);
letter-spacing: var(--font-tracking-body, 0);
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-heading);
font-weight: var(--font-weight-heading, 700);
line-height: var(--font-leading-heading, 1.2);
letter-spacing: var(--font-tracking-heading, -0.02em);
}
code,
pre,
kbd,
samp {
font-family: var(--font-code);
}
}
/* Gradient Mesh Animations */
@keyframes float {
0%,
100% {
transform: translateY(0) translateX(0);
@@ -61,7 +86,7 @@
.prose a {
text-decoration: underline;
text-decoration-color: var(--color-primary-300);
font-weight: 500;
font-weight: var(--hb-font-weight-body-bold, 600);
}
.prose a:hover {
@@ -100,4 +125,4 @@
.prose code:not(:where(pre *))::after {
content: none;
}
}
}
@@ -1,5 +1,6 @@
/* Hugo Blox Framework Custom Classes */
@layer components {
/* Section styles for Hugo Blox blocks */
.hbb-section {
padding-top: 6rem;
@@ -8,7 +9,7 @@
.section-subheading {
font-size: 1.25rem;
font-weight: 700;
font-weight: var(--font-weight-heading, 700);
}
/* Home section background styles */
@@ -129,4 +130,4 @@
section.dark {
background-color: transparent;
}
}
}
+2 -2
View File
@@ -15,7 +15,7 @@
.search-result mark {
background-color: rgb(254 240 138);
color: rgb(17 24 39);
font-weight: 600;
font-weight: var(--hb-font-weight-body-bold, 600);
padding: 0.05rem 0.2rem;
border-radius: 0.125rem;
}
@@ -83,4 +83,4 @@
.search-result:focus-visible {
outline: 2px solid rgb(59 130 246);
outline-offset: -2px;
}
}
@@ -6,7 +6,6 @@
- --hb-spacing-base: Base spacing unit
- --hb-spacing-section: Section padding
- --hb-font-size-base: Base font size
- --hb-font-size-scale: Modular scale ratio
*/
/* Border radius utility - use instead of hardcoded rounded-* classes */
+36
View File
@@ -0,0 +1,36 @@
# HugoBlox Font Pack
# https://docs.hugoblox.com
hugoblox:
meta:
format: "hugoblox-font@1"
name: "Academic"
vendor: "hugoblox"
version: "1.0.0"
license: "MIT"
style: "serif"
description: "Traditional serif pairing for academic, research, and institutional sites"
families:
heading: "Lora"
body: "Source Serif 4"
code: "Source Code Pro"
weights:
heading: [500, 600, 700]
body: [400, 600]
code: [400]
leading:
heading: 1.2
body: 1.7
code: 1.5
tracking:
heading: "0"
body: "0"
variable:
heading: true
body: true
code: false
+35
View File
@@ -0,0 +1,35 @@
# HugoBlox Font Pack
# https://docs.hugoblox.com
hugoblox:
meta:
format: "hugoblox-font@1"
name: "Developer"
vendor: "hugoblox"
version: "1.0.0"
license: "MIT"
description: "Technical, code-forward pairing for developer portfolios and docs"
families:
heading: "Space Grotesk"
body: "IBM Plex Sans"
code: "Fira Code"
weights:
heading: [500, 700]
body: [400, 500, 600]
code: [400, 700]
leading:
heading: 1.2
body: 1.6
code: 1.5
tracking:
heading: "-0.02em"
body: "0"
variable:
heading: true
body: false
code: true
+36
View File
@@ -0,0 +1,36 @@
# HugoBlox Font Pack
# https://docs.hugoblox.com
hugoblox:
meta:
format: "hugoblox-font@1"
name: "Editorial"
vendor: "hugoblox"
version: "1.0.0"
license: "MIT"
style: "serif"
description: "Elegant serif pairing for magazines, blogs, and long-form content"
families:
heading: "Playfair Display"
body: "Merriweather"
code: "Source Code Pro"
weights:
heading: [600, 700, 800]
body: [300, 400, 700]
code: [400]
leading:
heading: 1.15
body: 1.7
code: 1.5
tracking:
heading: "-0.01em"
body: "0"
variable:
heading: true
body: false
code: false
+30
View File
@@ -0,0 +1,30 @@
# HugoBlox Font Pack
# https://docs.hugoblox.com
hugoblox:
meta:
format: "hugoblox-font@1"
name: "Geometric"
vendor: "hugoblox"
version: "1.0.0"
license: "MIT"
description: "Bold, modern geometric sans-serif for startups and SaaS landing pages"
families:
heading: "Montserrat"
body: "Poppins"
code: "JetBrains Mono"
weights:
heading: [600, 700, 800]
body: [300, 400, 500, 600]
code: [400]
leading:
heading: 1.15
body: 1.6
code: 1.5
tracking:
heading: "-0.01em"
body: "0"
+35
View File
@@ -0,0 +1,35 @@
# HugoBlox Font Pack
# https://docs.hugoblox.com
hugoblox:
meta:
format: "hugoblox-font@1"
name: "Humanist"
vendor: "hugoblox"
version: "1.0.0"
license: "MIT"
description: "Friendly, approachable rounded sans-serif for community and personal sites"
families:
heading: "Nunito"
body: "Open Sans"
code: "Ubuntu Mono"
weights:
heading: [600, 700, 800]
body: [400, 600]
code: [400, 700]
leading:
heading: 1.25
body: 1.65
code: 1.5
tracking:
heading: "0"
body: "0"
variable:
heading: true
body: true
code: false
+35
View File
@@ -0,0 +1,35 @@
# HugoBlox Font Pack
# https://docs.hugoblox.com
hugoblox:
meta:
format: "hugoblox-font@1"
name: "Modern"
vendor: "hugoblox"
version: "1.0.0"
license: "MIT"
description: "Clean, modern sans-serif pairing — the default HugoBlox look"
families:
heading: "Inter"
body: "Inter"
code: "JetBrains Mono"
weights:
heading: [600, 700]
body: [400, 500]
code: [400]
leading:
heading: 1.2
body: 1.6
code: 1.5
tracking:
heading: "-0.02em"
body: "0"
variable:
heading: true
body: true
code: true
+30
View File
@@ -0,0 +1,30 @@
# HugoBlox Font Pack
# https://docs.hugoblox.com
hugoblox:
meta:
format: "hugoblox-font@1"
name: "System"
vendor: "hugoblox"
version: "1.0.0"
license: "MIT"
description: "System fonts only — zero network requests, maximum performance"
families:
heading: "system-sans"
body: "system-sans"
code: "system-mono"
weights:
heading: [600, 700]
body: [400, 500]
code: [400]
leading:
heading: 1.2
body: 1.6
code: 1.5
tracking:
heading: "-0.02em"
body: "0"
@@ -93,7 +93,7 @@
{{ if $palette }}
{{ range $shade, $value := $palette }}
/* Note: converting OKLCH to raw RGB CSS vars requires Tailwind 4's internal conversion
{{/* Note: converting OKLCH to raw RGB CSS vars requires Tailwind 4's internal conversion
or we output the raw color value directly if theme.css supports it.
The existing system expects --hb-primary-50-rgb to be a comma-less RGB triplet "255 255 255".
@@ -110,15 +110,15 @@
Since we cannot easily calculate OKLCH -> RGB in Hugo templates, we should
OUTPUT THE HIGHER LEVEL VARIABLES directly here to override theme.css.
*/
*/}}
--color-{{$name}}-{{$shade}}: {{ $value }};
{{ end }}
/* Also set the legacy RGB vars to a fallback (500 shade) to prevent breakage
in case something accesses the raw -rgb var directly, though unlikely */
{{/* Also set the legacy RGB vars to a fallback (500 shade) to prevent breakage
in case something accesses the raw -rgb var directly, though unlikely */}}
--hb-{{$name}}-500-rgb: 128 128 128;
{{ else }}
/* Unknown palette '{{$colorInput}}', falling back to Indigo-like default */
{{/* Unknown palette '{{$colorInput}}', falling back to Indigo-like default */}}
{{ partial "functions/generate_color_scale" (dict "name" $name "color" "#6366f1") }}
{{ end }}
{{ end }}
@@ -56,11 +56,90 @@
{{/* ═══════════════════════════════════════════════════════════════════════════
TYPOGRAPHY
Font packs are loaded from data/fonts/ and provide:
- families: { heading, body, code, nav }
- weights: { heading, body, code, nav } (arrays)
- sizes: { base, sm, lg }
- leading: { heading, body, code }
- tracking: { heading, body, caps }
Legacy support: typography.font (sans/serif/native) maps to pack names
═══════════════════════════════════════════════════════════════════════════ */}}
{{ $hb_typography := $hb.typography | default dict }}
{{ $typography := dict
"font" ($hb_typography.font | default "sans")
"size" ($hb_typography.size | default "md")
{{/* Resolve font pack name */}}
{{ $font_pack_name := $hb_typography.pack | default "modern" }}
{{/* Load the font pack */}}
{{ $font_pack := partial "functions/load_font_pack" $font_pack_name }}
{{/* Resolve families — inline overrides take priority */}}
{{ $pack_families := $font_pack.families | default dict }}
{{ $inline_families := $hb_typography.families | default dict }}
{{ $families := dict
"heading" ($inline_families.heading | default $pack_families.heading | default "Inter")
"body" ($inline_families.body | default $pack_families.body | default "Inter")
"code" ($inline_families.code | default $pack_families.code | default "JetBrains Mono")
"nav" ($inline_families.nav | default $pack_families.nav | default "")
}}
{{/* Resolve weights — inline overrides take priority */}}
{{ $pack_weights := $font_pack.weights | default dict }}
{{ $inline_weights := $hb_typography.weights | default dict }}
{{ $weights := dict
"heading" ($inline_weights.heading | default $pack_weights.heading | default (slice 700))
"body" ($inline_weights.body | default $pack_weights.body | default (slice 400))
"code" ($inline_weights.code | default $pack_weights.code | default (slice 400))
"nav" ($inline_weights.nav | default $pack_weights.nav | default (slice))
}}
{{/* Resolve sizes — inline overrides take priority */}}
{{ $pack_sizes := $font_pack.sizes | default dict }}
{{ $inline_sizes := $hb_typography.sizes | default dict }}
{{ $sizes := dict
"base" ($inline_sizes.base | default $pack_sizes.base | default "1rem")
"sm" ($inline_sizes.sm | default $pack_sizes.sm | default "0.875rem")
"lg" ($inline_sizes.lg | default $pack_sizes.lg | default "1.125rem")
}}
{{/* Resolve leading (line-height) */}}
{{ $pack_leading := $font_pack.leading | default dict }}
{{ $inline_leading := $hb_typography.leading | default dict }}
{{ $leading := dict
"heading" ($inline_leading.heading | default $pack_leading.heading | default 1.2)
"body" ($inline_leading.body | default $pack_leading.body | default 1.6)
"code" ($inline_leading.code | default $pack_leading.code | default 1.5)
}}
{{/* Resolve tracking (letter-spacing) */}}
{{ $pack_tracking := $font_pack.tracking | default dict }}
{{ $inline_tracking := $hb_typography.tracking | default dict }}
{{ $tracking := dict
"heading" ($inline_tracking.heading | default $pack_tracking.heading | default "-0.02em")
"body" ($inline_tracking.body | default $pack_tracking.body | default "0")
"caps" ($inline_tracking.caps | default $pack_tracking.caps | default "0.05em")
}}
{{/* Resolve variable font flags */}}
{{ $pack_variable := $font_pack.variable | default dict }}
{{ $inline_variable := $hb_typography.variable | default dict }}
{{ $variable := dict
"heading" ($inline_variable.heading | default $pack_variable.heading | default false)
"body" ($inline_variable.body | default $pack_variable.body | default false)
"code" ($inline_variable.code | default $pack_variable.code | default false)
"nav" ($inline_variable.nav | default $pack_variable.nav | default false)
}}
{{ $typography := dict
"pack" $font_pack_name
"style" ($font_pack.meta.style | default "sans")
"families" $families
"weights" $weights
"variable" $variable
"sizes" $sizes
"leading" $leading
"tracking" $tracking
}}
{{/* ═══════════════════════════════════════════════════════════════════════════
@@ -0,0 +1,56 @@
{{/*
HugoBlox Theme Engine: Layout Tokens
Resolves layout design tokens (radius, spacing) from the theme config
and emits them as CSS custom properties.
Input: Theme config dict from get_theme_config:
- layout: { radius, spacing }
Output: <style> (CSS custom properties for --hb-radius, --hb-spacing-*)
*/}}
{{/* Map radius tokens to CSS values */}}
{{ $radius := .layout.radius | default "md" }}
{{ $radius_value := "0.5rem" }}
{{ if eq $radius "none" }}
{{ $radius_value = "0" }}
{{ else if eq $radius "sm" }}
{{ $radius_value = "0.25rem" }}
{{ else if eq $radius "md" }}
{{ $radius_value = "0.5rem" }}
{{ else if eq $radius "lg" }}
{{ $radius_value = "0.75rem" }}
{{ else if eq $radius "full" }}
{{ $radius_value = "9999px" }}
{{ else }}
{{ warnf "LAYOUT TOKEN WARNING: Unknown radius value '%s'. Expected: none | sm | md | lg | full. Falling back to 'md' (0.5rem)." $radius }}
{{ end }}
{{/* Map spacing tokens to CSS values */}}
{{ $spacing := .layout.spacing | default "comfortable" }}
{{ $spacing_base := "1rem" }}
{{ $spacing_section := "4rem" }}
{{ if eq $spacing "compact" }}
{{ $spacing_base = "0.75rem" }}
{{ $spacing_section = "2.5rem" }}
{{ else if eq $spacing "comfortable" }}
{{ $spacing_base = "1rem" }}
{{ $spacing_section = "4rem" }}
{{ else if eq $spacing "spacious" }}
{{ $spacing_base = "1.25rem" }}
{{ $spacing_section = "6rem" }}
{{ else }}
{{ warnf "LAYOUT TOKEN WARNING: Unknown spacing value '%s'. Expected: compact | comfortable | spacious. Falling back to 'comfortable'." $spacing }}
{{ end }}
<style>
:root {
/* Layout — Border Radius */
--hb-radius: {{ $radius_value | safeCSS }};
/* Layout — Spacing */
--hb-spacing-base: {{ $spacing_base | safeCSS }};
--hb-spacing-section: {{ $spacing_section | safeCSS }};
}
</style>
@@ -0,0 +1,65 @@
{{/*
HugoBlox Theme Engine: Loads and validates a HugoBlox font pack
Input: Font pack name (string), e.g. "modern-sans" or "acme/editorial"
Returns: The font pack data object (families, weights, sizes, leading, tracking) or empty dict if invalid
Validates:
- Font pack exists in data/fonts/
- Required 'hugoblox' wrapper is present
- Required 'meta.format' starts with 'hugoblox-font@'
*/}}
{{ $pack_name := . }}
{{ $result := dict }}
{{/* Parse vendor/name format */}}
{{ $vendor := "" }}
{{ $name := $pack_name }}
{{ if strings.Contains $pack_name "/" }}
{{ $parts := split $pack_name "/" }}
{{ $vendor = index $parts 0 }}
{{ $name = index $parts 1 }}
{{ end }}
{{/* Load raw font pack data */}}
{{ $raw_pack := dict }}
{{ if $vendor }}
{{/* Third-party font pack: data/fonts/vendor/name.yaml */}}
{{ $vendor_fonts := index site.Data.fonts $vendor }}
{{ if $vendor_fonts }}
{{ $raw_pack = index $vendor_fonts $name }}
{{ end }}
{{ else }}
{{/* Built-in or user font pack: data/fonts/name.yaml */}}
{{ with index site.Data.fonts $name }}
{{ $raw_pack = . }}
{{ end }}
{{ end }}
{{/* Validate font pack structure */}}
{{ if not $raw_pack }}
{{ warnf "FONT PACK ERROR: Font pack '%s' not found in data/fonts/" $pack_name }}
{{ else if not $raw_pack.hugoblox }}
{{ warnf "FONT PACK ERROR: Font pack '%s' is not a valid HugoBlox font pack (missing 'hugoblox' key)" $pack_name }}
{{ else }}
{{ $pack := $raw_pack.hugoblox }}
{{ if not $pack.meta }}
{{ warnf "FONT PACK ERROR: Font pack '%s' is missing the required 'meta' block" $pack_name }}
{{ else }}
{{/* Validate format version */}}
{{ $format := $pack.meta.format | default "" }}
{{ if not (hasPrefix $format "hugoblox-font@") }}
{{ warnf "FONT PACK ERROR: Font pack '%s' has invalid format '%s'. Expected 'hugoblox-font@1'" $pack_name $format }}
{{ end }}
{{ end }}
{{/* Return the validated font pack data (without the hugoblox wrapper) */}}
{{ $result = $pack }}
{{ end }}
{{ return $result }}
@@ -0,0 +1,147 @@
{{/*
HugoBlox Theme Engine: Typography Rendering
Resolves font families, emits Google Fonts <link> tags,
and generates CSS custom properties for typography.
Input: Theme config dict from get_theme_config:
- typography: { families, weights, sizes, leading, tracking }
Output: <link> (Google Fonts) + <style> (CSS custom properties)
*/}}
{{ $typo := .typography }}
{{ $pack_style := $typo.style | default "sans" }}
{{ $families := $typo.families }}
{{ $weights := $typo.weights }}
{{ $variable := $typo.variable | default dict }}
{{ $leading := $typo.leading }}
{{ $tracking := $typo.tracking }}
{{ $sizes := $typo.sizes }}
{{/* System font stacks */}}
{{ $system_sans := "ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'" }}
{{ $system_serif := "ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif" }}
{{ $system_mono := "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace" }}
{{/* Map font names to CSS values and collect Google Font families */}}
{{ $resolve_family := dict }}
{{ $roles := slice "heading" "body" "code" "nav" }}
{{ range $role := $roles }}
{{ $name := index $families $role }}
{{ if not $name }}
{{ continue }}
{{ end }}
{{ $css := "" }}
{{ $is_google := false }}
{{ if eq $name "system-sans" }}
{{ $css = $system_sans }}
{{ else if eq $name "system-serif" }}
{{ $css = $system_serif }}
{{ else if eq $name "system-mono" }}
{{ $css = $system_mono }}
{{ else }}
{{/* Google Font — pick the right generic fallback based on pack style and role */}}
{{ if eq $role "code" }}
{{ $css = printf "'%s', %s" $name $system_mono }}
{{ else if eq $pack_style "serif" }}
{{ $css = printf "'%s', %s" $name $system_serif }}
{{ else }}
{{ $css = printf "'%s', %s" $name $system_sans }}
{{ end }}
{{ $is_google = true }}
{{ end }}
{{ $resolve_family = merge $resolve_family (dict $role (dict "css" $css "google" $is_google "name" $name)) }}
{{ end }}
{{/* Build Google Fonts URL */}}
{{ $gf_families := slice }}
{{ $seen := dict }}
{{ range $role := $roles }}
{{ with index $resolve_family $role }}
{{ if .google }}
{{ $name := .name }}
{{ $is_variable := index $variable $role | default false }}
{{/* Use full range for variable fonts, discrete weights for static */}}
{{ $weight_spec := "" }}
{{ if $is_variable }}
{{ $weight_spec = "100..900" }}
{{ else }}
{{ $role_weights := index $weights $role | default (slice 400) }}
{{ $weight_spec = delimit $role_weights "," }}
{{ end }}
{{/* Dedup key includes weight spec so the same font can appear as both static and variable if needed */}}
{{ $dedup_key := printf "%s|%s" $name $weight_spec }}
{{ if not (index $seen $dedup_key) }}
{{ $seen = merge $seen (dict $dedup_key true) }}
{{ $encoded := replace $name " " "+" }}
{{ $gf_families = $gf_families | append (printf "%s:wght@%s" $encoded $weight_spec) }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ if gt (len $gf_families) 0 }}
{{ $gf_url := printf "https://fonts.googleapis.com/css2?%s&display=swap" (delimit (apply $gf_families "printf" "family=%s" ".") "&") }}
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="{{ $gf_url }}" rel="stylesheet" />
{{ end }}
{{/* Font size vars */}}
{{ $font_size_base := $sizes.base | default "1rem" }}
{{ $font_size_sm := $sizes.sm | default "0.875rem" }}
{{ $font_size_lg := $sizes.lg | default "1.125rem" }}
{{/* Resolve CSS font-family values */}}
{{ $heading_css := $system_sans }}
{{ with index $resolve_family "heading" }}{{ $heading_css = .css }}{{ end }}
{{ $body_css := $system_sans }}
{{ with index $resolve_family "body" }}{{ $body_css = .css }}{{ end }}
{{ $code_css := $system_mono }}
{{ with index $resolve_family "code" }}{{ $code_css = .css }}{{ end }}
{{ $nav_css := $heading_css }}
{{ with index $resolve_family "nav" }}{{ if .css }}{{ $nav_css = .css }}{{ end }}{{ end }}
{{/* Get primary weight for each role (first in array) */}}
{{ $heading_weight := 700 }}
{{ with $weights.heading }}{{ $heading_weight = index . 0 }}{{ end }}
{{ $body_weight := 400 }}
{{ with $weights.body }}{{ $body_weight = index . 0 }}{{ end }}
{{/* Bold body weight: second value in array, or primary + 200 (capped at 900) */}}
{{ $body_weight_bold := math.Min 900 (add $body_weight 200) }}
{{ with $weights.body }}{{ if ge (len .) 2 }}{{ $body_weight_bold = index . 1 }}{{ end }}{{ end }}
<style>
:root {
/* Typography — Font Families */
--font-heading: {{ $heading_css | safeCSS }};
--font-body: {{ $body_css | safeCSS }};
--font-code: {{ $code_css | safeCSS }};
--font-nav: {{ $nav_css | safeCSS }};
/* Typography — Font Weights */
--font-weight-heading: {{ $heading_weight }};
--font-weight-body: {{ $body_weight }};
--hb-font-weight-body-bold: {{ $body_weight_bold }};
/* Typography — Line Heights */
--font-leading-heading: {{ $leading.heading }};
--font-leading-body: {{ $leading.body }};
--font-leading-code: {{ $leading.code }};
/* Typography — Letter Spacing */
--font-tracking-heading: {{ $tracking.heading | safeCSS }};
--font-tracking-body: {{ $tracking.body | safeCSS }};
--font-tracking-caps: {{ $tracking.caps | safeCSS }};
/* Typography — Font Sizes */
--hb-font-size-base: {{ $font_size_base | safeCSS }};
--hb-font-size-sm: {{ $font_size_sm | safeCSS }};
--hb-font-size-lg: {{ $font_size_lg | safeCSS }};
/* Typography — Font Family Alias (Tailwind v4 compat) */
--font-family-sans: {{ $body_css | safeCSS }};
}
</style>
+4 -76
View File
@@ -202,82 +202,10 @@
<title>{{$title}}</title>
{{/* Load font theme - uses typography config from get_theme_config */}}
{{/* Supported values: 'sans' (Inter, default), 'serif' (Roboto Slab), 'native' (system fonts) */}}
{{ $font_setting := $theme_config.typography.font | default "sans" }}
{{ $use_custom_font := true }}
{{ $font_family := "Inter var" }}
{{ $font_file := "Inter.var.woff2" }}
{{ $font_type := "woff2" }}
{{ if eq $font_setting "native" }}
{{/* Native system font stack - no custom font loaded */}}
{{ $use_custom_font = false }}
{{ else if eq $font_setting "serif" }}
{{ $font_file = "RobotoSlab-VariableFont_wght.ttf" }}
{{ $font_type = "truetype" }}
{{ end }}
{{/* Default case (sans or any unrecognized value) uses Inter */}}
{{/* Map size tokens to CSS custom properties */}}
{{ $font_size_base := "1rem" }}
{{ $font_size_scale := "1.25" }}
{{ if eq $theme_config.typography.size "sm" }}
{{ $font_size_base = "0.875rem" }}
{{ $font_size_scale = "1.2" }}
{{ else if eq $theme_config.typography.size "lg" }}
{{ $font_size_base = "1.125rem" }}
{{ $font_size_scale = "1.333" }}
{{ else if eq $theme_config.typography.size "xl" }}
{{ $font_size_base = "1.25rem" }}
{{ $font_size_scale = "1.414" }}
{{ end }}
{{/* Map radius tokens to CSS values */}}
{{ $radius_value := "0.5rem" }}
{{ if eq $theme_config.layout.radius "none" }}
{{ $radius_value = "0" }}
{{ else if eq $theme_config.layout.radius "sm" }}
{{ $radius_value = "0.25rem" }}
{{ else if eq $theme_config.layout.radius "lg" }}
{{ $radius_value = "0.75rem" }}
{{ else if eq $theme_config.layout.radius "full" }}
{{ $radius_value = "9999px" }}
{{ end }}
{{/* Map spacing tokens to CSS values */}}
{{ $spacing_base := "1rem" }}
{{ $spacing_section := "4rem" }}
{{ if eq $theme_config.layout.spacing "compact" }}
{{ $spacing_base = "0.75rem" }}
{{ $spacing_section = "2.5rem" }}
{{ else if eq $theme_config.layout.spacing "spacious" }}
{{ $spacing_base = "1.25rem" }}
{{ $spacing_section = "6rem" }}
{{ end }}
<style>
:root {
/* Typography tokens */
--hb-font-size-base: {{ $font_size_base }};
--hb-font-size-scale: {{ $font_size_scale }};
/* Layout tokens */
--hb-radius: {{ $radius_value }};
--hb-spacing-base: {{ $spacing_base }};
--hb-spacing-section: {{ $spacing_section }};
}
{{ if $use_custom_font }}
{{ $font_resource := resources.Get (printf "dist/font/%s" $font_file) }}
@font-face {
font-family: '{{$font_family}}';
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url({{ $font_resource.RelPermalink }}) format({{$font_type}});
}
{{ end }}
</style>
{{/* Typography: font loading, font families, and sizes */}}
{{ partial "functions/typography.html" $theme_config }}
{{/* Layout tokens: radius and spacing */}}
{{ partial "functions/layout_tokens.html" $theme_config }}
{{ if .Params.design.background.image.filename }}
{{/* See Hugo note on linking assets in styles: https://github.com/gohugoio/hugoThemes#common-permalink-issues */}}
@@ -59,10 +59,8 @@ hugoblox:
# Font and text sizing
# ────────────────────────────────────────────────────────────────────────────
typography:
# Font: 'sans' (Inter), 'serif' (Roboto Slab), or 'native' (system fonts)
font: "sans"
# Size: 'sm', 'md', 'lg', or 'xl' (affects base font size and scale)
size: "md"
# Theme pack: name from data/fonts/
pack: "academic"
# ────────────────────────────────────────────────────────────────────────────
# LAYOUT
@@ -59,10 +59,8 @@ hugoblox:
# Font and text sizing
# ────────────────────────────────────────────────────────────────────────────
typography:
# Font: 'sans' (Inter), 'serif' (Roboto Slab), or 'native' (system fonts)
font: "sans"
# Size: 'sm', 'md', 'lg', or 'xl' (affects base font size and scale)
size: "md"
# Theme pack: name from data/fonts/
pack: "humanist"
# ────────────────────────────────────────────────────────────────────────────
# LAYOUT
@@ -59,10 +59,8 @@ hugoblox:
# Font and text sizing
# ────────────────────────────────────────────────────────────────────────────
typography:
# Font: 'sans' (Inter), 'serif' (Roboto Slab), or 'native' (system fonts)
font: "sans"
# Size: 'sm', 'md', 'lg', or 'xl' (affects base font size and scale)
size: "md"
# Theme pack: name from data/fonts/
pack: "developer"
# ────────────────────────────────────────────────────────────────────────────
# LAYOUT
@@ -59,10 +59,8 @@ hugoblox:
# Font and text sizing
# ────────────────────────────────────────────────────────────────────────────
typography:
# Font: 'sans' (Inter), 'serif' (Roboto Slab), or 'native' (system fonts)
font: "sans"
# Size: 'sm', 'md', 'lg', or 'xl' (affects base font size and scale)
size: "md"
# Theme pack: name from data/fonts/
pack: "modern"
# ────────────────────────────────────────────────────────────────────────────
# LAYOUT
@@ -59,10 +59,8 @@ hugoblox:
# Font and text sizing
# ────────────────────────────────────────────────────────────────────────────
typography:
# Font: 'sans' (Inter), 'serif' (Roboto Slab), or 'native' (system fonts)
font: "sans"
# Size: 'sm', 'md', 'lg', or 'xl' (affects base font size and scale)
size: "md"
# Theme pack: name from data/fonts/
pack: "modern"
# ────────────────────────────────────────────────────────────────────────────
# LAYOUT
@@ -34,8 +34,8 @@ hugoblox:
# TYPOGRAPHY
# ────────────────────────────────────────────────────────────────────────────
typography:
font: "sans" # sans | serif | native
size: "md" # sm | md | lg | xl
# Theme pack: name from data/fonts/
pack: "modern"
# ────────────────────────────────────────────────────────────────────────────
# LAYOUT
+2 -4
View File
@@ -59,10 +59,8 @@ hugoblox:
# Font and text sizing
# ────────────────────────────────────────────────────────────────────────────
typography:
# Font: 'sans' (Inter), 'serif' (Roboto Slab), or 'native' (system fonts)
font: "sans"
# Size: 'sm', 'md', 'lg', or 'xl' (affects base font size and scale)
size: "md"
# Theme pack: name from data/fonts/
pack: "modern"
# ────────────────────────────────────────────────────────────────────────────
# LAYOUT
@@ -69,10 +69,8 @@ hugoblox:
# Font and text sizing
# ────────────────────────────────────────────────────────────────────────────
typography:
# Font: 'sans' (Inter), 'serif' (Roboto Slab), or 'native' (system fonts)
font: "sans"
# Size: 'sm', 'md', 'lg', or 'xl' (affects base font size and scale)
size: "md"
# Theme pack: name from data/fonts/
pack: "geometric"
# ────────────────────────────────────────────────────────────────────────────
# LAYOUT