diff --git a/data/fonts/classic.toml b/data/fonts/classic.toml
new file mode 100644
index 00000000..4b9e568c
--- /dev/null
+++ b/data/fonts/classic.toml
@@ -0,0 +1,14 @@
+# Font style metadata
+name = "Classic"
+
+# Optional Google font URL
+google_fonts = "Playfair Display:400,700|Fauna One"
+
+# Font families
+heading_font = "Playfair Display"
+body_font = "Fauna One"
+mono_font = "Roboto Mono"
+
+# Font size
+font_size = "20"
+font_size_small = "16"
diff --git a/data/fonts/default.toml b/data/fonts/default.toml
new file mode 100644
index 00000000..9ca2bc2a
--- /dev/null
+++ b/data/fonts/default.toml
@@ -0,0 +1,14 @@
+# Font style metadata
+name = "Default"
+
+# Optional Google font URL
+google_fonts = "Montserrat:400,700|Roboto:400,400italic,700|Roboto+Mono"
+
+# Font families
+heading_font = "Montserrat"
+body_font = "Roboto"
+mono_font = "Roboto Mono"
+
+# Font size
+font_size = "20"
+font_size_small = "16"
diff --git a/data/themes/default.toml b/data/themes/default.toml
new file mode 100644
index 00000000..738be90a
--- /dev/null
+++ b/data/themes/default.toml
@@ -0,0 +1,20 @@
+# Theme metadata
+name = "Default"
+
+# Is theme light or dark?
+light = true
+
+# Primary
+primary = "#0095eb"
+primary_light = "#6ec6ff"
+primary_dark = "#0069c0"
+
+# Menu
+menu_primary = "#fff"
+menu_text = "#34495e"
+menu_text_active = "#0095eb"
+menu_title = "#2b2b2b"
+
+# Home sections
+home_section_odd = "rgb(255, 255, 255)"
+home_section_even = "rgb(247, 247, 247)"
diff --git a/data/themes/forest.toml b/data/themes/forest.toml
new file mode 100644
index 00000000..a1559333
--- /dev/null
+++ b/data/themes/forest.toml
@@ -0,0 +1,20 @@
+# Theme metadata
+name = "Forest"
+
+# Is theme light or dark?
+light = true
+
+# Primary
+primary = "#4caf50"
+primary_light = "#80e27e"
+primary_dark = "#087f23"
+
+# Menu
+menu_primary = "#4caf50"
+menu_text = "#fff"
+menu_text_active = "#1b5e20"
+menu_title = "#fff"
+
+# Home sections
+home_section_odd = "rgb(255, 255, 255)"
+home_section_even = "rgb(247, 247, 247)"
diff --git a/data/themes/ocean.toml b/data/themes/ocean.toml
new file mode 100644
index 00000000..3aa4e129
--- /dev/null
+++ b/data/themes/ocean.toml
@@ -0,0 +1,20 @@
+# Theme metadata
+name = "Ocean"
+
+# Is theme light or dark?
+light = true
+
+# Primary
+primary = "#3f51b5"
+primary_light = "#757de8"
+primary_dark = "#002984"
+
+# Menu
+menu_primary = "#3f51b5" # 500
+menu_text = "#fff"
+menu_text_active = "#8c9eff" # A100
+menu_title = "#fff"
+
+# Home sections
+home_section_odd = "rgb(255, 255, 255)"
+home_section_even = "rgb(247, 247, 247)"
diff --git a/exampleSite/config.toml b/exampleSite/config.toml
index 241b2785..8213d4b5 100644
--- a/exampleSite/config.toml
+++ b/exampleSite/config.toml
@@ -5,6 +5,7 @@ theme = "academic"
enableEmoji = true
footnotereturnlinkcontents = "^"
ignoreFiles = ["\\.Rmd$", "\\.Rmarkdown$", "_files$", "_cache$"]
+paginate = 10
# Enable comments by entering your Disqus shortname
disqusShortname = ""
@@ -16,10 +17,22 @@ googleAnalytics = ""
defaultContentLanguage = "en"
defaultContentLanguageInSubdir = false
+[outputs]
+ home = [ "HTML", "CSS" ]
+
[blackfriday]
hrefTargetBlank = true
[params]
+ # Color theme.
+ # Choose from `default`, `ocean`, or `forest`.
+ color_theme = "default"
+
+ # Font style.
+ # Choose from `default` or `classic`.
+ font = "default"
+
+ # Your details.
name = "Lena Smith"
role = "Professor of Artificial Intelligence"
organization = "Stanford University"
diff --git a/exampleSite/content/post/getting-started.md b/exampleSite/content/post/getting-started.md
index a3a61f0d..d7ef29b8 100644
--- a/exampleSite/content/post/getting-started.md
+++ b/exampleSite/content/post/getting-started.md
@@ -90,6 +90,21 @@ Refer to our guide on [managing content]({{< ref "post/managing-content.md" >}})
[How to remove unused widgets and content pages]({{< ref "post/managing-content.md#removing-content" >}}).
+### Themes
+
+The following color themes are available and can be set by the `color_theme` option in `config.toml`:
+
+- default (light blue)
+- ocean (deep blue)
+- forest (green)
+
+### Font
+
+The following font styles are available and can be set by the `font` option in `config.toml`:
+
+- default (modern)
+- classic
+
### Customization & updating
Continue reading below for advanced customization tips and instructions for keeping the framework up-to-date with any improvements that become available.
@@ -109,12 +124,6 @@ To create a dropdown sub-menu, add `identifier = "something"` to the parent item
Save your main icon and mobile icon as square PNG images named `icon.png` and `apple-touch-icon.png`, respectively. Place them in your root `static/img/` folder.
-### Theme color (CSS)
-
-You can link custom CSS assets (relative to your root `static/css`) from your `config.toml` using `custom_css = ["custom.css"]`.
-
-For example, lets make a green theme. First, define `custom_css = ["green.css"]` in `config.toml`. Then we can download the example [green theme](https://gist.github.com/gcushen/d5525a4506b9ccf83f2bce592a895495) and save it as `static/css/green.css`, relative to your website root (i.e. **not** in the `themes` directory).
-
### Analytics
To enable [Google Analytics](http://www.google.com/analytics), add your tracking code in `config.toml` similarly to `googleAnalytics = "UA-12345678-9"`.
@@ -148,6 +157,12 @@ For further details on Hugo's internationalization and multilingual features, re
Where `:slug` defaults to the filename of the post, excluding the file extension. However, slug may be overridden on a per post basis if desired, simply by setting `slug = "my-short-post-title"` in your post preamble.
+### Advanced style customization (CSS)
+
+For advanced customization of the style, you can link custom CSS assets (relative to your root `static/css`) from your `config.toml` using `custom_css = ["custom.css"]`.
+
+For example, let's override some of Academic's default styles. First, define `custom_css = ["override.css"]` in `config.toml`. Then we can create the file `static/css/override.css`, relative to your website root (i.e. **not** in the `themes` directory). Add your custom CSS to this file.
+
## Updating
diff --git a/layouts/index.css b/layouts/index.css
new file mode 100644
index 00000000..d1ae6b73
--- /dev/null
+++ b/layouts/index.css
@@ -0,0 +1,9 @@
+{{- $scr := .Scratch -}}
+{{- $scr.Set "site" $.Site -}}
+
+{{- partial "css/parse_theme.css" . -}}
+
+{{- $scr.Set "css" (partial "css/academic.css" $scr) -}}
+
+{{/* Return parsed CSS. */}}
+{{- $scr.Get "css" -}}
diff --git a/static/css/hugo-academic.css b/layouts/partials/css/academic.css
similarity index 86%
rename from static/css/hugo-academic.css
rename to layouts/partials/css/academic.css
index b9b57100..4dbaa583 100644
--- a/static/css/hugo-academic.css
+++ b/layouts/partials/css/academic.css
@@ -21,14 +21,14 @@
}
html {
- font-family: 'Merriweather', serif;
- font-size: 16px;
+ font-family: '{{ .Get "body_font" }}', sans-serif;
+ font-size: {{ .Get "font_size_small" }}px;
color: rgba(0,0,0,0.8);
line-height: 1.65;
}
@media screen and (min-width: 58em) {
html {
- font-size: 20px;
+ font-size: {{ .Get "font_size" }}px;
}
}
@@ -61,7 +61,7 @@ ul, ol, dl {
/* Navigation bar text */
.navbar-default {
- font-family: 'Lato', sans-serif;
+ font-family: '{{ .Get "body_font" }}', sans-serif;
font-weight: 400;
line-height: 1.25;
text-rendering: optimizeLegibility;
@@ -69,7 +69,7 @@ ul, ol, dl {
/* Headings */
h1, h2, h3, h4, h5, h6 {
- font-family: 'Lato', sans-serif;
+ font-family: '{{ .Get "heading_font" }}', sans-serif;
font-weight: 400;
margin-bottom: .5rem;
line-height: 1.25;
@@ -96,14 +96,14 @@ h4, h5, h6 {
a,
h3.article-title a:hover {
- color: #0095eb;
+ color: {{ .Get "primary" }};
text-decoration: none;
transition: color 0.6s ease;
}
a:hover,
a:focus {
- color: #005181;
+ color: {{ .Get "primary" }};
}
img,
@@ -130,7 +130,7 @@ figcaption {
line-height: 1.25;
font-size: 1rem;
margin-bottom: 1.65rem;
- font-family: 'Lato', sans-serif;
+ font-family: '{{ .Get "heading_font" }}', sans-serif;
counter-increment: captions;
}
@@ -143,7 +143,7 @@ figcaption h4 {
pre,
code {
- font-family: 'Roboto Mono', 'Courier New', 'Courier', monospace;
+ font-family: '{{ .Get "mono_font" }}', monospace;
}
pre {
@@ -210,7 +210,7 @@ blockquote p:last-child {
}
.home-section {
- background-color: rgb(255, 255, 255);
+ background-color: {{ .Get "home_section_odd" }};
padding: 110px 0 110px 0;
animation: intro 0.3s both;
animation-delay: 0.15s;
@@ -221,7 +221,7 @@ blockquote p:last-child {
}
.home-section:nth-of-type(even) {
- background-color: rgb(247, 247, 247);
+ background-color: {{ .Get "home_section_even" }};
}
@media screen and (max-width: 768px) {
@@ -238,7 +238,6 @@ blockquote p:last-child {
}
.section-heading p {
- font-family: 'Lato', sans-serif;
font-weight: 400;
font-size: 1.1rem;
color: #b2b2b2;
@@ -261,8 +260,6 @@ blockquote p:last-child {
margin: 0 auto;
border-radius: 50%;
background-size: cover;
- -webkit-background-size: cover;
- -moz-background-size: cover;
}
#profile .portrait-title h2 {
@@ -273,13 +270,13 @@ blockquote p:last-child {
}
#profile .portrait-title h3 {
- font-size: 1.13em;
+ font-size: 1rem;
font-weight: 300;
- color: #AAAAAA;
+ color: rgba(0,0,0, 0.54);
margin: 0px 0 10px 0;
}
-#profile ul.social-icon {
+#profile ul.network-icon {
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
@@ -288,15 +285,15 @@ blockquote p:last-child {
margin-top: 30px;
}
-#profile .social-icon li {
+#profile .network-icon li {
margin-right: 10px;
}
-#profile .social-icon li:last-of-type {
+#profile .network-icon li:last-of-type {
margin-right: 0;
}
-#profile .social-icon li:hover {
+#profile .network-icon li:hover {
transform: scale(1.2)
}
@@ -452,7 +449,7 @@ article {
}
.article-metadata a:hover {
- color: #0095eb;
+ color: {{ .Get "primary" }};
}
.article-list-item {
@@ -503,7 +500,7 @@ article {
**************************************************/
.pub-icon {
- color: #03396c;
+ color: rgba(0, 0, 0, 0.54);
font-size: 0.81em;
padding-top: 6px;
}
@@ -758,16 +755,16 @@ footer a#back_to_top i {
**************************************************/
.btn-primary {
- border-color: #0095eb;
- background: #0095eb;
+ border-color: {{ .Get "primary" }} !important;
+ background: {{ .Get "primary" }} !important;
}
.btn-primary:hover,
-.btn-primary:focus,
.btn-primary:active,
.btn-primary.active,
+.btn-primary:visited,
.open > .dropdown-toggle.btn-primary {
- background: #0095eb;
+ background: {{ .Get "primary" }} !important;
}
/*************************************************
@@ -790,12 +787,12 @@ footer a#back_to_top i {
.btn-toolbar .btn.btn-primary:hover,
.btn-toolbar .btn.btn-primary:focus {
- background-color: rgba(0,149,235,0.6);
+ background-color: {{ .Get "primary_dark" }} !important;
}
.btn-toolbar .btn.btn-primary:active,
.btn-toolbar .btn.btn-primary.active {
- background-color: rgba(0,89,175,1);
+ background-color: {{ .Get "primary_light" }} !important;
}
/*************************************************
@@ -803,14 +800,22 @@ footer a#back_to_top i {
**************************************************/
.btn-outline {
- background-color: transparent;
+ background-color: transparent !important;
color: inherit;
transition: all .5s;
}
.btn-primary.btn-outline {
- color: #0095eb;
- border-color: #0095eb;
+ color: {{ .Get "primary" }} !important;
+ border-color: {{ .Get "primary" }} !important;
+}
+
+.btn-primary.btn-outline:focus {
+ color: {{ .Get "primary" }} !important;
+}
+
+.btn-primary.btn-outline:active {
+ color: #fff !important;
}
.btn-success.btn-outline {
@@ -834,7 +839,7 @@ footer a#back_to_top i {
.btn-info.btn-outline:hover,
.btn-warning.btn-outline:hover,
.btn-danger.btn-outline:hover {
- color: #fff;
+ color: #fff !important;
}
/*************************************************
@@ -846,12 +851,21 @@ footer a#back_to_top i {
}
.navbar-default {
- background: #fff;
+ background: {{ .Get "menu_primary" }};
box-shadow: 0 0.125rem 0.25rem 0 rgba(0,0,0,.11)
}
+.navbar-default .navbar-toggle {
+ border-color: transparent;
+}
+
+.navbar-default .navbar-toggle:focus,
+.navbar-default .navbar-toggle:hover {
+ background-color: transparent;
+}
+
nav#navbar-main li {
- font-size: 16px;
+ font-size: {{ .Get "font_size_small" }}px;
}
.navbar-default .navbar-nav>li>a,
@@ -860,14 +874,20 @@ nav#navbar-main li {
white-space: nowrap;
-webkit-transition: 0.2s ease;
transition: 0.2s ease;
- color: #34495e;
+ color: {{ .Get "menu_text" }};
font-weight: 600;
}
+.navbar-default .navbar-nav>li>a:focus,
+.navbar-default .navbar-nav>li>a:hover {
+ color: {{ .Get "menu_text_active" }};
+ background-color: transparent;
+}
+
.navbar-default .navbar-nav>.active>a,
.navbar-default .navbar-nav>.active>a:focus,
.navbar-default .navbar-nav>.active>a:hover {
- color: #0095eb;
+ color: {{ .Get "menu_text_active" }};
font-weight: 700;
background-color: transparent !important; /* Override Bootstrap. */
}
@@ -880,30 +900,59 @@ nav#navbar-main li {
padding-bottom: 10px;
}
+.navbar-default .navbar-toggle .icon-bar {
+ background-color: {{ .Get "menu_text" }} !important;
+}
+
+.dropdown-menu {
+ background-color: {{ .Get "menu_primary" }} !important;
+}
+
.dropdown-menu > li > a {
display: block;
padding: 3px 20px;
clear: both;
font-weight: 400;
line-height: 1.42857143;
- color: #34495e;
+ color: {{ .Get "menu_text" }};
white-space: nowrap;
}
+.dropdown-menu>li>a:focus,
+.dropdown-menu>li>a:hover {
+ color: {{ .Get "menu_text_active" }};
+ text-decoration: none;
+ background-color: {{ .Get "menu_primary" }};
+}
+
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:focus,
.dropdown-menu > .active > a:hover {
- color: #fff;
+ color: {{ .Get "menu_primary" }};
text-decoration: none;
- background-color: #0095eb;
+ background-color: {{ .Get "menu_text_active" }};
outline: 0;
}
+.navbar-default .navbar-nav>.open>a,
+.navbar-default .navbar-nav>.open>a:focus,
+.navbar-default .navbar-nav>.open>a:hover,
+.navbar-default .navbar-nav>.open>a:visited {
+ color: {{ .Get "menu_text" }} !important;
+ background-color: {{ .Get "menu_primary" }} !important;
+}
+
.navbar-default .navbar-brand {
text-transform: uppercase;
font-weight: bold;
font-size: 1.2em;
- color: #2b2b2b;
+ color: {{ .Get "menu_title" }};
+}
+
+.navbar-default .navbar-brand:focus,
+.navbar-default .navbar-brand:hover {
+ color: {{ .Get "menu_title" }};
+ background-color: transparent;
}
@media screen and (max-width: 1200px) {
@@ -963,7 +1012,7 @@ nav#navbar-main li {
clear: both;
font-weight: 400;
line-height: 1.42857143;
- color: #34495e;
+ color: {{ .Get "menu_text" }};
white-space: nowrap;
}
@@ -980,7 +1029,7 @@ nav#navbar-main li {
.navbar-default .navbar-nav .open .dropdown-menu > li > a {
padding: 5px 15px 5px 25px;
line-height: 20px;
- color: #34495e;
+ color: {{ .Get "menu_text" }};
}
.navbar-default .navbar-nav .open .dropdown-menu > li > a:focus,
@@ -992,7 +1041,7 @@ nav#navbar-main li {
.navbar-default .navbar-nav .open .dropdown-menu > .active > a,
.navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus,
.navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover {
- color: #0095eb;
+ color: {{ .Get "menu_text_active" }};
background-color: transparent;
}
diff --git a/layouts/partials/css/parse_theme.css b/layouts/partials/css/parse_theme.css
new file mode 100644
index 00000000..8288dfdd
--- /dev/null
+++ b/layouts/partials/css/parse_theme.css
@@ -0,0 +1,32 @@
+{{- $scr := .Scratch -}}
+{{- $site := $scr.Get "site" -}}
+
+{{/* Attempt to load font style specified by user. */}}
+{{- $font_index := .Site.Params.font | default "default" -}}
+{{ if isset .Site.Data.themes $font_index }}
+ {{- $font := index .Site.Data.fonts $font_index -}}
+ {{- $scr.Set "google_fonts" $font.google_fonts -}}
+ {{- $scr.Set "body_font" $font.body_font -}}
+ {{- $scr.Set "heading_font" $font.heading_font -}}
+ {{- $scr.Set "mono_font" $font.mono_font -}}
+ {{- $scr.Set "font_size" $font.font_size -}}
+ {{- $scr.Set "font_size_small" $font.font_size_small -}}
+{{ end }}
+
+{{/* Attempt to load color theme specified by user. */}}
+{{- $theme_index := .Site.Params.color_theme | default "default" -}}
+{{ if isset .Site.Data.themes $theme_index }}
+ {{ $theme := index .Site.Data.themes $theme_index }}
+
+ {{- $scr.Set "primary" $theme.primary -}}
+ {{- $scr.Set "primary_light" $theme.primary_light -}}
+ {{- $scr.Set "primary_dark" $theme.primary_dark -}}
+
+ {{- $scr.Set "menu_primary" $theme.menu_primary -}}
+ {{- $scr.Set "menu_text" $theme.menu_text -}}
+ {{- $scr.Set "menu_text_active" $theme.menu_text_active -}}
+ {{- $scr.Set "menu_title" $theme.menu_title -}}
+
+ {{- $scr.Set "home_section_odd" $theme.home_section_odd -}}
+ {{- $scr.Set "home_section_even" $theme.home_section_even -}}
+{{ end }}
diff --git a/layouts/partials/header.html b/layouts/partials/header.html
index 3eaa3c51..8be5bd35 100644
--- a/layouts/partials/header.html
+++ b/layouts/partials/header.html
@@ -36,8 +36,12 @@
{{ end }}
{{/* We cannot use SRI with Google Fonts because the CSS is dynamically generated according to the user agent */}}
-
-
+ {{- partial "css/parse_theme.css" . -}}
+ {{- $scr := .Scratch -}}
+ {{ with ($scr.Get "google_fonts") }}
+
+ {{ end }}
+
{{ range .Site.Params.custom_css }}
{{ end }}