diff --git a/modules/blox/blox/portfolio/README.md b/modules/blox/blox/portfolio/README.md index 7c397faae..da1e4279b 100644 --- a/modules/blox/blox/portfolio/README.md +++ b/modules/blox/blox/portfolio/README.md @@ -43,6 +43,7 @@ A flexible, filterable portfolio block for showcasing work with Alpine.js-powere # text: "Browse All" # Custom text design: columns: 3 + aspect_ratio: photo # Card image shape: photo (3:2), landscape, square, portrait, wide fallback_icon: code-bracket # Or: academic-cap, paint-brush, camera, etc. ``` @@ -95,6 +96,7 @@ featured: true | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `columns` | integer | 3 | Grid columns (2, 3, or 4) | +| `aspect_ratio` | string | `photo` | Card image shape — matches the crop to the box so images aren't double-cropped. One of `photo` (3:2), `landscape` (4:3), `square` (1:1), `portrait` (3:4), `wide` (16:9). | | `fallback_icon` | string | `code-bracket` | Icon shown when item has no image. Supports all Hugo Blox icon packs (hero, brands, devicon, emoji, custom). Format: `icon-name` or `pack/icon-name` | | `status_badge.enable` | boolean | true | Show or hide the status badge | diff --git a/modules/blox/blox/portfolio/block.html b/modules/blox/blox/portfolio/block.html index e3db80fb2..3928a0046 100644 --- a/modules/blox/blox/portfolio/block.html +++ b/modules/blox/blox/portfolio/block.html @@ -173,6 +173,28 @@ {{ $fallback_icon = $fallback_raw }} {{ end }} +{{/* Card image aspect ratio (square | landscape | portrait | wide | photo) + The chosen ratio drives BOTH the CSS aspect box and the `Fill` dimensions, + so the box always matches the crop (one predictable crop at any width / + column count). Every class string is written out literally so Tailwind's + scanner generates the utilities. Photo (3:2) is the default with a fixed 600x400 crop. */}} +{{ $ratio_map := dict + "square" (dict "class" "aspect-square" "fill" "600x600 webp") + "landscape" (dict "class" "aspect-[4/3]" "fill" "600x450 webp") + "portrait" (dict "class" "aspect-[3/4]" "fill" "480x640 webp") + "wide" (dict "class" "aspect-[16/9]" "fill" "800x450 webp") + "photo" (dict "class" "aspect-[3/2]" "fill" "600x400 webp") +}} +{{ $ratio_name := "photo" }} +{{ $ratio_raw := index $design "aspect_ratio" }} +{{ if eq (printf "%T" $ratio_raw) "string" }} + {{ $trimmed := lower (strings.TrimSpace $ratio_raw) }} + {{ if $trimmed }}{{ $ratio_name = $trimmed }}{{ end }} +{{ end }} +{{ $ratio := index $ratio_map $ratio_name | default (index $ratio_map "photo") }} +{{ $ratio_class := index $ratio "class" }} +{{ $ratio_fill := index $ratio "fill" }} +
{{/* Header */}} @@ -271,7 +293,7 @@

class="group relative flex flex-col bg-white dark:bg-white/[0.03] backdrop-blur-xl rounded-2xl border border-gray-200 dark:border-white/[0.08] overflow-hidden hover:border-primary-500/50 hover:bg-gray-50 dark:hover:bg-white/[0.06] transition-all duration-300 hover:shadow-xl hover:shadow-primary-500/10 card-hover-lift" > {{/* Card Header / Image */}} -
+
{{ $image := $item.Resources.GetMatch "{featured,cover,thumbnail}*" }} {{ if $image }} {{ if not (reflect.IsImageResourceProcessable $image) }} @@ -281,7 +303,7 @@

class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" > {{ else }} - {{ $img := $image.Fill "600x400 webp" }} + {{ $img := $image.Fill $ratio_fill }}