-
Notifications
You must be signed in to change notification settings - Fork 84
Coding standards
- Prettier
- Javascript style guide
- HTML style guide
- CSS style guide
- Nunjucks style guide
- General reading
The project uses Prettier to format the source code. Some Google standards may be overlooked in favor of the Prettier style guide.
Javascript file names and variables should follow the naming principles for the project:
- File names must be written in
kebab-case
- Variable names must be written in
lowerCamelCase
- Local variables should have an underscore at the end of its name, i.e.
let myLocalVar_ = true;
Note: Before adding any new code, make sure to take a look at the codebase, analyze and understand it and follow established patterns.
All Javascript files must start with the following license disclaimer:
/**
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
If you need to add some configurations, plugins, collections, etc… to Eleventy, do so in the .eleventy.js
file and add them following existing patterns. Similarly, if you need to add some configurations, plugins, etc… to Vite, do so in the vite.config.js
file and add them following existing patterns. HTML transformations should be done via a PostHTML plugin, inside lib/transforms
, and added as a plugin to the Vite PostHTML plugin in vite.config.js
.
Code to extend our build process should be placed under the lib
folder in one of the following sub-folders:
-
collections
- code to add collections to 11ty -
filters
- code to filter data on 11ty templates -
helpers
- utility functions -
markdown
- markdown rendering -
linting
- linting extensions, including remark rules and content model schemas -
transforms
- HTML transformations
Before adding any new Javascript, make sure you explore all HTML and CSS alternatives and determine that and none of them worked as needed.
main.js
is the entry point of the Javascript code and it’s located in the site/js/
folder.
Global components should be initialized on the DOMContentLoaded
event handler following the pattern defined by MainNavigation
class. i.e. the Navigation
Components used on a specific page will use Dynamic imports, so they are loaded only when needed. To add components using dynamic imports place your code on load
handler following the pattern defined by toc
component.
The project is powered by Nunjucks which is a templating language, however, all the templates are written to HTML files.
The html structure plays an important role for accessibility, therefore, it’s very important to make sure that the semantic element clearly describes its meaning properly according to the designs.
- File names must be written in
kebab-case
- Major navigation blocks should be wrap by the
nav
element - The html structure should include the proper accessibility attributes following the accessibility recommendations
- When styling text check the existing class
type
and its elements in_typography.scss
file. Use it like<h1 class=”type--h1”> some title </h1>
- To avoid adding too many classes to an element, don’t double up a class in the html, use
@extend
in the element styling. For example: You can usetype--*
to add typography style to the elements like:<h3 class="icon-card__title type--h5 ">{{title}}</h3>
Notice that the element already has anicon-card__title
class, so, you might extend the%type--h5
in theicon-card__title
class.- Don't use spans or divs unless there isn’t another element that makes sense, verify the purpose of the element you are placing and select the best semantic element to match it.
- All images, except our UI icons, favicon, and PWA icons, are served from an image-optimization CDN. All image URLs for images served from the CDN should be prefixed with
ix://
instead of a domain to be properly transformed, so if an image was available atposts/foo/image.png
on the CDN, the URL should beix://posts/foo/image.png
in our codebase. If you need help uploading an image to our CDN, please reach out to one of the site administrators. - Images should include the
alt
attribute with a description text. If the image is decorative it should havealt=”’
Image alt
- Don't include
target="_blank"
. We want to preserve default behavior unless there's a great need to. - Don’t manually include
rel="noopener"
, our build process will automatically add it.
- All component styles are written in the
scss
syntax of Sass and compiled to generate a single CSS file. - Layout is based on Fluid layout web page design, that means there are no "standard breakpoints", but rather there are component and layout based breakpoints
- File names must be written in kebab-case
- Each component has a separate Sass file with its own style scope, and should be placed on the components folder (
site/sass/components/_*.scss
), then imported onstyle.scss
Sass file (site/sass/style.scss
) - Any style file must have an overview description at the beginning
// <file overview>
.component-class {
// <definitions>
}
- Each Sass partial should only have one block (see next), or component, in it.
- Following BEM style pattern, all nested styles must be nested by ampersand
&__element
to generate a single class.
<section class="component">
<article class="component__text">
Lorem ipsum dolor sit amet...
</article>
</section>
// <file overview>
.component {
display: flex;
&__text {
color: var(--white);
}
}
- Avoid using “arbitrary numbers” without a coherent use. When selecting a number that may look arbitrary please add a comment explaining your reasoning.
-
Do not use
base64
encoded images in CSS - Use absolute paths (
/foo/bar
) in URLs - Use
margin
for spacing between elements andpadding
for spacing inside an element. - When using
display: grid
is preferred to usegap
for adding spacing around items on the grid. - Prefixes like
-webkit
and-moz-
are blocked by project linter, but you can use// sass-lint:disable-line no-vendor-prefix
at the end of the line to disable it. Please use it just in certain circumstances like override browser-specific styling. - Group common styles.
&__first-element,
&__second-element {
background-color: var(--black);
color: var(--white);
display: block;
}
- Do not style HTML tags directly unless you have no other way to style an element, for example styling HTML generated from markdown files or markdownIt plugins.
- In case of using any breakpoint (requirement only) the project has a dependency to create safe breakpoints. You can Read more about how to use it. Make sure to keep the component scope
// <file overview>
.component {
display: flex;
@include mq(700px) {
// <definitions>
}
}
-
Global variables must be written to the
_vars.scss
SASS file (site/sass/globals/_vars.scss
) . - Local variables must be written to its specific component Sass file, at the beginning of the file, keeping the component scope.
// <file overview>
.component {
$my-local-variable: #cecece display: flex;
&__text {
color: var(--my-local-variable);
}
}
- Variable names must be written in kebab-case.
- Use Google colors variables provided by
_colors.scss
file (site/sass/globals/_colors.scss
) - Do not add new colors, only if it is a requirement.
Typography for the site is defined in typography.scss
. This file contains general styling for anchors across the site, and a base class for texts called .type
. The .type
class defines the flow and spacing of elements for long format content (content from .md
files). Headings are defined to change size using the clamp
function between a min value that will work for small viewports and a max value that will work for large viewports. For browsers that don't support clamp
the font size will be the same across all viewports (medium size font).
Here is an example of the compiled CSS for type--h1
.
.type--h1 {
font-size: pxEm(48px);
line-height: 1.1666666667;
letter-spacing: pxEm(-0.5px);
}
@supports (font-size: clamp(pxEm(36px), 5.859375vw, pxEm(60px))) {
.type--h1 {
font-size: clamp(pxEm(36px), 5.859375vw, pxEm(60px));
line-height: 1.2;
}
}
- Changes in global typography styles must be written to the
_typography.scss
SASS file. - When writing a new component use classes defined on typography file. Do not redeclare
font-size
orfont-family
in component styles unless there is no other way.. - Use classes provided by
_typography.scss
file (site/sass/components/_typography.scsss
) instead of styling html tags fonts.
We encourage using modern CSS when it is possible to provide users an enhanced experience when their browser allows it.
One of those modern utilities is the he clamp function, which allows us to specify a min, variable, and max value we want something to be. Clamp is currently supported in Chromium browsers and Firefox will support it soon, so we can start using it. With it, we can, in conjunction with @supports, deliver modern code for browsers that support it, and fallback code for browsers that don't.
%blockquote__before {
width: 0.25rem;
@supports (width: clamp(1px, 1vw, 2px)) {
width: clamp(0.25rem, 1vw, 0.5rem);
}
}
What the above will do is set the width to .25rem
(4px
) if 1vw
< 4px
, 1vw
if 4px
< 1vw
< .5rem
, and .5rem
if 1vw
< .5rem
. This does mean that Safari browsers will always have the smaller width of .25rem
.
- Giving the approach used on the project (Fluid layout), we encourage the use of relative units such as
em
,rem
,ch
and so on. In case you are not familiar using them, the project has two mixins to help you to convertpixels
torems
andems
,pxRem
andpxEm
.
// <file overview>
.component {
padding: pxRem(16px) pxRem(24px);
}
Here's a small cheatsheet conversion table between pixels
and rems
.
Px | Rem |
---|---|
8 | 0.5 |
16 | 1 |
20 | 1.25 |
24 | 1.5 |
28 | 1.75 |
32 | 2 |
40 | 2.5 |
- The project uses Prettier as code formatter and it does not support
nunjucks
syntax formatting the code asHTML
. - Conditional and variable definitions need to be written in a single line.
<title>
{% if section != 'index' %} {% block title %}{% endblock %} - {% endif %}
</title>
- New components will be located at templates/_components level.
- Macros follow the same name convention as the file that includes them using
camelCase
.
icon-card.html
{% macro iconCard(data, defaultText) -%}
<article class="icon-card">
...
</article>
{%- endmacro %}
- Macros need to be documented.. Use JSDoc style documentation for all macros
<!--{#
Renders content with a CTA.
@param {object} content - Main content for the macro
@param {string} content.title - Title of macro
@param {string} content.body - Main body content of the macro
@param {number} [content.weight] - Weight of the macro (optional)
@param {object} cta - Call to Action
@param {string} cta.title - Title of the CTA
@param {string} cta.url - URL of the CTA
#}-->
{% macro myMacro(content, cta) -%}
<article class="my-macro”>
...
</article>
{%- endmacro %}
These resources will help you write cleaner code.