- Timber (Twig) based templates. Put logic in usual wordpress PHP templates, relate it to a Twig template by assigning to the
$context[]
variable, add corresponding templates in<themename>/templates
folder; - BEM methodology for markup/CSS. The project frontend consists of self-contained components. BEM naming convention is
component__element_modifier
. Avoid all the things that you would avoid in a typical BEM-like project. See below for more information; - namespaces for CSS classes aka prefixes. Read below on what prefixes can be used, and see here why namespacing is cool;
- stylelint linting. Comments starting from words "todo"/"hack" appear as warnings to bring attention to them;
dotenv
for doing different things depending on local/stg/prod environment;- shared variables inside the theme (a variable added to
common_config.json
can be reused in JS/Gulp/SASS/PHP/Twig); - npm packages for theme usage;
- Babel-enabled modular JS;
- SVG spriting. Put new SVG files to be found in the sprite to
<themename>/img/svg-sprite-source
folder, invoke them with theimage-svg-sprite.twig
partial; - automated Modernizr build based on actually used features only;
- custom fields registered in code for faster deployment to other environments.
The theme is best served with VVV site template but can be used standalone without any problems.
CSS architecture of the project follows a set of rules to establish better maintainability, reusability, and organization of code. It borrows from several concepts including BEM/7-1 pattern/ITCSS/Harry Roberts'namespaces. Every class or mixin should be prefixed. Here's the types of classes/mixins that are used throughout the project:
- Components (prefixed with
c-
) are potentially reusable mixins that represent independent, fully styled blocks within a page. Where to place:components/_component-name.scss
.- The concept of components is fully compatible with the BEM methodology. They may contain
__elements
and_modifiers
. Components may itself have a modifier, but a component cannot have a subcomponent — only 1 level of nesting elements inside a component is allowed; - They are applied to the class of the same name in
_main.scss
but also can be applied to other classes as well, without having to add the original class in the markup explicitly and allowing for easy extension (any component can be extended with another component — without drawbacks of@extend
s). That's why the first argument in the component mixin should always be$base_class
and its inner elements definitions should start with#{$base_class}
. See the example component in thecomponents
folder; - Non reusable components used for layout features (such as header, footer, main and so on) are still components, so they should be prefixed and comply to the usual rules. It is not mandatory though to create them as mixins;
- The concept of components is fully compatible with the BEM methodology. They may contain
- Theming mixins (
t-
) — these are only related to appearance. Usually are not used alone as well. Where to place:abstracts/_mixins.scss
; - Utilities are “does one thing”-style mixins. Prefix:
u-
. Where to place:abstracts/_mixins.scss
; - Scoped mixins (
s-
) - define a separate styling context inside which tag selectors may be used (usually we can only use classes). Only for styling user edited rich content areas (articles body etc.). Where to place:abstracts/_mixins.scss
.
The project also makes use of context dependent prefixes such as js-
, has-
and others.
When styling a new piece of markup, it's important to see if there's already a component mixin that fits its design. If there is, maybe it would be more appropriate to add some new elements to that mixin and then apply it. An alternative approach is to create a new component that @include
s another one and add up the difference in styling to the latter.
When styling a group of repeated items (such as a section of teasers) it's preferable to separate the group's own styling and item's inner styling into two different components. This way we can always reapply the item's styling independently somewhere else.
Don't use extends unless they're provided by an external tool (such as svg-sprite
). Here's some explanation why this project avoids them.
The theme is dependent on ACF and Timber Library plugins. Make sure they're installed and activated before activating the theme.
The theme can also make use of an .env
file if it exists in the project. The path to the .env
file is specified in gulpfile.js
.
- Replace all the instances of
themeprefix
in boilerplate*.php
files with any prefix wanted; - replace all the instances of
theme_domain
in boilerplate*.php
,*.twig
,style.scss
,loco.xml
files with your theme's localisation domain; - rename the theme in
style.scss
andpackage.json
files appropriately; - go to the
timber-theme
theme folder, runnpm install
; - create an
.env
file in the theme folder or adjust its location ingulpfile.js
. AddHOST=YOURLOCALSITE.TEST
there to enable Browsersync; - Add
ENV=dev
line to the.env
file. This will generate files more adapted for local FE work (CSS source maps, non minified CSS/JS, pixels instead of rems). On staging/production it may contain anything except fordev
; - run
gulp
to compile theme,gulp watch
to compile and watch for changes.
You may wish to add style.css
in the root after first gulp
execution to the theme's .gitignore
file (though it's not mandatory).
- If you create a native Wordpress custom page template — put the Twig file into the
templates/custom-templates
folder. It is a good idea to keep PHP files for custom page templates prefixed uniformly (for example withtemplate-
prefix). - The theme Javascript is separated into modules. Each module is merged into the main
scripts.min.js
file which is served on frontend upon gulp compilation. Each time you need to introduce a new script that is not related to others, you will want to create a new module.- duplicate any existing module in the
js/modules
folder (or the providedexample-module.js
file); - rename it appropriately;
- init the module in
js/main.js
file.
- duplicate any existing module in the
- Theme functions are organized into several includes, if adding something try to find an appropriate include for that or create a new one. Each file's purpose is described in its comment section.
- When registering new custom fields you can follow the naming convention of
{posttypename}_{fieldname}
for post custom fields and post-type-wide fields (stored in theoption
table) and{taxname}_{fieldname}
for term meta fields. This will allow you to use the fields in various smart ways. - You can use Loco Translate plugin for translation of the English theme strings into another languages (no setup needed, just install it on your local). The plugin will automatically discover all the English strings of the theme and will let you translate them right in the admin. After doing some translations make a commit. The translation file
<theme-path>/languages/<lang-slug>.po
is compiled into the.mo
file when you save your translation in Loco Translate admin interface and also by agulp watch
task. - You can use a
@z-index space: XX-XX
comment in the beginning of a SCSS file of a component to indicate the range ofz-index
values to be used here to other developers. This helps to prevent clashes between different components. Obviously, other components should havez-index
values assigned in another range. For example, a componentc-a
will have@z-index space: 20-30
comment while a componentc-b
will have@z-index space: 30-40
. - You can lint PHP files by running
composer install
in the theme folder (install composer globally first) andvendor/bin/phpcs .
.
- add a stylelint check for browser incompatibilities with
ismay/stylelint-no-unsupported-browser-features
- replace JSHint with ESLint