Add featured image system with focal points and responsive XL split

- featured image: Enable focal point to be set by user in front matter
- pages: Featured image responsively transforms to split view on XL monitors
- pages: Refactor page title, metadata, and image into one reusable module
- archetypes: Migrate to folder approach and update image options
- post widget: Refactor detailed layout to use featured image
- accessibility: Add alt tag to header and featured image
- accessibility: Improve text contrast based on Lighthouse audit
- publication: Entirely deprecate old `image` front matter option
- docs: Remove header image option (was never a documented feature)
- project widget: Add `noopener` to external links

See #708
Fix #728
Fix #704
Fix #705
See #718
This commit is contained in:
George Cushen committed 2018-10-13 21:58:51 +01:00
1 parent 2afcb642db
commit c37cf33fc6
25 files changed
+229 -159

No files matched your search

+7 -4
View File
@@ -9,9 +9,12 @@ tags = []
categories = []
# Featured image
# Place your image in the `static/img/` folder and reference its filename below, e.g. `image = "example.jpg"`.
[header]
image = ""
caption = ""
# To use, add an image named `featured.jpg/png` to your page's folder.
[image]
# Caption (optional)
caption = ""
# Focal point (optional)
# Options: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight
focal_point = ""
+++
-24
View File
@@ -1,24 +0,0 @@
+++
title = "{{ replace .Name "-" " " | title }}"
date = {{ .Date }}
draft = false
# Authors. Comma separated list, e.g. `["Bob Smith", "David Jones"]`.
authors = []
# Tags and categories
# For example, use `tags = []` for no tags, or the form `tags = ["A Tag", "Another Tag"]` for one or more tags.
tags = []
categories = []
# Featured image
# Place your image in the `static/img/` folder and reference its filename below, e.g. `image = "example.jpg"`.
# Use `caption` to display an image caption.
# Markdown linking is allowed, e.g. `caption = "[Image credit](http://example.org)"`.
# Set `preview` to `false` to disable the thumbnail in listings.
[header]
image = ""
caption = ""
preview = true
+++
+23
View File
@@ -0,0 +1,23 @@
+++
title = "{{ replace .Name "-" " " | title }}"
date = {{ .Date }}
draft = false
# Authors. Comma separated list, e.g. `["Bob Smith", "David Jones"]`.
authors = []
# Tags and categories
# For example, use `tags = []` for no tags, or the form `tags = ["A Tag", "Another Tag"]` for one or more tags.
tags = []
categories = []
# Featured image
# To use, add an image named `featured.jpg/png` to your page's folder.
[image]
# Caption (optional)
caption = ""
# Focal point (optional)
# Options: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight
focal_point = ""
+++
+8 -3
View File
@@ -14,7 +14,12 @@ summary = ""
external_link = ""
# Featured image
# To use, add an image named `featured.jpg/png` to your project's folder.
[header]
caption = "" # Optionally add a caption to the featured image.
# To use, add an image named `featured.jpg/png` to your page's folder.
[image]
# Caption (optional)
caption = ""
# Focal point (optional)
# Options: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight
focal_point = ""
+++
@@ -25,9 +25,6 @@ publication_short = ""
abstract = ""
abstract_short = ""
# Featured image thumbnail (optional)
image_preview = ""
# Is this a selected publication? (true/false)
selected = false
@@ -60,16 +57,13 @@ url_source = ""
# Digital Object Identifier (DOI)
doi = ""
# Does this page contain LaTeX math? (true/false)
math = false
# Does this page require source code highlighting? (true/false)
highlight = true
# Featured image
# Place your image in the `static/img/` folder and reference its filename below, e.g. `image = "example.jpg"`.
[header]
image = ""
caption = ""
# To use, add an image named `featured.jpg/png` to your page's folder.
[image]
# Caption (optional)
caption = ""
# Focal point (optional)
# Options: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight
focal_point = ""
+++
@@ -42,16 +42,13 @@ url_slides = ""
url_video = ""
url_code = ""
# Does the content use math formatting?
math = false
# Does the content use source code highlighting?
highlight = true
# Featured image
# Place your image in the `static/img/` folder and reference its filename below, e.g. `image = "example.jpg"`.
[header]
image = ""
caption = ""
# To use, add an image named `featured.jpg/png` to your page's folder.
[image]
# Caption (optional)
caption = ""
# Focal point (optional)
# Options: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight
focal_point = ""
+++
@@ -1,5 +1,6 @@
+++
title = "Academic: the website designer for Hugo"
subtitle = "Create a beautifully simple website in under 10 minutes :rocket:"
date = 2016-04-20T00:00:00
lastmod = 2018-01-13T00:00:00
@@ -11,7 +12,7 @@ authors = []
tags = ["Academic"]
summary = "Create a beautifully simple website or blog in under 10 minutes."
[header]
[image]
caption = "Image credit: [**Unsplash**](https://unsplash.com/photos/CpkOjOcXdUY)"
[[gallery_item]]
@@ -17,6 +17,11 @@ external_link = "http://example.org"
# Featured image
# To use, add an image named `featured.jpg/png` to your project's folder.
[header]
caption = "Photo by Toa Heftiba on Unsplash" # Optionally add a caption to the featured image.
[image]
# Caption (optional)
caption = "Photo by Toa Heftiba on Unsplash"
# Focal point (optional)
# Options: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight
focal_point = "Smart"
+++
@@ -17,8 +17,13 @@ external_link = ""
# Featured image
# To use, add an image named `featured.jpg/png` to your project's folder.
[header]
caption = "Photo by rawpixel on Unsplash" # Optionally add a caption to the featured image.
[image]
# Caption (optional)
caption = "Photo by rawpixel on Unsplash"
# Focal point (optional)
# Options: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight
focal_point = "Smart"
+++
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis posuere tellus ac convallis placerat. Proin tincidunt magna sed ex sollicitudin condimentum. Sed ac faucibus dolor, scelerisque sollicitudin nisi. Cras purus urna, suscipit quis sapien eu, pulvinar tempor diam. Quisque risus orci, mollis id ante sit amet, gravida egestas nisl. Sed ac tempus magna. Proin in dui enim. Donec condimentum, sem id dapibus fringilla, tellus enim condimentum arcu, nec volutpat est felis vel metus. Vestibulum sit amet erat at nulla eleifend gravida.
+1 -3
View File
@@ -7,11 +7,9 @@
{{ partial "header.html" . }}
{{ partial "navbar.html" . }}
{{ partial "header_image.html" . }}
{{ partial "page_header.html" . }}
<div class="universal-wrapper">
{{ with .Title }}<h1>{{ . }}</h1>{{ end }}
{{ with .Content }}
<div class="article-style" itemprop="articleBody">{{ . }}</div>
{{ end }}
+1 -4
View File
@@ -3,12 +3,9 @@
<article class="article" itemscope itemtype="http://schema.org/Article">
{{ partial "header_image.html" . }}
{{ partial "page_header.html" . }}
<div class="article-container">
<h1 itemprop="name">{{ .Title }}</h1>
{{ partial "article_metadata" (dict "content" . "is_list" 0) }}
<div class="article-style" itemprop="articleBody">
{{ .Content }}
+50 -13
View File
@@ -642,7 +642,7 @@ ul.share li:hover i {
}
/*************************************************
* Blog Articles
* Page content style
**************************************************/
article {
@@ -652,12 +652,45 @@ article {
.article-container {
max-width: 760px;
padding: 1rem 20px 0 20px;
padding: 0 20px 0 20px;
margin: 0 auto 0 auto;
}
.split-header {
margin-bottom: 2rem;
}
.split-header .share-box {
float: left;
}
.page-subtitle {
font-size: 1.15rem;
color: rgba(0,0,0,.54);
margin-bottom: 1rem;
}
.split-header .page-subtitle {
margin-bottom: 1.5rem;
}
.split-header-content {
max-width: 612px;
width: 100%;
padding: 60px 60px 32px 0;
margin-left: auto;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.split-header-image {
position: relative; /* Required for caption positioning */
clear: both;
max-width: 580px;
}
.article-header {
position: relative;
position: relative; /* Required for caption positioning */
clear: both;
}
@@ -700,12 +733,16 @@ article {
transition: color 0.6s ease;
}
.text-muted {
color: rgba(0,0,0,0.54) !important; /* Override Bootstrap */
}
.article-metadata {
margin-bottom: 15px;
overflow: hidden;
font-size: 14px;
letter-spacing: 0.03em;
color: #888;
color: rgba(0,0,0,0.54);
}
/* For article page only, not lists. */
@@ -841,13 +878,13 @@ article .article-metadata {
.pub-list-item .pub-authors {
line-height: normal;
font-style: normal;
font-size: 1rem;
color: #3170A5;
font-size: 0.9rem;
color: rgba(0,0,0,0.54);
}
.pub-list-item .pub-publication {
color: #090;
font-size: 1rem;
color: rgba(0,0,0,0.54);
font-size: 0.9rem;
}
.pub-list-item .pub-links {
@@ -1029,7 +1066,7 @@ article .article-metadata {
}
.card .card-text p {
color: #999999;
color: rgba(0,0,0,0.54);
font-size: 0.75rem;
}
@@ -1126,7 +1163,7 @@ footer p {
.site-footer,
footer a#back_to_top i {
color: #899596;
color: rgba(0,0,0,0.54);
}
/**************************************************
@@ -1237,18 +1274,18 @@ a.badge:hover {
.btn-toolbar .btn.btn-primary:hover,
.btn-toolbar .btn.btn-primary:focus {
background-color: {{ .Get "primary_dark" }} !important;
background-color: {{ .Get "primary_light" }} !important;
}
.btn-toolbar .btn.btn-primary:active,
.btn-toolbar .btn.btn-primary.active {
background-color: {{ .Get "primary_light" }} !important;
background-color: {{ .Get "primary_dark" }} !important;
}
.btn-primary:not(:disabled):not(.disabled).active:focus,
.btn-primary:not(:disabled):not(.disabled):active:focus,
.show > .btn-primary.dropdown-toggle:focus {
box-shadow: 0 0 0 .2rem {{ .Get "primary_dark" }};
box-shadow: 0 0 0 .2rem {{ .Get "primary_light" }};
}
/*************************************************
-2
View File
@@ -30,8 +30,6 @@
</div>
<article class="article" itemscope itemtype="http://schema.org/Article">
{{ partial "header_image.html" . }}
<div class="docs-article-container">
<h1 itemprop="name">{{ .Title }}</h1>
-21
View File
@@ -1,21 +0,0 @@
{{ $featured := (.Resources.ByType "image").GetMatch "*featured*" }}
{{ with $featured }}
{{ $image := .Fill "1600x400" }}
<div class="article-header">
<img src="{{ $image.RelPermalink }}" class="article-banner" itemprop="image" style="width: 100%; min-height: 400px; height: auto;">
{{ with $.Params.header.caption }}<span class="article-header-caption">{{ . | markdownify | emojify }}</span>{{ end }}
</div>
{{end}}
{{ if and .Params.header.image (not $featured) }}
<div class="article-header">
{{ $img_src := urls.Parse .Params.header.image }}
{{ if $img_src.Scheme }}
<img src="{{ .Params.header.image }}" class="article-banner" itemprop="image">
{{ else }}
<img src="{{ (printf "/img/%s" .Params.header.image) | relURL }}" class="article-banner" itemprop="image">
{{ end }}
{{ with .Params.header.caption }}<span class="article-header-caption">{{ . | markdownify | emojify }}</span>{{ end }}
</div>
{{end}}
+92
View File
@@ -0,0 +1,92 @@
{{ $page := . }}
{{ $featured := (.Resources.ByType "image").GetMatch "*featured*" }}
{{ $anchor := $page.Params.image.focal_point | default "Smart" }}
{{/* Set default titles for node pages */}}
{{ $title := .Title }}
{{ if and (not $title) .IsNode }}
{{ if eq .Type "post" }}
{{ $title = i18n "posts" }}
{{ else if eq .Type "talk" }}
{{ $title = i18n "talks" }}
{{ else if eq .Type "publication" }}
{{ $title = i18n "publications" }}
{{end}}
{{end}}
{{/* Header image */}}
{{ if and .Params.header.image (not $featured) }}
<div class="article-header">
{{ $img_src := urls.Parse .Params.header.image }}
{{ if $img_src.Scheme }}
<img src="{{ .Params.header.image }}" class="article-banner" itemprop="image" alt="">
{{ else }}
<img src="{{ (printf "/img/%s" .Params.header.image) | relURL }}" class="article-banner" itemprop="image" alt="">
{{ end }}
{{ with .Params.header.caption }}<span class="article-header-caption">{{ . | markdownify | emojify }}</span>{{ end }}
</div>
{{end}}
{{/* Featured image */}}
{{ with $featured }}
{{ $image := .Fill (printf "1600x400 q90 %s" $anchor) }}
<div class="article-header d-xl-none">
<img src="{{ $image.RelPermalink }}" class="article-banner" itemprop="image" alt="">
{{ with $.Params.image.caption }}<span class="article-header-caption">{{ . | markdownify | emojify }}</span>{{ end }}
</div>
{{ $image := .Fill (printf "680x500 q90 %s" $anchor) }}
<div class="container-fluid split-header d-none d-xl-block">
<div class="row">
<div class="col-6">
<div class="split-header-content">
<h1 itemprop="name">{{ $title }}</h1>
{{ with $page.Params.subtitle }}
<p class="page-subtitle">{{ . | markdownify | emojify }}</p>
{{end}}
{{ partial "page_metadata" (dict "content" $page "is_list" 1) }}
{{ partial "share.html" $page }}
</div>
</div>
<div class="col-6">
<div class="split-header-image">
<img src="{{ $image.RelPermalink }}" itemprop="image" alt="">
{{ with $.Params.image.caption }}<span class="article-header-caption">{{ . | markdownify | emojify }}</span>{{ end }}
</div>
</div>
</div>
</div>
<div class="article-container d-xl-none">
<h1 itemprop="name">{{ $title }}</h1>
{{ with $page.Params.subtitle }}
<p class="page-subtitle">{{ . | markdownify | emojify }}</p>
{{end}}
{{ partial "page_metadata" (dict "content" $page "is_list" 0) }}
</div>
{{else}}
{{/* Case when page has no image */}}
{{/* Wider container for nodes */}}
{{ $ctnr := "article-container" }}
{{ if $page.IsNode }}
{{ $ctnr = "universal-wrapper" }}
{{end}}
<div class="{{$ctnr}} pt-3">
<h1 itemprop="name">{{ $title }}</h1>
{{ with $page.Params.subtitle }}
<p class="page-subtitle">{{ . | markdownify | emojify }}</p>
{{end}}
{{ if not .IsNode }}
{{ partial "page_metadata" (dict "content" $page "is_list" 0) }}
{{end}}
</div>
{{end}}
File renamed without changes.
+6 -9
View File
@@ -1,17 +1,14 @@
{{ $post := .post }}
<div class="card-simple" itemscope itemprop="blogPost" itemtype="http://schema.org/BlogPosting">
{{ partial "article_metadata" (dict "content" $post "is_list" 1) }}
{{ partial "page_metadata" (dict "content" $post "is_list" 1) }}
{{ $preview := $post.Params.header.preview | default true }}
{{ if and $post.Params.header.image $preview }}
{{ $resource := ($post.Resources.ByType "image").GetMatch "*featured*" }}
{{ $anchor := $post.Params.image.focal_point | default "Smart" }}
{{ with $resource }}
{{ $image := .Fill (printf "918x517 q90 %s" $anchor) }}
<a href="{{ $post.RelPermalink }}">
{{ $img_src := urls.Parse $post.Params.header.image }}
{{ if $img_src.Scheme }}
<img src="{{ $post.Params.header.image }}" class="article-banner" itemprop="image">
{{ else }}
<img src="{{ "/img/" | relURL }}{{ $post.Params.header.image }}" class="article-banner" itemprop="image">
{{ end }}
<img src="{{ $image.RelPermalink }}" class="article-banner" itemprop="image" alt="">
</a>
{{end}}
<h3 class="article-title" itemprop="headline">
+1 -1
View File
@@ -20,7 +20,7 @@
{{ end }}
<div class="stream-meta">
{{ partial "article_metadata" (dict "content" $post "is_list" 1) }}
{{ partial "page_metadata" (dict "content" $post "is_list" 1) }}
</div>
</div>
+4 -3
View File
@@ -75,14 +75,15 @@
{{ $.Scratch.Set "target" "" }}
{{ if $project.Params.external_link }}
{{ $.Scratch.Set "project_url" $project.Params.external_link }}
{{ $.Scratch.Set "target" "target=\"_blank\"" }}
{{ $.Scratch.Set "target" "target=\"_blank\" rel=\"noopener\"" }}
{{ end }}
{{ $resource := ($project.Resources.ByType "image").GetMatch "*featured*" }}
{{ $anchor := $project.Params.image.focal_point | default "Smart" }}
<div class="col-12 col-md-6 col-lg-4 project-item isotope-item {{ delimit (apply .Params.tags "urlize" ".") " " }}">
<div class="card">
{{ with $resource }}
{{ $image := .Fill "550x550" }}
<a href="{{ $.Scratch.Get "project_url" }}" title="" class="card-image hover-overlay"
{{ $image := .Fill (printf "550x550 q90 %s" $anchor) }}
<a href="{{ $.Scratch.Get "project_url" }}" {{ $.Scratch.Get "target" | safeHTMLAttr }} class="card-image hover-overlay"
{{ $.Scratch.Get "target" | safeHTMLAttr }}>
<img src="{{ $image.RelPermalink }}" alt="" class="img-responsive">
</a>
+1 -10
View File
@@ -3,18 +3,9 @@
<article class="article article-project" itemscope itemtype="http://schema.org/Article">
{{ partial "header_image.html" . }}
{{ partial "page_header.html" . }}
<div class="article-container">
<div class="pub-title">
<h1 itemprop="name">{{ .Title }}</h1>
<span class="pub-authors" itemprop="author">&nbsp;</span>
<span class="float-right">
{{ partial "share.html" . }}
</span>
</div>
{{ with .Params.external_link }}
<a class="btn btn-outline-primary my-1" href="{{ . }}" target="_blank" rel="noopener">{{ i18n "open_project_site" }}</a>
{{ end }}
+1 -14
View File
@@ -2,22 +2,9 @@
{{ partial "navbar.html" . }}
<div class="pub" itemscope itemtype="http://schema.org/CreativeWork">
{{ partial "header_image.html" . }}
{{ partial "page_header.html" . }}
<div class="article-container">
<h1 itemprop="name">{{ .Title }}</h1>
<span class="pub-authors" itemprop="author">
{{ with .Params.authors }}
{{ delimit . ", " | markdownify }}
{{ end }}
</span>
<span class="float-right">
{{ partial "share.html" . }}
</span>
{{ if .Params.image }}
<img src="{{ "/img/" | relURL }}{{ .Params.image }}" class="pub-banner" itemprop="image">
{{end}}
{{ if .Params.abstract }}
<h3>{{ i18n "abstract" }}</h3>
+1 -3
View File
@@ -1,12 +1,10 @@
{{ partial "header.html" . }}
{{ partial "navbar.html" . }}
{{ partial "header_image.html" . }}
{{ partial "page_header.html" . }}
<div class="universal-wrapper">
<h1>{{ .Title | default (i18n "posts") }}</h1>
{{ with .Content }}
<div class="article-style" itemprop="articleBody">{{ . }}</div>
{{ end }}
+1 -2
View File
@@ -1,12 +1,11 @@
{{ partial "header.html" . }}
{{ partial "navbar.html" . }}
{{ partial "header_image.html" . }}
{{ partial "page_header.html" . }}
<div class="universal-wrapper">
<div class="row">
<div class="col-lg-12">
<h1>{{ .Title | default (i18n "publications") }}</h1>
{{ with .Content }}
<div class="article-style" itemprop="articleBody">{{ . }}</div>
+1 -2
View File
@@ -1,12 +1,11 @@
{{ partial "header.html" . }}
{{ partial "navbar.html" . }}
{{ partial "header_image.html" . }}
{{ partial "page_header.html" . }}
<div class="universal-wrapper">
<div class="row">
<div class="col-lg-12">
<h1>{{ .Title | default (i18n "talks") }}</h1>
{{ with .Content }}
<div class="article-style" itemprop="articleBody">{{ . }}</div>
+1 -13
View File
@@ -2,22 +2,10 @@
{{ partial "navbar.html" . }}
<div class="pub" itemscope itemtype="http://schema.org/Event">
{{ partial "header_image.html" . }}
{{ partial "page_header.html" . }}
<div class="article-container">
<div class="pub-title">
<h1 itemprop="name">{{ .Title }}</h1>
<span class="pub-authors" itemprop="author">
{{ with .Params.authors }}
{{ delimit . ", " | markdownify }}
{{ end }}
</span>
<span class="float-right">
{{ partial "share.html" . }}
</span>
</div>
{{ if .Params.abstract }}
<h3>{{ i18n "abstract" }}</h3>
<p class="pub-abstract" itemprop="text">{{ .Params.abstract | markdownify }}</p>