This is a WIP starting point for custom themes for grav CMS.
We are using some node magic to help with boring and repetitive tasks. Please learn first about the file structure and the way assets are organized and processed in this project.
Chassis provides templates, styles or functionality for the following plugins (if you install and enable them…)
- breadcrumbs
- company-details
- forms
- markdown-details
- markdown-notices
- pagination
- shortcode-core
- shortcode-gallery
.
├── /.tasks node scripts (see package.json)
├── /admin Admin modifications and enhancements
│ └── /buttons Editor buttons
├── /assets "raw" assets
│ ├── /css CSS files
│ │ ├── /base settings, normalization, helper
│ │ ├── /form form components
│ │ ├── /molecule simple modules
│ │ ├── /oranism complex modules
│ │ ├── /template template/page specifics (e.g. spacing)
│ │ ├── /vendor 3rd party / plugin styles
│ │ ├── admin.css admin style modifications
│ │ ├── fonts.css dedicated web font style sheet
│ │ └── main.css main style sheet
│ ├── /favicon favicons/app icons
│ ├── /fonts font files in WOFF2 format
│ ├── /icons SVG icons
│ │ └── _icons.html template for icons sprite cheat sheet
│ ├── /img static images
│ │ ├── marker.svg map marker template
│ │ └── social.jpg default open graph image
│ └── /js JS files
│ ├── /src JS (bundle) source files
│ ├── dev.json JS helper bundle for local enviroment
│ ├── main.json JS base bundle.
│ └── summary.js JS standalone component
├── /blueprints grav blueprints for page types
├── /classes custom PHP Classes
│ └── Utils.php utilty class with helper functions
├── /dist build files
│ ├── /css minified CSS files
│ ├── /fonts duplicates of assets/fonts
│ ├── /icons optimized and minified icons
│ ├── /img optimized images
│ └── /js minified JS files and bundles
├── /langages translation files
├── /shortcodes custom shortcodes
├── /templates grav templates
│ ├── /email email templates
│ ├── /forms custom form elements for better styling
│ ├── /macros macros to use with twig
│ ├── /modular templates for modular page elements
│ ├── /partials template parts
│ └── *.html.twig page templates
├── .eslintrc eslint config
├── .styleintrc styleint config
├── chassis.php theme functions
├── chassis.yaml theme config file
└── package.json
We are using PostCSS for convenience. It will inline @import
, resolve nesting and autoprefix.
/assets/css/main.css
is the main CSS file and hub. You'll find only imports inside, which will be inlined in processing. If you need to, you can add other CSS files in parallel to main.css to provide other subsets or differently scoped styles. Every CSS file stored directly in /assets/css/
will be processed and the result stored in /dist/css/
.
Additionally this will also happen to CSS files in /assets/css/page
. So you can create per page additions or overwrites which can be referenced by templates. Make sure there are no equal file names in css and css/pages.
In /assets/js
you will find .js and .json files, as well as a src
folder. In this setup (no webpack or other advanced magic) the JS files are independent functional components. JSON files are the base for bundles. With these, you can concatenate multiple components from the src
folder as well as libraries from /node_modules
which you installed via npm (see example below). In bundles, the order is important. The libs will appear before the code from src
.
Every JS file in /assets/js
will be copied in /dist/js
. Bundles will run through a combination of their parts and the result will be saved as js in /dist/js
. Please be aware that there will be conflicts if the filenames of a bundle and a standalone component are the same (foobar.js and foobar.json for example).
{
"lib": [
"choices.js/public/assets/scripts/choices.min.js"
],
"src": [
"address.js",
"userprofile.js"
]
}
All image files in /assets/img
will be optimized on build (or called manually) using imagemin
(svgo, pngQuant, mozJpeg, gifsicle, Zopfli) and stored in /dist/img
. When using the watch task, images will simply be copied to avoid waiting times in development.
It's good practice to use only WOFF2 format fonts now. Browser support is good and we provide a fallback to system fonts. Also make sure to subset (use Font Squirrels Generator or Font Mangler) to reduce the file sizes. At build or with the dedicated command, the fonts will be put in /dist
.
If you are using a CI server, you can add the /dist
folder to .gitignore
. Otherwise, you should make a build before every merge with your main branch, so the main branch includes the minified and most optimized assets in /dist
.
In package.json
you will find an onject called config
. Here are paths stored that are used by the node scripts.
To use this feature, make sure you set up the correct URL of your project in config.bsProxy
in package.json
.
When the watch
task is running, you can access http://localhost:3000. Depending on your network or firewall configuration, you could also access this port with other devices to do even more cross-device/browser testing. Browsersync
will keep scroll position (proportional) in sync.
The watch
task will force refreshes on CSS and JS files via Browsersync so you can see instantly the impact of your changes.
On port 3001 you can access the Browsersync control panel.
Wir use node scripts as a task runner.
command | function |
---|---|
npm run css | processes the CSS files and saves them with source maps to /dist/css |
npm run cssmin | same as css but with minifying |
npm run js | creates JS bundles and copies JS files to /dist/js |
npm run jsmin | same as js but with minifying |
npm run lint | checks CSS and JS assets for bad coding styles and errors |
npm run fonts | copies font files to /dist/fonts |
npm run img | simply copies images from /assets/img to /dist/img |
npm run imgmin | optimizes images and saves results to /dist/img |
npm run icons | optimizes icons and saves results to /dist/icons |
npm run sprite | creates an icon sprite from /dist/icons in /dist/sprite |
npm run favicons | creates favicon files from /dist/favicons/favicon.svg and saves them in /dist/ - move them from here |
npm run watch | watch for changes and process changed or new files |
npm run todo | find all occurances of todo |
npm run clean | clear /dist |
npm run dev | runs css , js , img and icons in parallel once |
npm run build | runs lint , clean , cssmin , jsmin , imgmin , icons and fonts |
This is a bit trickey since grav has more than one place to set the name. In order to rename the theme, you will need to follow these steps (let's take picasso for example):
- Rename the theme folder
chassis
->picasso
- Rename
/chassis.yaml
and/chassis.php
inpicasso.*
- Change the name in
/blueprints.yaml
- In the file formerly known as
/chassis.php
rename the class name, mind the capital first letterclass Chassis extends Theme
->class Picasso extends Theme
- There are occurrences regarding the utility class in the same file, rename and follow the capitalization
- In
/classes/Utils.php
rename the namespace definition, mind the capitalization - Make sure all occurrences of utility functions in the template folder are renamed (search for chassis in files)
- Set new theme in
user/config/system.yaml
When using a dash in the theme name, you will have to CamelCase (upper camel case) the namespaces and class names.
[caption class="image" caption="Quelle: Unsplash.com"]
![](image.jpg)
[/caption]
Adds a caption (via HTML figure
+ figcaption
) to your media (image, video, embed, audio).
[email link=1][email protected][/email]
Mask e-mails with HTML entities to give some spam protection. link
parameter is optional and makes the address a mailto
link.
[icon=mail title="E-Mail"]
Shortcode to use in text icons utilizing the svg-extension plugin.
As seen in the example, the first word is the icon name, optional parameters follow after that.
Parameter | Effect |
---|---|
id | Set an ID for the SVG element |
class | Set the CSS classes for the SVG element |
title | Set a title (accessibility) |
[lang=fr inline=1]Bonjour[/lang]
Wrap text in a different language semantically, so screenreader can interpret and pronounce it correctly. By default, it wraps the text in a div
, adding the optional inline
parameter wraps it in a span
.
[video=Uuad8V5f_QA]
[video="https://www.youtube.com/watch?v=Uuad8V5f_QA"]
[video id=Uuad8V5f_QA]
[video id="https://www.youtube.com/watch?v=Uuad8V5f_QA"]
[video id=141358 type=vimeo]
Embed a video from YouTube or Vimeo with a privacy alert. The video will only load (and request external resources) if the user confirms (once or for the whole site).
! The CSS and JS of this component needs to be added to processing. They are not enabled by default.
Some interpretations of the following options depend on the video platform.
Parameter | Effect | Values | Default |
---|---|---|---|
id | Video ID or URL | string or URL | – |
type | Which video platform | youtube or vimdeo | youtube |
showinfo | Include information overlays | 0 or 1 | 0 |
controls | Show video player controls | 0 or 1 | 1 |
color | Controls color | red, white, hexcode | white |
class | Additional CSS classes for the embed wrapper | string | – |
[raw][email link=1][email protected][/email][/raw]
This is a helper to show shortcodes on pages without getting them processed.