diff --git a/package.json b/package.json index 2f9b101..277227a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "eleventy-excellent", "version": "2.1.4", - "description": "Eleventy starter based on the workflow suggested by Andy Bell's buildexcellentwebsit.es.", + "description": "Eleventy starter built around the workflow suggested by Andy Bell's buildexcellentwebsit.es.", "author": "Lene Saile", "license": "ISC", "engines": { diff --git a/src/_data/meta.js b/src/_data/meta.js index 2db8322..3a026ea 100644 --- a/src/_data/meta.js +++ b/src/_data/meta.js @@ -2,7 +2,7 @@ module.exports = { url: process.env.URL || 'http://localhost:8080', siteName: 'Eleventy Excellent', siteDescription: - 'Eleventy starter based on the workflow suggested by buildexcellentwebsit.es', + 'Eleventy starter built around the CSS workflow suggested by buildexcellentwebsit.es', siteType: 'Person', // schema locale: 'en_EN', lang: 'en', @@ -23,14 +23,20 @@ module.exports = { themeBgColor: '#FBFBFB', // Manifest: defines a placeholder background color for the application page to display before its stylesheet is loaded opengraph_default: '/assets/images/template/opengraph-default.jpg', // fallback/default meta image opengraph_default_alt: - 'Visible content: Eleventy starter based on workflow for Cube CSS, Every Layout, Design Tokens and Tailwind for uitility, based on the concepts explained in buildexcellentwebsit.es', // alt text for default meta image + 'Visible content: Eleventy starter built around the CSS workflow for Cube CSS, Every Layout, Design Tokens and Tailwind for uitility, based on the concepts explained in buildexcellentwebsit.es', // alt text for default meta image blog: { // RSS feed name: 'My Web Development Blog', description: 'Tell the word what you are writing about in your blog. It will show up on feed readers.', // feed links are looped over in the head. You may add more to the array. - feedLinks: [{title: 'Atom Feed', url: '/feed.xml', type: 'application/atom+xml'}], + feedLinks: [ + { + title: 'Atom Feed', + url: '/feed.xml', + type: 'application/atom+xml' + } + ], // Tags tagSingle: 'Tag', tagPlural: 'Tags', @@ -51,7 +57,9 @@ module.exports = { ariaTop: 'Main', ariaBottom: 'Complementary', ariaPlatforms: 'Platforms', - closedText: 'Menu' + // activate alternative mobile menu with drawer + drawerNav: false, + navLabel: 'Menu' }, themeSwitch: { title: 'Theme', diff --git a/src/_includes/components/burger-template.njk b/src/_includes/components/burger-template.njk new file mode 100644 index 0000000..f4038ce --- /dev/null +++ b/src/_includes/components/burger-template.njk @@ -0,0 +1,24 @@ + + + + + + + diff --git a/src/_includes/partials/header.njk b/src/_includes/partials/header.njk index 3d95c83..d1844c8 100644 --- a/src/_includes/partials/header.njk +++ b/src/_includes/partials/header.njk @@ -10,6 +10,6 @@ {% include "svg/star.svg" %} {{ meta.siteName }} - {% include "partials/menu.njk" %} + {% include "partials/main-nav.njk" %} diff --git a/src/_includes/partials/main-nav.njk b/src/_includes/partials/main-nav.njk new file mode 100644 index 0000000..4e70b02 --- /dev/null +++ b/src/_includes/partials/main-nav.njk @@ -0,0 +1,34 @@ +{% set drawerNav = meta.navigation.drawerNav %} + +{% if drawerNav %} + + {% set drawerClass = "site-nav-drawer" %} +{% endif %} + + + +{% if drawerNav %} + {% include "components/burger-template.njk" %} +{% endif %} diff --git a/src/_includes/partials/menu.njk b/src/_includes/partials/menu.njk deleted file mode 100644 index f087bbd..0000000 --- a/src/_includes/partials/menu.njk +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/src/_layouts/base.njk b/src/_layouts/base.njk index 62a592b..3a2e2e7 100644 --- a/src/_layouts/base.njk +++ b/src/_layouts/base.njk @@ -2,6 +2,8 @@ + +
@@ -64,10 +66,11 @@ - {% if masonry %} + {% endif %} + {% if youtube %} {% endif %} - + {% if meta.navigation.drawerNav %} + + + {% endif %} + {% if meta.easteregg %} + {% endif %} diff --git a/src/assets/css/blocks/site-nav-drawer.css b/src/assets/css/blocks/site-nav-drawer.css new file mode 100644 index 0000000..6a85945 --- /dev/null +++ b/src/assets/css/blocks/site-nav-drawer.css @@ -0,0 +1,150 @@ +/* set on parent div to get the right z-index context */ +.ontop { + z-index: 1; + position: relative; +} + +.site-nav-drawer { + position: var(--nav-position, absolute); + inset-inline-end: 0.1rem; +} + +/* Remove default list styling and create layout for list */ +.site-nav-drawer ul { + --cluster-vertical-alignment: normal; + --gutter: var(--space-xs); + list-style: none; + margin: 0; + line-height: 0.5em; + padding: var(--nav-list-padding, var(--space-2xl) var(--space-s)); + background: var(--nav-list-background, var(--color-bg)); + box-shadow: var(--nav-list-shadow, -5px 0 11px 0 rgb(0 0 0 / 0.2)); + flex-direction: var(--nav-list-layout, column); + block-size: var(--nav-list-height, 100vh); + position: var(--nav-list-position, fixed); + inset-block-start: 0; + inset-inline-end: 0; + inline-size: var(--nav-list-width, min(22rem, 100vw)); + visibility: var(--nav-list-visibility, visible); +} + +.site-nav-drawer [aria-expanded='false'] + ul { + transform: var(--nav-list-transform, translateX(100%)); + visibility: var(--nav-list-visibility, hidden); +} + +/* animates ul only when opening to avoid flash on page load, svg always */ +@media (prefers-reduced-motion: no-preference) { + .site-nav-drawer [aria-expanded='true'] + ul, + .site-nav-drawer svg { + transition: + transform 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55), + visibility 0.05s linear; + } +} + +/* Basic link styling */ +.site-nav-drawer a { + --text-color: var(--color-text); + --background-color: var(--color-bg); + --border-color: transparent; + background-color: var(--background-color); + color: var(--text-color); + padding: var(--anchor-padding, var(--space-s)); + text-decoration: none; + display: block; + border-radius: var(--border-radius); + border: 1px solid var(--border-color); +} + +/* Change the border-color on :hover and :focus */ +.site-nav-drawer a:where(:hover, :focus) { + --background-color: var(--color-bg-accent); + --text-color: var(--color-text-accent); + --border-color: var(--color-bg-accent); +} + +/* Change border-color and color for the active page */ +.site-nav-drawer [aria-current='page'], +.site-nav-drawer [data-state='active'] { + --background-color: var(--color-bg-accent); + --text-color: var(--color-text); + --border-color: var(--color-bg-accent); +} + +/* Reset button styling */ +.site-nav-drawer button { + all: unset; + display: var(--nav-button-display, flex); + align-items: center; + position: relative; + z-index: 2; + cursor: pointer; + align-items: center; + padding: var(--space-xs) 0; +} + +.site-nav-drawer span { + font-size: var(--size-step-min-1); + font-weight: bold; + text-transform: uppercase; + padding-inline-end: var(--space-2xs); +} + +.site-nav-drawer svg { + block-size: 100%; + inline-size: auto; + transform: translateY(-0.1em); + color: var(--color-text); +} + +.site-nav-drawer [aria-expanded='true'] svg { + transform: var(--nav-list-rotate, rotate(45deg)); +} + +@media screen(sm) { + .site-nav-drawer { + --nav-button-display: none; + --nav-position: static; + } + + .site-nav-drawer ul { + --nav-list-background: transparent; + --nav-list-layout: row; + --nav-list-position: static; + --nav-list-padding: 0; + --nav-list-height: auto; + --nav-list-width: 100%; + --nav-list-shadow: none; + --nav-list-transform: none; + --nav-list-visibility: visible; + } + + .site-nav-drawer a { + --anchor-padding: var(--space-xs) 0.2em; + --text-color: var(--color-text); + --background-color: transparent; + --border-color: transparent; + --text-decoration: transparent; + text-decoration-line: underline; + text-decoration-color: var(--text-decoration, transparent); + text-decoration-thickness: 3px; + text-underline-offset: 0.2em; + } + + .site-nav-drawer a:where(:hover, :focus) { + --text-color: var(--color-text); + --background-color: transparent; + --border-color: transparent; + --text-decoration: var(--color-text-accent); + } + + /* Change border-color and color for the active page */ + .site-nav-drawer [aria-current='page'], + .site-nav-drawer [data-state='active'] { + --text-color: var(--color-primary); + --background-color: transparent; + --border-color: transparent; + --text-decoration: var(--color-primary); + } +} diff --git a/src/assets/scripts/nav-drawer.js b/src/assets/scripts/nav-drawer.js new file mode 100644 index 0000000..f8e00e0 --- /dev/null +++ b/src/assets/scripts/nav-drawer.js @@ -0,0 +1,34 @@ +// © Manuel Matuzović: https://web.dev/website-navigation/ + +const nav = document.querySelector('nav'); +const list = nav.querySelector('ul'); +const burgerClone = document.querySelector('#burger-template').content.cloneNode(true); +const svg = nav.querySelector('svg'); + +const button = burgerClone.querySelector('button'); +button.addEventListener('click', e => { + const isOpen = button.getAttribute('aria-expanded') === 'true'; + button.setAttribute('aria-expanded', !isOpen); +}); + +// avoid DRY: disabling menu +const disableMenu = () => { + button.setAttribute('aria-expanded', false); +}; + +// close on escape +nav.addEventListener('keyup', e => { + if (e.code === 'Escape') { + disableMenu(); + } +}); + +// close if clicked outside of event target +document.addEventListener('click', e => { + const isClickInsideElement = nav.contains(e.target); + if (!isClickInsideElement) { + disableMenu(); + } +}); + +nav.insertBefore(burgerClone, list); diff --git a/src/docs/less-js.md b/src/docs/less-js.md index 1894e5d..520180c 100644 --- a/src/docs/less-js.md +++ b/src/docs/less-js.md @@ -4,10 +4,11 @@ title: Less JavaScript The only "real" JavaScript dependency is **theme-toggle.js**, which is inlined. -There are two more scripts that are generated but you have to opt in: +There are three more scripts that are available, but you have to opt in: + +**nav-drawer.js**, to opt in to a drawer menu on small screens. See the [navigation documentation](/docs/navigation/). **masonry.js**, creating the masonry effect used on the cards. -A fallback until [maybe, one day](https://caniuse.com/mdn-css_properties_grid-template-rows_masonry) we get to use `grid-template-rows: masonry;`. Search for `masonry: true` to see where it is activated, and set to `false`, an empty string, or delete the front matter field, if you don't want to use it. The script won't be included then. Nothing breaks, the cards just won't rise up to completely fill the gaps in their grid. The **easteregg.js** is an opt-in JS-file set in `src/_data/meta.js`. diff --git a/src/docs/masonry.md b/src/docs/masonry.md new file mode 100644 index 0000000..37dbf0f --- /dev/null +++ b/src/docs/masonry.md @@ -0,0 +1,9 @@ +--- +title: Masonry +--- + +There is the idea of making masonry layout a native part of CSS grid, using `grid-template-rows: masonry;`. It is [not yet to be seen on the horizon](https://caniuse.com/mdn-css_properties_grid-template-rows_masonry), but it is already included in the starter (inside the `grid.css` composition). +Until then, a small script will help us to get the effect. + +It gets loaded by opt-in. +Set `masonry: true` in your front matter to activate. diff --git a/src/docs/navigation.md b/src/docs/navigation.md new file mode 100644 index 0000000..754fbc6 --- /dev/null +++ b/src/docs/navigation.md @@ -0,0 +1,19 @@ +--- +title: Navigation +--- + +Edit your navigation items in `src/_data/navigation.js`. + +You have two options for mobile navigation: by default, the navigation on small displays is converted to small pills that wrap. This does not require any additional JavaScript. + +Before version 2.0 a slide out drawer was the default, you can activate it again in `src/_data/meta.js`: + +```js +navigation: { + // other settings + drawerNav: true, + navLabel: 'Menu' + }, +``` + +`drawerNav` activates the navigation drawer, [built according to Manuel Matuzović's article on web.dev.](https://web.dev/articles/website-navigation) \ No newline at end of file diff --git a/src/pages/about.md b/src/pages/about.md index ced613b..dd69c0b 100644 --- a/src/pages/about.md +++ b/src/pages/about.md @@ -8,7 +8,7 @@ youtube: true This starter uses modern CSS, fluid type & space, flexible Layouts and Progressive Enhancement, wrapped in a basic template. -Based on the CSS boilerplate by Andy Bell and inspired by Andy's talk **'Be the browser’s mentor, not its micromanager'**. +It is built around the CSS boilerplate by Andy Bell and inspired by Andy's talk **'Be the browser’s mentor, not its micromanager'**. If you want to know exactly how it all works, [read this article on piccalil.li](https://piccalil.li/blog/a-css-project-boilerplate/). diff --git a/src/pages/get-started.md b/src/pages/get-started.md index 62473fc..ca70df0 100644 --- a/src/pages/get-started.md +++ b/src/pages/get-started.md @@ -15,7 +15,6 @@ You can use this starter as a template for your blog and you are ready to go! Bu - `src/_data/meta.js` - sets different "hard coded" text values all over the template, you can change the language, etc. - edit your personal details and social media in `src/_data/personal.yaml`. - Open `src/assets/css/blocks/external-link.css`. Replace "eleventy-excellent.netlify.app" with your own domain. This is about the external link indicators, they are matched with your domain. If you don't want to use external link indicators, feel free to delete the whole style rule. You can also add the class `no-indicator` to any anchor element you want to except from this rule. -- Edit your navigation items in `src/_data/navigation.js`. If you are working with **VS Code** I recommend installing the "Tailwind CSS IntelliSense" addon, as it works also for our custom utility classes. That said, you will find that Tailwind CSS does not work as you might expect. I explain this in [one of the blog posts](/blog/what-is-tailwind-css-doing-here/). diff --git a/src/pages/index.md b/src/pages/index.md index efed2b2..9cc89ed 100644 --- a/src/pages/index.md +++ b/src/pages/index.md @@ -10,7 +10,7 @@ blog: ## An Eleventy starter -This [Eleventy](https://www.11ty.dev/) starter is based on [Andy Bell's](https://andy-bell.co.uk/) talk 'Be the browser’s mentor, not its micromanager' and its companion website buildexcellentwebsit.es. +This [Eleventy](https://www.11ty.dev/) starter was inspired [Andy Bell's](https://andy-bell.co.uk/) talk 'Be the browser’s mentor, not its micromanager' and its companion website buildexcellentwebsit.es. In his words, it's about hinting the browser rather than micromanaging it, using progressive enhancement, CSS layout, fluid type & spacing, as well as modern CSS features.