├── .gitignore ├── accessibility ├── images │ ├── alt-examples │ │ ├── bell.png │ │ ├── maths.png │ │ ├── orlok.png │ │ ├── virus.png │ │ └── akkadian.png │ ├── color_contrast_01.jpg │ ├── color_contrast_02.gif │ ├── color_contrast_03.gif │ ├── color_contrast_04.gif │ ├── color_contrast_05.gif │ └── microsoft-accessibility.jpg ├── common-remediations │ ├── README.md │ ├── sc-2.4.11.md │ ├── sc-3.2.2.md │ ├── sc-1.3.2.md │ ├── sc-1.4.10.md │ ├── sc-1.4.1.md │ ├── sc-3.1.1-and-3.1.2.md │ └── sc-2.1.1.md ├── 05-effective-colour-contrast.md ├── 03-accessibility-in-emails.md ├── 07-guide-for-suppliers.md ├── 01-popular-tools.md ├── 04-accessibility-in-pdfs.md └── README.md ├── markup ├── README.md └── house-style.md ├── git ├── README.md ├── semver.md └── git.md ├── javascript └── README.md ├── css ├── README.md ├── config │ └── .stylelintrc ├── bem-css.md ├── house-style.md └── how-we-write-css.md ├── writing ├── README.md ├── social-media.md ├── house-style.md └── inclusive-language.md ├── learning ├── README.md ├── web-accessibility.md └── web-performance.md ├── .editorconfig ├── performance ├── README.md ├── browser-caching.md ├── advertising.md ├── performance-checklist.md ├── font-loading.md └── images.md ├── security ├── README.md └── secure-markup.md ├── practices ├── README.md ├── javascript-styling.md ├── managing-static-assets.md ├── code-review.md ├── open-source-support.md ├── structured-data.md ├── house-style.md ├── graded-browser-support.md └── progressive-enhancement.md ├── README.md └── CONTRIBUTING.md /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | *.iml 3 | -------------------------------------------------------------------------------- /accessibility/images/alt-examples/bell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/alt-examples/bell.png -------------------------------------------------------------------------------- /accessibility/images/color_contrast_01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/color_contrast_01.jpg -------------------------------------------------------------------------------- /accessibility/images/color_contrast_02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/color_contrast_02.gif -------------------------------------------------------------------------------- /accessibility/images/color_contrast_03.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/color_contrast_03.gif -------------------------------------------------------------------------------- /accessibility/images/color_contrast_04.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/color_contrast_04.gif -------------------------------------------------------------------------------- /accessibility/images/color_contrast_05.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/color_contrast_05.gif -------------------------------------------------------------------------------- /accessibility/images/alt-examples/maths.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/alt-examples/maths.png -------------------------------------------------------------------------------- /accessibility/images/alt-examples/orlok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/alt-examples/orlok.png -------------------------------------------------------------------------------- /accessibility/images/alt-examples/virus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/alt-examples/virus.png -------------------------------------------------------------------------------- /accessibility/images/alt-examples/akkadian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/alt-examples/akkadian.png -------------------------------------------------------------------------------- /accessibility/images/microsoft-accessibility.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springernature/frontend-playbook/HEAD/accessibility/images/microsoft-accessibility.jpg -------------------------------------------------------------------------------- /markup/README.md: -------------------------------------------------------------------------------- 1 | # Markup 2 | 3 | We utilise HTML5 for compiled markup. 4 | 5 | * [House style](house-style.md) 6 | 7 | [Main table of contents](../README.md#table-of-contents) 8 | -------------------------------------------------------------------------------- /git/README.md: -------------------------------------------------------------------------------- 1 | # git 2 | 3 | We use git as a our version control system. 4 | 5 | * [git](git.md) 6 | * [Semver](semver.md) 7 | 8 | [Main table of contents](../README.md#table-of-contents) 9 | -------------------------------------------------------------------------------- /javascript/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript 2 | 3 | We use JavaScript both in the client and on the server. 4 | 5 | * [House style](house-style.md) 6 | 7 | [Main table of contents](../README.md#table-of-contents) 8 | -------------------------------------------------------------------------------- /css/README.md: -------------------------------------------------------------------------------- 1 | # CSS 2 | 3 | We use Sass to generate CSS, and we organise it using a visual component-led approach. 4 | 5 | * [House style](house-style.md) 6 | * [BEM CSS](bem-css.md) 7 | * [How we write CSS](how-we-write-css.md) 8 | 9 | [Main table of contents](../README.md#table-of-contents) 10 | -------------------------------------------------------------------------------- /writing/README.md: -------------------------------------------------------------------------------- 1 | # Writing 2 | 3 | We write for a variety of audiences, and we must therefore take that into account whenever we write. 4 | 5 | * [House style](house-style.md) 6 | * [Inclusive language](inclusive-language.md) 7 | * [Social media](social-media.md) 8 | 9 | [Main table of contents](../README.md#table-of-contents) 10 | -------------------------------------------------------------------------------- /learning/README.md: -------------------------------------------------------------------------------- 1 | # Learning resources 2 | 3 | In this section we offer curated lists of learning resources that people can use to get started or improve their knowledge of accessibility or web performance. 4 | 5 | * [Accessibility](web-accessibility.md) 6 | * [Web performance](web-performance.md) 7 | 8 | [Main table of contents](../README.md#table-of-contents) 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 4 8 | indent_style = tab 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.json] 13 | insert_final_newline = false 14 | indent_size = 2 15 | indent_style = space 16 | 17 | [*.md] 18 | indent_size = 2 19 | indent_style = space 20 | trim_trailing_whitespace = false 21 | 22 | [*.yml] 23 | indent_size = 2 24 | indent_style = space 25 | -------------------------------------------------------------------------------- /performance/README.md: -------------------------------------------------------------------------------- 1 | # Performance 2 | 3 | Performance refers to the speed in which web pages are downloaded and displayed on the user's browser. 4 | 5 | Faster page speeds have been shown to increase visitor retention and user satisfaction, especially for users with slow internet connections and those on mobile devices. Improved web performance also leads to less data travelling across the web, which in turn lowers a website's power consumption and environmental impact. 6 | 7 | - [Advertising](advertising.md) 8 | - [Browser caching](browser-caching.md) 9 | - [Font loading](font-loading.md) 10 | - [Images](images.md) 11 | - [Performance checklist](performance-checklist.md) 12 | 13 | [Main table of contents](../README.md#table-of-contents) 14 | -------------------------------------------------------------------------------- /security/README.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | All web developers should be aware of security risks related to web technologies. 4 | 5 | * The Open Worldwide Application Security Project ([OWASP](https://owasp.org/)) is a nonprofit foundation that works to improve the security of software. They maintain a [top 10 list of critical security risks in web applications](https://owasp.org/www-project-top-ten/), which is essential reading. 6 | * Mozilla's open-source infosec documentation contains an excellent [Web Security Cheat Sheet](https://infosec.mozilla.org/guidelines/web_security.html) we encourage you to read. 7 | * We publish a document to help you create [secure markup](secure-markup.md). 8 | 9 | [Main table of contents](../README.md#table-of-contents) 10 | -------------------------------------------------------------------------------- /learning/web-accessibility.md: -------------------------------------------------------------------------------- 1 | # Web accessibility 2 | 3 | This is a list of different resources that we offer to people interested in knowing more about web accessibility. 4 | 5 | Udacity have published an [excellent free course on Web Accessibility](https://www.udacity.com/course/web-accessibility--ud891) with Google engineers Alice Boxhall and Rob Dodson. 6 | 7 | The Financial Times have produced an [accessibility tip sheet](https://ft-interactive.github.io/accessibility/index.html). 8 | 9 | The Government Digital Service frequently publishes excellent resources. Some highlights are: 10 | 11 | * [We're making accessibility clearer and easier](https://gds.blog.gov.uk/2017/10/23/were-making-accessibility-clearer-and-easier/) 12 | * [Making your service accessible: an introduction](https://www.gov.uk/service-manual/helping-people-to-use-your-service/making-your-service-accessible-an-introduction) 13 | -------------------------------------------------------------------------------- /accessibility/common-remediations/README.md: -------------------------------------------------------------------------------- 1 | # Common remediations 2 | 3 | This part of the Playbook describes some common accessibility issues that _can't_ be detected with automated tools, and gives examples and suggestions for repairs. 4 | 5 | It's not exhaustive, and shouldn't be treated as such - these are just some of the mistakes that Accessibility Enablement frequently encounter that you should familiarise yourself with so that you can avoid them in your own work. 6 | 7 | It's also not a substitute for familiarising yourself with WCAG directly. 8 | 9 | * [Success Criterion 1.1.1 Non-text content](sc-1.1.1.md) 10 | * [Success Criterion 1.3.1 Info and Relationships](sc-1.3.1.md) 11 | * [Success Criterion 1.3.2 Meaningful Sequence](sc-1.3.2.md) 12 | * [Success Criterion 1.4.1 Use of Color](sc-1.4.1.md) 13 | * [Success Criterion 1.4.10 Reflow](sc-1.4.10.md) 14 | * [Success Criterion 2.1.1 Keyboard](sc-2.1.1.md) 15 | * [Success Criterion 2.4.11 Focus Not Obscured (Minimum)](sc-2.4.11.md) 16 | * [Success Criterion 3.1.1 Language of Page and Success Criterion 3.1.2 Language of Parts](sc-3.1.1-and-3.1.2.md) 17 | * [Success Criterion 3.2.2 On Input](sc-3.2.2.md) 18 | 19 | [Main table of contents](../../README.md#table-of-contents) 20 | -------------------------------------------------------------------------------- /practices/README.md: -------------------------------------------------------------------------------- 1 | # Practices 2 | 3 | Development of products at Springer Nature is informed by two primary constraints: 4 | 5 | * The products that Springer Nature produce are used in an enormous variety of contexts, by an enormous variety of users, all of them spread across the planet. We have no way of knowing the situation that any given user could be in. We must deal with: 6 | * The variety of technical conditions: Device; operating system; network connection; CPU; browser; screen size; interface; institutional network policies; browser extensions; ISP-injected scripts. 7 | * The infinite variety of the human experience: User context; user disabilities; user time limits; user financial status. 8 | * We have a number of obligations to ensure our products conform to the WCAG 2.1 guidelines, to the “AA” level of Success Criteria. 9 | 10 | * [Code reviews](code-review.md) 11 | * [(Graded) Browser support](graded-browser-support.md) 12 | * [House style](house-style.md) 13 | * [Javascript dependent styling](javascript-styling.md) 14 | * [Managing node projects](managing-node-projects.md) 15 | * [Managing static assets](managing-static-assets.md) 16 | * [Open source support](open-source-support.md) 17 | * [Progressive enhancement](progressive-enhancement.md) 18 | * [Structured data](structured-data.md) 19 | 20 | [Main table of contents](../README.md#table-of-contents) 21 | -------------------------------------------------------------------------------- /practices/javascript-styling.md: -------------------------------------------------------------------------------- 1 | # Javascript dependent styling 2 | 3 | A class name of `.js` on the document root element (normally `html`) is used to target JS-dependent visual styles via CSS. 4 | 5 | ## Scripts 6 | 7 | The `.js` class must be added via a micro—but blocking—script, placed as far up in the `` of the document as possible. 8 | 9 | The blocking nature of the script prevents any visual flickering or browser reflows, unlike other techniques where JavaScript may cause styles to be applied after the page has rendered. 10 | 11 | ```html 12 | 16 | ``` 17 | 18 | ## Styles 19 | 20 | All UI elements MUST be usable and visually-acceptable when Javascript is not present. Enhancements can be made when Javascript is present by nesting those styles underneath the `.js` class. 21 | 22 | Following the principles of [Progressive Enhancement](./progressive-enhancement.md), consider building and releasing your core unenhanced version first. Then build and deliver the Javascript enhanced version in a subsequent iteration. 23 | 24 | ```scss 25 | // Define core styles 26 | .c-component { 27 | color: black; 28 | padding-bottom: 1rem; 29 | } 30 | 31 | // Add and override declarations when JS is present 32 | .js .c-component { 33 | height: 200px; 34 | padding-bottom: 0; // overridden now that JS is present 35 | background-color: #e4e4e4; 36 | margin: 10px; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /accessibility/common-remediations/sc-2.4.11.md: -------------------------------------------------------------------------------- 1 | # Success Criterion 2.4.11 Focus Not Obscured (Minimum) 2 | 3 | Keyboard focus must be visible - if a sighted keyboard user can't see a focus ring or similar focus styling, they will be unable to locate themselves on the page. 4 | 5 | See [Understanding Focus Not Obscured (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/focus-not-obscured-minimum.html) for further details. 6 | 7 | The issues and remediations listed in this file are not exhaustive. 8 | 9 | ## The issues 10 | 11 | - [Missing or inadequate focus styles](#missing-or-inadequate-focus-styles) 12 | 13 | ### Missing or inadequate focus styles 14 | 15 | #### What's the problem? 16 | 17 | Focus styles are missing from interactive elements, or are present but difficult to see. 18 | 19 | #### Who's affected by the problem? 20 | 21 | * Keyboard users 22 | * Low vision users browsing with a magnifier 23 | 24 | #### Why's it a problem? 25 | 26 | Not everyone uses a mouse. Some users navigate through a page with their keyboard by pressing the tab key to move from one focusable element to another. If focus styles are removed or insufficient, these users have no way of knowing which element they are about to activate. 27 | 28 | All elements that receive focus MUST have visible focus styles. 29 | 30 | Browser default focus styles are likely insufficient as they can be difficult to see in some designs. We prefer focus styles to be highly visible. 31 | 32 | #### How do I fix it? 33 | 34 | We do this: 35 | ```css 36 | a:focus { 37 | outline: 3px solid #fece3e; 38 | } 39 | 40 | a:focus, button:focus { 41 | background-color: #fc0; 42 | outline: 2px solid #fc0; 43 | } 44 | ``` 45 | 46 | We _don't_ do this: 47 | ```css 48 | a:focus { 49 | outline: 0; 50 | } 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /writing/social-media.md: -------------------------------------------------------------------------------- 1 | # Social media 2 | 3 | - [Cruft.io](#cruftio) 4 | - [Posting publicly](#posting-publicly) 5 | 6 | An important part of our work as developers is not only to create quality products, but also to raise awareness of accessibility, performance and progressive enhancement best practices. This includes promoting our work and our practices in open spaces like social media, conferences, talks and other events. 7 | 8 | For open-source projects, we aim to keep our projects up to date and fix any vulnerabilities in a timely fashion. Please see our [Open Source Support page](https://github.com/springernature/frontend-playbook/blob/main/practices/open-source-support.md) for details on how we do this. 9 | 10 | ## Cruft.io 11 | 12 | [Cruft.io](http://cruft.io) is a blog run by Springer Nature Technology. Anyone can post there and the instructions can be found in the [project's wiki (internal)](https://github.com/springernature/cruft/). 13 | 14 | ## Posting publicly 15 | 16 | Before publishing anything ensure that: 17 | 18 | * All the public communications follow our [language standards](house-style.md). 19 | * When reporting bugs or security issues, remember to use positive language instead of blaming. 20 | * Always use [inclusive language](inclusive-language.md). 21 | 22 | We do: 23 | > Released Shunter 1.2.3. Security upgrade of `nac` to 3.2.1 which addresses several vulns. https://github.com/springernature/shunter/blob/master/HISTORY.md#123-2017-03-08 24 | 25 | We _don't_ do: 26 | > Released Shunter 1.2.3. Fixes a vulnerability which was caused by a bug in `nac`, breaking our project. https://github.com/springernature/shunter/blob/master/HISTORY.md#123-2017-03-08 27 | 28 | * Always provide links where people can find further information if interested. E.g. a changelog for a software release, a blog article, a link to the frontend playbook, etc. 29 | -------------------------------------------------------------------------------- /learning/web-performance.md: -------------------------------------------------------------------------------- 1 | # Web performance 2 | 3 | This is a list of different resources that we offer to people interested in knowing more about web performance. 4 | 5 | ## Online courses 6 | 7 | For people wanting to learn about web performance we recommend to have a look at the following courses: 8 | 9 | * ["Lightning-fast web performance"](https://scottjehl.com/lfwp/) by Scott Jehl is an excellent short introductory course that has been recently made free. 10 | * ["Web Performance Fundamentals"](https://frontendmasters.com/courses/web-perf/) by Todd Gardner covers things in more detail. A subscription to Frontend Masters is required. 11 | 12 | ## Books 13 | 14 | The following books can be used as refererence. Some of them have been published for a while so not all advice may be applicable today, but they are still very useful to improve knowledge of a particular subject. 15 | 16 | * "High Performance Web Sites" by Steve Souders: https://learning.oreilly.com/library/view/high-performance-web/9780596529307/ 17 | * "Even Faster Web Sites" by Steve Souders: https://learning.oreilly.com/library/view/even-faster-web/9780596803773/ 18 | * "High Performance Browser Networking" by Ilya Grigorik: https://hpbn.co/ 19 | * "HTTP/2 in Action" by Barry Pollard: https://learning.oreilly.com/library/view/http-2-in-action/9781617295164/ 20 | * "Using WebPageTest" by Rick Viscomi, Andy Davies & Marcel Duran: https://learning.oreilly.com/library/view/using-webpagetest/9781491902783/ 21 | * "Time Is Money" by Tammy Everts: https://learning.oreilly.com/library/view/time-is-money/9781491928783/ 22 | 23 | ## Videos 24 | 25 | * Catchpoint frequently releases videos showcasing new features of WebPageTest, or Twitch streams of their performance auditing sessions: 26 | https://www.youtube.com/channel/UC5CqJ9V7cQddZDf1DKXcy7Q/featured 27 | * The London Web Performance Group has a youtube channel with most of their talks: https://www.youtube.com/user/ldnwebperf/videos 28 | 29 | ## Other resources 30 | 31 | * Google has three collections of web performance-related material available on their web.dev site: https://web.dev/learn/#collections 32 | -------------------------------------------------------------------------------- /accessibility/common-remediations/sc-3.2.2.md: -------------------------------------------------------------------------------- 1 | # Success Criterion 3.2.2 On Input 2 | 3 | The user must retain control over context changes so that they can be confident that the service will behave predictably. 4 | 5 | See [Understanding On Input](https://www.w3.org/WAI/WCAG22/Understanding/on-input.html) for further details. 6 | 7 | The issues and remediations listed in this file are not exhaustive. 8 | 9 | ## The issues 10 | - [No advance warning when opening new window](#no-advance-warning-when-opening-new-window) 11 | 12 | ### No advance warning when opening new window 13 | 14 | #### What's the problem? 15 | 16 | Links open in new window without warning the user that this will happen. 17 | 18 | #### Who's affected by the problem? 19 | 20 | * Screen reader users 21 | * Low vision users who magnify the entire screen 22 | * Users with cognitive challenges 23 | 24 | #### Why's it a problem? 25 | 26 | Having a window open unexpectedly when you click on a link can be disorientating to users who can only see a portion of the screen, who can't see the screen at all, or who can become easily distracted by unexpected changes to their browsing context. 27 | 28 | #### How do I fix it? 29 | 30 | Avoid opening links in new tabs or windows wherever possible. 31 | 32 | If you really have to do it, warn the user before they click on the link that it'll open in a new window. You can use text like "opens in a new window" or a visual icon. If you choose to use an icon, make sure it's accessible to screen reader users. 33 | 34 | You MUST use `rel="noopener"` on outbound links that open in a new window. See the [secure markup guide](https://github.com/springernature/frontend-playbook/blob/main/security/secure-markup.md#add-relnoopener-to-outbound-links-in-new-windows) for an explanation. 35 | 36 | We do this: 37 | ```html 38 | 39 | My site (opens in a new window) 40 | 41 | 42 | Or 43 | 44 | 45 | My site opens in a new window 46 | 47 | ``` 48 | 49 | We don’t do this: 50 | ```html 51 | All about Knitting 52 | ``` 53 | -------------------------------------------------------------------------------- /accessibility/common-remediations/sc-1.3.2.md: -------------------------------------------------------------------------------- 1 | # Success Criterion 1.3.2 Meaningful Sequence 2 | 3 | Content can be shifted around on screen using CSS or JavaScript so that it no longer matches the DOM order. This can be detectable to screen reader or other keyboard users who rely on the DOM to understand the sequence of the page. 4 | 5 | See [Understanding Meaningful Sequence](https://www.w3.org/WAI/WCAG22/Understanding/meaningful-sequence.html) and its associated Success Criteria for further details. 6 | 7 | The issues and remediations listed in this file are not exhaustive. 8 | 9 | ## The issues 10 | 11 | - [Visual order doesn't match source order](#visual-order-doesnt-match-source-order) 12 | 13 | ### Visual order doesn't match source order 14 | 15 | #### What's the problem? 16 | 17 | CSS positioning has been used so that the visual order of interactive elements doesn't match the HTML source order. 18 | 19 | #### Who's affected by the problem? 20 | 21 | * Keyboard users 22 | * Screen reader users 23 | 24 | #### Why's it a problem? 25 | 26 | Keyboard users (including screen reader users) expect to tab forwards and backwards through interactive elements in a linear sequence. For left-to-right languages, this means the elements should be presented in left-to-right order. 27 | 28 | Switching the visual order of elements with CSS but not changing the order in the source code can lead to focus being placed on unexpected elements, which can confuse users or cause them to activate the wrong control. 29 | 30 | For example, using a `float:right;` on an interactive element can make it visually appear to be the last control in a group, but when a keyboard user tabs into the component, it may be the first control they interact with. 31 | 32 | #### How do I fix it? 33 | 34 | * Take care when using CSS positioning, flexbox, and grid layouts 35 | * Make sure the visual order of components matches the order in the HTML source 36 | * Tab through your document to make sure the focus order is expected 37 | * If the order of the content matters (e.g. an in-page navigation panel is only useful to a keyboard user if it appears before the main page content), amend the DOM structure accordingly 38 | 39 | We do this: 40 | ```html 41 | 42 | 43 | 44 | ``` 45 | 46 | We don't do this: 47 | ```html 48 | 49 | 50 | 51 | ``` 52 | -------------------------------------------------------------------------------- /accessibility/common-remediations/sc-1.4.10.md: -------------------------------------------------------------------------------- 1 | # Success Criterion 1.4.10 Reflow 2 | 3 | Users with low vision may magnify the screen to be able to read text. Your web pages need to be responsive so that they allow these users to read text comfortably without horizontal scrolling or being impeded by design elements. 4 | 5 | To meet WCAG 2.1 AA, you need to allow for up to 400% magnification. See [Understanding Resize text](https://www.w3.org/WAI/WCAG21/Understanding/resize-text.html) and [Understanding Reflow](https://www.w3.org/WAI/WCAG21/Understanding/reflow.html) for further details. 6 | 7 | ## The issues 8 | 9 | - [Content obscured at high magnification](#content-obscured-at-high-magnification) 10 | - [Information removed at high magnification](#information-removed-at-high-magnification) 11 | 12 | ### Content obscured at high magnification 13 | 14 | #### What's the problem? 15 | 16 | When the screen is magnified, content is obscured. Text or functionality may be pushed off-screen. Elements may overlap with or cover up other elements. 17 | 18 | #### Who's affected by the problem? 19 | 20 | * Low-vision users 21 | 22 | #### Why's it a problem? 23 | 24 | Low-vision users may need to zoom or magnify content in their browsers to be able to use a website. If content or functionality is obscured when they do this, they may be unable to read or use the website. 25 | 26 | #### How do I fix it? 27 | 28 | Use a [responsive design](https://www.smashingmagazine.com/2011/01/guidelines-for-responsive-web-design/). 29 | 30 | Make sure that nothing in your layout becomes visually obscured down to a width of 320px. 31 | 32 | ### Information removed at high magnification 33 | 34 | #### What's the problem? 35 | 36 | When the screen is magnified (or when using a mobile layout), important information is removed. Text labels for icons may be removed from the UI, or menu items could be lost. 37 | 38 | #### Who's affected by the problem? 39 | 40 | * Low-vision users 41 | * Mobile device users 42 | 43 | #### Why's it a problem? 44 | 45 | Low-vision users may need to zoom or magnify content in their browsers to be able to use a website. In a responsively-designed website, this may effectively put them into the "mobile" layout. 46 | 47 | Removing information for visual effect may make it difficult for these users to interpret content, or move around the site effectively. 48 | 49 | #### How do I fix it? 50 | 51 | Avoid "hiding" content in mobile layouts - if it's important enough to display on desktop, it's important enough to display on mobile. 52 | 53 | Make sure that the "mobile" content has parity with the "desktop" content. -------------------------------------------------------------------------------- /git/semver.md: -------------------------------------------------------------------------------- 1 | # SemVer 2 | 3 | * [What is SemVer](#what-is-semver) 4 | * [Why we use SemVer](#why-we-use-semver) 5 | * [Common concerns](#common-concerns) 6 | * [How can I trust that things aren’t going to break with a minor or patch release update?](#how-can-i-trust-that-things-arent-going-to-break-with-a-minor-or-patch-release-update) 7 | * [The version number is getting really big really quickly!](#the-version-number-is-getting-really-big-really-quickly) 8 | * [Find out more:](#find-out-more) 9 | 10 | 11 | ## What is SemVer 12 | 13 | SemVer is a way of versioning software in the format of MAJOR.MINOR.PATCH: 14 | 15 | * MAJOR version when you make breaking changes, 16 | * MINOR version when you add functionality in a backwards-compatible manner for any specific MAJOR version, and 17 | * PATCH version when you make backwards-compatible bug fixes to any specific MAJOR.MINOR version. 18 | 19 | This means that any time you release a new MAJOR release, the minor and patch values reset to 0, and the same is true of the patch value when making a MINOR release. 20 | 21 | For more information about how SemVer is defined, please see: http://semver.org/ 22 | 23 | ## Why we use SemVer 24 | 25 | SemVer allows us to keep a consistent numbering scheme to ensure that going forward we can maintain compatibility with all system and platform components. It also allows us to upgrade dependencies with the confidence that things won’t break. 26 | 27 | SemVer enables us to ensure that once something is committed we can be confident that any version remains unique. 28 | 29 | ## Common concerns 30 | 31 | ### How can I trust that things aren’t going to break with a minor or patch release update? 32 | 33 | Like any practice, SemVer can be let down by people not using it correctly (like releasing a breaking change under a minor version rather than a major). It’s the responsibility of the person upgrading to ensure that the upgrade is appropriate and compatible. 34 | 35 | ### The version number is getting really big really quickly! 36 | 37 | When a piece of software under heavy development many major/minor releases may happen in quick succession, so your version might start to look like 23.2.0 or 3.34.1. THAT’S OKAY! If that’s a true representation of what has happened in the code, then it’s appropriate that the version number reflects that. 38 | 39 | What _might_ be a worry is if your version looked like 2.1.45 - did you really release 45 patches/bug fixes in a row without adding any new features? 40 | 41 | ## Find out more: 42 | 43 | * [Canonical source of info](http://semver.org/) 44 | * [How we version and release our open-source software](../practices/open-source-support.md) 45 | * [What is Semantic Versioning (SemVer)?](https://abdulapopoola.com/2015/10/26/what-is-semver/) 46 | -------------------------------------------------------------------------------- /css/config/.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "at-rule-empty-line-before": [ "always", { 4 | "except": ["blockless-group"] 5 | } ], 6 | "block-closing-brace-newline-after": "always", 7 | "block-closing-brace-newline-before": "always-multi-line", 8 | "block-closing-brace-space-before": "always-single-line", 9 | "block-no-empty": true, 10 | "block-opening-brace-newline-after": "always-multi-line", 11 | "block-opening-brace-space-after": "always-single-line", 12 | "block-opening-brace-space-before": "always", 13 | "color-hex-case": "lower", 14 | "color-hex-length": "short", 15 | "color-no-invalid-hex": true, 16 | "comment-empty-line-before": [ "always", { 17 | "except": ["first-nested"] 18 | }], 19 | "declaration-bang-space-after": "never", 20 | "declaration-bang-space-before": "always", 21 | "declaration-block-semicolon-newline-after": "always-multi-line", 22 | "declaration-block-semicolon-space-after": "always-single-line", 23 | "declaration-block-semicolon-space-before": "never", 24 | "declaration-block-single-line-max-declarations": 0, 25 | "declaration-colon-newline-after": "always-multi-line", 26 | "declaration-colon-space-after": "always-single-line", 27 | "declaration-colon-space-before": "never", 28 | "function-calc-no-unspaced-operator": true, 29 | "function-comma-newline-after": "always-multi-line", 30 | "function-comma-space-after": "always-single-line", 31 | "function-comma-space-before": "never", 32 | "function-parentheses-newline-inside": "always-multi-line", 33 | "function-parentheses-space-inside": "never-single-line", 34 | "function-whitespace-after": "always", 35 | "indentation": "tab", 36 | "max-empty-lines": 1, 37 | "media-feature-colon-space-after": "always", 38 | "media-feature-colon-space-before": "never", 39 | "media-feature-range-operator-space-after": "always", 40 | "media-feature-range-operator-space-before": "always", 41 | "media-query-list-comma-newline-after": "always-multi-line", 42 | "media-query-list-comma-space-after": "always-single-line", 43 | "media-query-list-comma-space-before": "never", 44 | "media-query-parentheses-space-inside": "never", 45 | "no-eol-whitespace": true, 46 | "no-missing-eof-newline": true, 47 | "number-leading-zero": "always", 48 | "number-no-trailing-zeros": true, 49 | "number-zero-length-no-unit": true, 50 | "rule-no-shorthand-property-overrides": true, 51 | "rule-non-nested-empty-line-before": "always-multi-line", 52 | "rule-trailing-semicolon": "always", 53 | "selector-combinator-space-after": "always", 54 | "selector-combinator-space-before": "always", 55 | "selector-list-comma-newline-after": "always", 56 | "selector-list-comma-space-before": "never", 57 | "string-quotes": "single", 58 | "value-list-comma-newline-after": "always-multi-line", 59 | "value-list-comma-space-after": "always-single-line", 60 | "value-list-comma-space-before": "never" 61 | } 62 | } -------------------------------------------------------------------------------- /performance/browser-caching.md: -------------------------------------------------------------------------------- 1 | # Browser caching 2 | 3 | - [HTML Markup](#html-markup) 4 | - [CSS, JS and Images](#css-js-and-images) 5 | - [General](#general) 6 | - [Further resources](#further-resources) 7 | 8 | ## HTML Markup 9 | 10 | * Serve these with a `Cache-Control: no-cache` header. This will instruct the browser to cache locally but only after checking with the server that the content hasn’t changed. Note that `no-cache` does NOT mean "don’t cache", rather it tells the browser to always revalidate when the resource is requested. `no-store` tells the browser not to cache at all, which isn’t usually desirable. 11 | * See [Caching best practices](https://jakearchibald.com/2016/caching-best-practices/) for more information. 12 | 13 | ## CSS, JS and Images 14 | 15 | * Set a long `max-age` eg: `Cache-Control: max-age: 31536000` (one year). The `max-age` directive states the maximum amount of time in seconds that fetched responses are allowed to be used again (from the time when a request is made) and because content on these URLs typically don't change, it is safe to cache them for really long periods. 16 | * Use a [cache-busting](https://www.keycdn.com/support/what-is-cache-busting) mechanism for versioning assets to ensure that the browser caches each version as a different URL. Example: `sncss-29d48c7.css` or `sncss.js?v=29d48c7` where “_29d48c7_” is an auto-generated number unique to every version of the file. Frameworks like [Shunter](https://github.com/springernature/shunter) use the filename version style which is preferred. 17 | 18 | ## General 19 | 20 | * If it is under your control, ensure the server provides an Entity Tag (`ETag`) header. The `ETag` header is an additional identifier for a specific version of a resource, typically comprised of the modified time and file size. (On older systems the ETag may also include an inode portion, but this is problematic.) The `Etag` header is especially useful to prevent simultaneous updates overwriting each other. If you use a CDN, it is likely this header will already be provided and properly configured. Learn more: 21 | * [MDN ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) 22 | * [Express options for 'ETag' setting](https://expressjs.com/en/api.html#etag.options.table) 23 | * You no longer need to use [`Expires` headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires) as it has been superseded by `Cache-Control` header with `max-age`, which is [supported by modern browsers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Browser_compatibility). 24 | 25 | It’s important to note that there isn’t a one-size-fits-all approach to caching, so always decide a caching strategy based on your needs. 26 | 27 | ## Further resources 28 | 29 | * [Web Fundamentals: HTTP Caching](https://web.dev/articles/http-cache) 30 | * [HTTP Cache Headers: A Complete Guide](https://www.keycdn.com/blog/http-cache-headers) 31 | -------------------------------------------------------------------------------- /accessibility/common-remediations/sc-1.4.1.md: -------------------------------------------------------------------------------- 1 | # Success Criterion 1.4.1 Use of Color 2 | 3 | Partial sight, aging and congenital color deficits all produce changes in perception that reduce the visual effectiveness of certain color combinations. 4 | 5 | See [Understanding Use of Color](https://www.w3.org/WAI/WCAG22/Understanding/use-of-color.html) for further details. 6 | 7 | The issues and remediations listed in this file are not exhaustive. 8 | 9 | ## The issues 10 | 11 | - [Information conveyed by colour alone](#information-conveyed-by-colour-alone) 12 | 13 | ### Information conveyed by colour alone 14 | 15 | #### What's the problem? 16 | 17 | Some kind of information is conveyed with colour, with no supplementation in text or by some other method. 18 | 19 | Examples may include (but are not limited to): 20 | 21 | * Changing the background colour of an input field to red to indicate an error without also providing an error message 22 | * Changing the colour of an icon or text string to indicate some kind of status 23 | * Using a graph or a chart where colour is the only way to indicate different aspects of the data 24 | * Removing underlines from hyperlinks, leaving just colour to differentiate them from surrounding text 25 | 26 | #### Who's affected by the problem? 27 | 28 | * Screen reader users 29 | * Users with colour blindness 30 | * Low-vision users who use high contrast modes 31 | * Users with monochromatic displays or displays with inaccurate colour reproduction 32 | * All users if a stylesheet containing colour information fails to load for any reason (network problems, server issues, etc.) 33 | 34 | #### Why's it a problem? 35 | 36 | Screen reader users without a display can never see colour, and nor can users who are experiencing problems loading your stylesheets. 37 | 38 | Colour blind or high contrast display users may not perceive colours in the way you intended, and in some cases may be unable to perceive your colour choices at all. 39 | 40 | Any kind of information that's only conveyed using colour can't convey that information if the colour isn't perceivable by the user. 41 | 42 | #### How do I fix it? 43 | 44 | You can use colour to indicate statuses or differences, but supplement it with something else. 45 | 46 | This can include (but is not limited to): 47 | 48 | * Text labels and descriptions 49 | * Error messages presented in text 50 | 51 | In charts or graphs: 52 | 53 | * Consider using a monochrome colour palette 54 | * Use different [relative luminance](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_Colors_and_Luminance) for different data points 55 | * Use different fill patterns in addition to solid colour areas 56 | * Use unambiguous text labels for lines or bars 57 | 58 | For links: 59 | 60 | * Never indicate a link with `color` alone 61 | * Use `text-decoration: underline` (automatically applied by user agents) in all but special cases, such as navigation menus 62 | -------------------------------------------------------------------------------- /performance/advertising.md: -------------------------------------------------------------------------------- 1 | # Advertising 2 | 3 | - [Ethical](#ethical) 4 | - [Accessibility](#accessibility) 5 | - [Performance](#performance) 6 | - [References](#references) 7 | 8 | These guidelines are based on ethical, [accessibility](../accessibility/README.md) and performance recommendations and best practices. 9 | 10 | ## Ethical 11 | 12 | * Do use clear, intelligible, and unambiguous information. 13 | * Don't use ads that are misleading. For example, "trick banners" that look like part of the operating system UI. 14 | * Don't use ads that advertise businesses that participate in spammy or scammy practices. 15 | * Don't use images that convey a false sense of urgency. 16 | * Don't advertise products with obvious exaggerations or dubious claims that are impossible to prove. 17 | * Don't advertise "free" products or services that have hidden costs or charges. 18 | * Don't advertise gambling, alcohol and tobacco. 19 | * Don't use [pop-under ads](https://en.wikipedia.org/wiki/Pop-up_ad#Pop-under_ads). 20 | * Adverts must not contain spyware, malware or any software that results in an unexpected or deceptive experience. This includes links to sites containing these products. 21 | 22 | ## Accessibility 23 | 24 | * Don't use ads that make use of fast animations or flashing content. 25 | * The ad content must have clearly defined borders and not be confused with normal page content. 26 | * Audio or video in ads must be user initiated. A control must be included in order to allow for audio/video initiation and stop. 27 | 28 | All advertising must also comply with the rest of our [accessibility guidelines](../accessibility/06-accessibility-checklist.md). 29 | 30 | ## Performance 31 | 32 | * Do load ads asynchronously. 33 | * Don't use ads that add a significant size to the page. 34 | * Do use a maximum of 15 file requests for initial file load, as per the [IAB display advertising guidelines](https://www.iab.com/guidelines/iab-display-advertising-guidelines/). 35 | * All assets must be packaged together for delivery. All assets should be delivered in compressed format (e.g. GZIP). 36 | 37 | ## References 38 | 39 | * IAB Display Advertising Guidelines 40 | [https://www.iab.com/guidelines/iab-display-advertising-guidelines/](https://www.iab.com/guidelines/iab-display-advertising-guidelines/) 41 | 42 | * UK Code of Non-broadcast Advertising and Direct & Promotional Marketing (CAP Code) [https://www.asa.org.uk/codes-and-rulings/advertising-codes/non-broadcast-code.html](https://www.asa.org.uk/codes-and-rulings/advertising-codes/non-broadcast-code.html) 43 | 44 | * Advertising Standards Authority (ASA) 45 | [https://www.asa.org.uk/](https://www.asa.org.uk/) 46 | 47 | * Facebook Advertising Policies 48 | [https://www.facebook.com/policies/ads](https://www.facebook.com/policies/ads) 49 | 50 | * Pinterest Advertising Standards 51 | [https://about.pinterest.com/en/advertising-standards](https://about.pinterest.com/en/advertising-standards) 52 | 53 | * LinkedIn Advertising Guidelines 54 | [https://www.linkedin.com/legal/sas-guidelines](https://www.linkedin.com/legal/sas-guidelines) 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Frontend Playbook 2 | 3 | This repo contains The Frontend Playbook. It details how we run software development and how we make web and mobile products together. It's filled with things we've learned based on our own experience and study of others' experiences. 4 | 5 | The main motivator for this playbook is not to document a list of guidelines, but rather to create an opportunity to collaborate on them, and to gain consensus. 6 | 7 | This is a living document that we contribute to in a _public_ GitHub repo. Reasons for doing this in the open include (but are not limited to): 8 | 9 | 1. Interacting with and learning from others. Receiving contributions from people who don't work here can help us, providing learning opportunities that we would not receive otherwise - for example, see [this contribution](https://github.com/springernature/frontend-playbook/pull/48#issuecomment-236139605) from @rowanmanning. 10 | 11 | 1. Providing a showcase for our work/ethics. This is _really_ useful when hiring people (for both parties). We've had very positive feedback from interviewees - it's a great recruiting tool. It also means that people are quickly up and running when they join. 12 | 13 | See "[Changing the laws of engineering with pull requests](https://www.youtube.com/watch?v=YIpNpptGX6Q)" for an in depth explanation of how developing a playbook like this is of benefit. 14 | 15 | ## Sections 16 | 17 | There's no particular order to which you should read the playbook, but the [Practices section](practices/README.md) is probably a good starting point. 18 | 19 | * [Accessibility](accessibility/README.md) 20 | * [CSS](css/README.md) 21 | * [Git](git/README.md) 22 | * [JavaScript](javascript/README.md) 23 | * [Markup](markup/README.md) 24 | * [Performance](performance/README.md) 25 | * [Practices](practices/README.md) 26 | * [Security](security/README.md) 27 | * [Writing](writing/README.md) 28 | 29 | ## Contributing 30 | 31 | To contribute please clone the repo (or fork it if you're an external contributor), create a new branch for your changes, then create a pull request to merge your changes in. 32 | 33 | Please keep discussion inside the issues and pull requests, avoiding Slack, hallway conversations etc. Remember that this repo is public, and the discussions we have can be of benefit to people apart from us. 34 | 35 | [Read the full contributor guide](CONTRIBUTING.md). 36 | 37 | ## Key words 38 | 39 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP (Best Current Practice) 14](https://www.rfc-editor.org/info/bcp14) ([RFC 2119](https://tools.ietf.org/html/rfc2119), [RFC8174](https://tools.ietf.org/html/rfc8174)) when, and only when, they appear in all capitals, as shown here. 40 | 41 | ## License 42 | 43 | The Frontend Playbook is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. 44 | 45 | You should have received a copy of the license along with this work. If not, see [Creative Commons BY-NC-SA 4.0 license](http://creativecommons.org/licenses/by-nc-sa/4.0/). 46 | -------------------------------------------------------------------------------- /practices/managing-static-assets.md: -------------------------------------------------------------------------------- 1 | # Managing static assets 2 | 3 | Static assets are files that don't need to be generated, modified or processed by an application before being delivered to the user. This typically includes CSS, JavaScript, images and web fonts. Static assets change rarely, and their content doesn't depend on user input or preferences. 4 | 5 | **We [MUST][rfc-2119] host these kinds of static resources on our own infrastructure and Content Delivery Network (CDN) instead of including them on our pages from a third-party CDN.** 6 | 7 | JavaScript files or libraries introduce security and data compliance risk. Resources related to fonts and videos also carry heightened data compliance risk on the basis of legal precedence. 8 | 9 | Self-hosting static assets has several advantages over relying on third parties for their delivery: 10 | 11 | * **Data protection.** When a user requests a resource from a third party service via a site we control, we are responsible for sharing their Personally Identifiable Information - such as user IP addresses - with the third party. We have a commitment to treating our users personal data with proper care, and a responsibility to the company to follow local privacy laws. 12 | * **Robustness.** As long as our site is up, the static resource will be up too. We don't depend on third party servers or additional CDNs besides our own, and we won't be affected by their outages, or closure of the service. 13 | * **Consistency.** Static assets are cached and served like the rest of our resources, and use the same CDN. As a result, resource timings and user experience are more consistent all around the world. 14 | * **Security.** Reduces our front-end [attack surface](https://en.wikipedia.org/wiki/Attack_surface) as the resources will enjoy the same level of security as the rest of first party content, and we don't have to trust the security of third parties. Self-hosting the asset makes it easier for us to use [Subresource Integrity (SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) for an additional layer of security. 15 | * **Control.** 16 | If we serve the asset we also have more control of how it's cached across the internet and by clients - so in the event of a compliance or security issue, we are able to react and protect our users and the company more quickly. 17 | * **Performance.** Self-hosting may save the users the cost of the DNS request, TCP connection and TLS negotiation for each CDN-hosted request, which in slow connections may make a big difference. This can also be mitigated with [`rel=dns-prefetch`](https://developer.mozilla.org/en-US/docs/Learn/Performance/dns-prefetch) and [`rel=preconnect`](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preconnect), but self-hosting the assets eliminates that penalty completely. 18 | * **Filtering.** Some CDNs are filtered by the [Great Firewall of China (GFW)](https://en.wikipedia.org/wiki/Great_Firewall). This can slow down the loading of certain resources, or even make them fail to load completely. Self-hosting static assets helps mitigate this, as all of the 1st party resources on a page will be served from the same place. 19 | 20 | [rfc-2119]: https://tools.ietf.org/html/rfc2119 21 | -------------------------------------------------------------------------------- /accessibility/common-remediations/sc-3.1.1-and-3.1.2.md: -------------------------------------------------------------------------------- 1 | # Success Criterion 3.1.1 Language of Page and Success Criterion 3.1.2 Language of Parts 2 | 3 | The HTML `lang` attribute is used to give information about the primary and secondary languages of your pages. It must be present and correct. 4 | 5 | See [Understanding Language of Page](https://www.w3.org/WAI/WCAG22/Understanding/language-of-page.html) and [Understanding Language of Parts](https://www.w3.org/WAI/WCAG22/Understanding/language-of-parts.html) for further details. 6 | 7 | The issues and remediations listed in this file are not exhaustive. 8 | 9 | ## The issues 10 | 11 | - [Specified language is incorrect](#specified-language-is-incorrect) 12 | - [Change in language not specified](#change-in-language-not-specified) 13 | 14 | ### Specified language is incorrect 15 | 16 | #### What's the problem? 17 | 18 | The language specified in the HTML `lang` attribute doesn't match the language used for the main page. 19 | 20 | #### Who's affected by the problem? 21 | 22 | * Screen reader users 23 | 24 | #### Why's it a problem? 25 | 26 | Words are pronounced differently in different languages. Screen reader software is designed to respect these pronunciation differences when it encounters web pages that specify their main language. 27 | 28 | If the language specified doesn't match the actual language used, the screen reader software may mispronounce the text of the page. 29 | 30 | #### How do I fix it? 31 | 32 | Make sure the language specified in the `lang` attribute accurately reflects the language of the page. If you provide a translated version of a page, make sure you provide the correct `lang` attribute, too. 33 | 34 | We do this: 35 | ```html 36 | 37 | ... 38 | Las razas estándar de gansos 39 | 40 | 41 | 42 | ... 43 | The Standard Breeds of Geese 44 | ``` 45 | 46 | We _don't_ do this: 47 | ```html 48 | 49 | ... 50 | Die Standardrassen von Gänsen 51 | ``` 52 | 53 | ### Change in language not specified 54 | 55 | #### What's the problem? 56 | 57 | An element on the page contains text in a different language to the rest of the page, but the change in language isn't signalled with a `lang` attribute. 58 | 59 | #### Who's affected by the problem? 60 | 61 | * Screen reader users 62 | 63 | #### Why's it a problem? 64 | 65 | Words are pronounced differently in different languages. Screen reader software is designed to respect these pronunciation differences when it encounters components on web pages that specify a change in language. 66 | 67 | If a piece of text in a document is presented in a different language without programmatically indicating the change, the screen reader software may mispronounce the text. 68 | 69 | #### How do I fix it? 70 | 71 | If you have text on a web page that is in a different language to the rest of the page, include the appropriate `lang` attribute in its wrapping element. 72 | 73 | We do this: 74 | ```html 75 | 76 | ... 77 | Las razas estándar de gansos 78 | ... 79 |

C'est un belle journee sur le village, et tu es un méchant oie.

80 | ``` 81 | 82 | We _don't_ do this: 83 | ```html 84 | 85 | ... 86 | The Standard Breeds of Geese 87 | ... 88 |

C'est un belle journee sur le village, et tu es un méchant oie.

89 | ``` -------------------------------------------------------------------------------- /writing/house-style.md: -------------------------------------------------------------------------------- 1 | # Language style guide 2 | 3 | * [Writing style](#writing-style) 4 | * [Tone of voice](#tone-of-voice) 5 | * [Plain English](#plain-english) 6 | * [Technical writing](#technical-writing) 7 | * [Frontend or front-end](#frontend-or-front-end) 8 | 9 | ## Writing style 10 | 11 | We don't enforce strict standards on writing style as we want you to use your own words to express your own personality. That said, we have three general sets of guidelines - tone of voice, plain English, and technical writing. 12 | 13 | ### Tone of voice 14 | 15 | For a general audience, you should write like a human. Be professional, but conversational - we want our contributors and readers to feel comfortable joining in at any time. 16 | 17 | Be thankful to contributors and those who log issues. They're giving up their time to make our playbook better. Make sure they know we're grateful to them. 18 | 19 | Maintain the same friendly and professional standards across the entire repository - in documentation, issues, pull requests, and comments. 20 | 21 | Always use [inclusive language](inclusive-language.md). 22 | 23 | ### Plain English 24 | 25 | Follow [Plain English guidelines](http://www.plainenglish.co.uk/how-to-write-in-plain-english.html) to help safeguard the accessibility of your written content. You might find tools like [Hemingway App](http://www.hemingwayapp.com/) helpful when editing. In particular: 26 | 27 | * Be concise 28 | * Check any sentences with more than 25 words to see if you can split them to make them clearer. 29 | * Ideally no more than 1-2 points per sentence. 30 | * Use contractions (e.g. "can't", "it's"). 31 | * Go straight to the point. 32 | * Avoid unnecessary words (e.g. There is, It is, very, really, pretty, just, actually). 33 | * Be specific 34 | - Prefer the active voice to the passive voice[\[1\]][active-passive] (e.g. "NPM will install the dependencies" instead of "the dependencies will be installed"). 35 | * Address the reader as "you" where possible. 36 | * Avoid referring to "things" or "stuff". 37 | * Be direct. Avoid metaphor, simile, and slang. 38 | * Be informative 39 | * Consider your audience. General information may not look the same as information aimed at a technical audience. 40 | * Be as precise as you can usefully be - consider linking to high quality external resources where relevant. 41 | 42 | ### Technical writing 43 | 44 | When expressing technical concepts, you'll need to use technical language. This may be complex, contain jargon, or seem formal. That's ok! Technical writing isn't for a general audience. Your priorities must be clarity, brevity, and accuracy. If you think your reader may need additional context to understand a concept, link out to external resources. 45 | 46 | All of the advice in the [plain English](#plain-english) section applies. Additionally: 47 | 48 | * Expand acronyms the first time you use them, and limit their use thereafter e.g. "Avoid the use of TLAs (Three Letter Acronyms)". 49 | * When defining technical requirements, you may use the keywords defined in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) for those requirement levels, e.g. "MUST", "SHOULD", "OPTIONAL", etc. 50 | 51 | ## Frontend or front-end 52 | 53 | Always use `frontend` regardless of the context. It's less confusing and error prone, and ensures consistency across all our documentation and portfolio of products. 54 | 55 | [active-passive]: https://oxfordediting.com/the-active-verb-form-makes-academic-writing-more-readable/ 56 | -------------------------------------------------------------------------------- /practices/code-review.md: -------------------------------------------------------------------------------- 1 | # Code reviews 2 | 3 | * [Why do them?](#why-do-them) 4 | * [What to look out for](#what-to-look-out-for) 5 | 6 | Code Review, or Peer Code Review, is the act of having your code checked by others for mistakes, errors, and omissions (e.g. missing tests). Like pair-programming (which we also support), it accelerates and streamlines software development. 7 | 8 | While we can support "traditional" Code Reviews, [we routinely review via **pull requests**](../git/git.md#pull-requests). These are communicated in the `#frontend-pr` Slack channel, and managed via GitHub. Discussion should happen in the GitHub comments, not Slack. 9 | 10 | Requesters merge their own changes when they're ready. Keep your fingers off that tempting green merge button. 11 | 12 | 13 | ## Why do them? 14 | 15 | **PR reviews are cross-team, thereby helping to foster discussion and feedback** 16 | 17 | 1. Knowledge sharing and transfer within and between teams: 18 | * Allows everyone to learn from their colleagues. 19 | * Allows greater visibility and familiarity of other team's work. 20 | * Helps prevent knowledge silos or domain-specific codebases. 21 | * Allows FEDs to share expertise. 22 | 1. Standards compliance across teams: 23 | * Aids the ability for developers to easily move between teams. 24 | * Ensures changes to codebase conforms to the same standards and guidelines. 25 | * Helps identify areas where code re-use are beneficial ("should that be a component?"). 26 | * Helps identify areas of compliance, which are missed during development. 27 | * Fosters caution and code quality over temporary hacks. 28 | 1. Prepares people for work on [open source software projects](https://github.com/springernature/open-source-directory). 29 | 1. Generally aids onboarding and training. 30 | 31 | 32 | ## What to look out for 33 | 34 | * **Accessibility** 35 | 36 | * [Accessibility](../accessibility/06-accessibility-checklist.md) problems. Suggest testing with [pa11y](https://github.com/pa11y) and/or other tools. 37 | * [pa11y dashboard](http://pa11y.springernature.com/) _(link only works if inside the Springer Nature VPN)_ 38 | 39 | * **Complexity** 40 | 41 | * [Overly complex code](https://www.codesimplicity.com/post/what-is-overengineering/): code that solves problems we don't have, or makes things more complex instead of less. 42 | * Code that introduces [out-of-date](https://docs.npmjs.com/cli/outdated) or unnecessary dependencies into the project. 43 | * Changes which may have wider ramifications than the author anticipated. Double check they are aware which can of worms they have just opened :) 44 | 45 | * **Performance** 46 | 47 | * [Premature](http://wiki.c2.com/?PrematureOptimization) and/or micro optimisations. 48 | * Non-performant code. Suggest testing with [Lighthouse](https://developers.google.com/web/tools/lighthouse/), [SpeedCurve](https://speedcurve.com), [WebPageTest](https://www.webpagetest.org/) and/or other tools. 49 | 50 | * **Scope** 51 | 52 | * [PRs which are non-atomic](https://medium.com/@fagnerbrack/one-pull-request-one-concern-e84a27dfe9f1) and should be split into separate PRs, e.g. a new UI feature combined with an unrelated configuration change. 53 | * Code which could be split up into reusable modules. 54 | 55 | * **Security** 56 | 57 | * Code that adds dependencies that contain known vulnerabilities. Suggest testing with tools like [npm audit](https://docs.npmjs.com/cli/v8/commands/npm-audit), [Snyk](https://snyk.io) (for open source repos) and/or [White Source](https://www.whitesourcesoftware.com/) (for private repos). 58 | 59 | * **Syntax** 60 | * Syntactic inconsistencies the [linter](https://github.com/springernature/frontend-playbook/blob/main/practices/house-style.md#linting) did not catch. 61 | -------------------------------------------------------------------------------- /accessibility/05-effective-colour-contrast.md: -------------------------------------------------------------------------------- 1 | # Effective colour contrast 2 | 3 | This page contains three basic guidelines for making effective color choices that work for nearly everyone. It is a partial copy of a brochure on effective colour contrast by the ["Lighthouse International" charity](http://www.lighthouseguild.org/). The original brochure no longer exists on the Lighthouse International website, but a [full reproduction is available](http://www.cs.mtu.edu/~nilufer/classes/cs3611/interesting-stuff/designing-with-colors-1/color_contrast.htm). 4 | 5 | * [How does impaired vision affect color perception?](#how-does-impaired-vision-affect-color-perception) 6 | * [The three rules](#the-three-rules) 7 | * [Exaggerate lightness differences between foreground and background colors, and avoid using colors of similar lightness adjacent to one another, even if they differ in saturation or hue.](#exaggerate-lightness-differences-between-foreground-and-background-colors-and-avoid-using-colors-of-similar-lightness-adjacent-to-one-another-even-if-they-differ-in-saturation-or-hue) 8 | * [Choose dark colors with hues from the bottom half of this hue circle against light colors from the top half of the circle.](#choose-dark-colors-with-hues-from-the-bottom-half-of-this-hue-circle-against-light-colors-from-the-top-half-of-the-circle) 9 | * [Avoid contrasting hues from adjacent parts of the hue circle, especially if the colors do not contrast sharply in lightness.](#avoid-contrasting-hues-from-adjacent-parts-of-the-hue-circle-especially-if-the-colors-do-not-contrast-sharply-in-lightness) 10 | 11 | ## How does impaired vision affect color perception? 12 | 13 | Partial sight, aging and congenital color deficits all produce changes in perception that reduce the visual effectiveness of certain color combinations. Two colors that contrast sharply to someone with normal vision may be far less distinguishable to someone with a visual disorder. It is important to appreciate that it is the contrast of colors one against another that makes them more or less discernible rather than the individual colors themselves. Here are three simple rules for making effective color choices: 14 | 15 | ## The three rules 16 | 17 | ### Exaggerate lightness differences between foreground and background colors, and avoid using colors of similar lightness adjacent to one another, even if they differ in saturation or hue. 18 | 19 | ![Foreground and background contrast](images/color_contrast_01.jpg) 20 | 21 | Dont assume that the lightness you perceive will be the same as the lightness perceived by people with color deficits. You can generally assume that they will see less contrast between colors than you will. If you lighten the light colors and darken the dark colors in your design, you will increase its visual accessibility. 22 | 23 | ![Light and dark colour wheel](images/color_contrast_02.gif) 24 | 25 | ### Choose dark colors with hues from the bottom half of this hue circle against light colors from the top half of the circle. 26 | 27 | Avoid contrasting light colors from the bottom half against dark colors from the top half. 28 | 29 | For most people with partial sight and/or congenital color deficiencies, the lightness values of colors in the bottom half of the hue circle tend to be reduced. 30 | 31 | ![Hue contrast colour wheel](images/color_contrast_03.gif) 32 | 33 | ![Effective and ineffective hue contrast](images/color_contrast_04.gif) 34 | 35 | ### Avoid contrasting hues from adjacent parts of the hue circle, especially if the colors do not contrast sharply in lightness. 36 | 37 | Color deficiencies associated with partial sight and congenital deficiencies make it difficult to discriminate between colors of similar hue. 38 | 39 | ![Ineffective adjacent hues](images/color_contrast_05.gif) 40 | -------------------------------------------------------------------------------- /css/bem-css.md: -------------------------------------------------------------------------------- 1 | # BEM CSS 2 | 3 | We use the **Block, Element, Modifier** methodology (commonly referred to as BEM) for CSS class naming. The main aim of the [BEM methodology](http://getbem.com/) is to speed up the development process and ease the teamwork of developers. 4 | 5 | It is worth noting that we use a naming scheme based on BEM, but adapted by [Nicolas Gallagher](http://nicolasgallagher.com/about-html-semantics-front-end-architecture/), and detailed in [this post](http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/) by Harry Roberts. 6 | 7 | We namespace our CSS as detailed in our [how we write CSS](how-we-write-css.md) guide. For the purposes of the examples here, we will use the `component` namespace. 8 | 9 | BEM naming follows this pattern: 10 | ```css 11 | /* Block component */ 12 | .c-block {} 13 | 14 | /* Element that depends upon the block */ 15 | .c-block__element {} 16 | 17 | /* Modifier that changes the style of the block */ 18 | .c-block--modifier {} 19 | ``` 20 | 21 | ## Naming style 22 | 23 | All class names should be _lowercase-hyphenated_ - all lowercase, words separated by a hyphen. 24 | 25 | We _don't_ do this: 26 | ```css 27 | .c-alertBox 28 | .c-AlertBox 29 | .c-Alert-Box 30 | ``` 31 | 32 | We do this: 33 | ```css 34 | .c-alert-box 35 | ``` 36 | 37 | ## Examples 38 | 39 | **Block**: Unique, meaningful names for a logical unit of style. Avoid excessive shorthand. 40 | 41 | We _don't_ do this: 42 | ```css 43 | .c-feature 44 | .c-content 45 | .c-btn 46 | ``` 47 | 48 | We do this: 49 | ```css 50 | .c-alert-box 51 | .c-button 52 | ``` 53 | 54 | **Element**: styles that only apply to children of a block. Class name is a concatenation of the block name, two underscores and the element name. Examples: 55 | - `.c-alert-box__close` 56 | - `.c-button__icon` 57 | 58 | **Modifier**: override or extend the base styles of a block or element with modifier styles. Class name is a concatenation of the block (or element) name, two hyphens and the modifier name. Examples: 59 | - `.c-alert-box--success` 60 | - `.c-button--expanded` 61 | 62 | ## BEM best practices 63 | 64 | Don’t extend the block element with a modifier, without the unmodified block element also being present. 65 | 66 | We _don't_ do this: 67 | ```html 68 |
69 | ``` 70 | 71 | We do this: 72 | ```html 73 |
74 | ``` 75 | 76 | Don't create elements inside elements. If you find yourself needing this, consider converting your element into a block. 77 | 78 | We _don't_ do this: 79 | ```css 80 | .c-alert-box__close__button 81 | ``` 82 | 83 | Choose your modifiers wisely. These two rules have very different meaning: 84 | ```css 85 | .c-block--modifier .c-block__element { color: red; } 86 | .c-block__element--modifier { color: red; } 87 | ``` 88 | 89 | Don't nest class names when using a preprocessor. Here are a few reasons why: 90 | 91 | 1. It prevents from being able to find the class names easily 92 | 2. It hinders developers understanding the context that they are working on 93 | 3. When reviewing a pull request, it requires extra effort to see the actual 94 | selector and to do a proper review 95 | 96 | We _do_ this: 97 | 98 | ```css 99 | .c-block { padding: 24px; } 100 | 101 | .c-block--modifier { padding: 12px; } 102 | 103 | .c-block__element { color: white; } 104 | 105 | .c-block__element--modifier { color: black } 106 | ``` 107 | 108 | We _don't_ do this: 109 | 110 | ```css 111 | .c-block { 112 | padding: 24px; 113 | 114 | &--modifier { 115 | padding: 12px; 116 | } 117 | 118 | &__element { 119 | color: white; 120 | 121 | &--modifier { 122 | color: black; 123 | } 124 | } 125 | } 126 | ``` 127 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Frontend Playbook 2 | 3 | If you're on this page because you'd like to contribute to the Playbook, that's fantastic! Thank you for getting involved ❤️ 4 | 5 | Contributing to the Playbook is for everyone. Whether you work at Springer Nature or not, the Playbook is for you - a guide to good working standards and practices that support healthy, happy teams. You don't need to be a developer to get involved. We cover many areas, from cultural and technical writing to specific technical practices. Please adhere to our [house style](writing/house-style.md) and [inclusive language](writing/inclusive-language.md) guidelines when you make your contributions. 6 | 7 | ## How do I contribute? 8 | 9 | ### Discussing 10 | 11 | You can get involved in discussions in issues and pull requests. Sometimes we need a discussion to [come to an agreement](https://github.com/springernature/frontend-playbook/issues/92) on a particular issue before a pull request is opened. Sometimes [a pull request](https://github.com/springernature/frontend-playbook/pull/87) will be discussed. Both types of discussion help bring us to a common understanding, and your input at this stage is really valuable. 12 | 13 | ### Opening and assigning issues 14 | 15 | [Our issues list](https://github.com/springernature/frontend-playbook/issues) is half to-do list, half discussion. Not every issue will produce a pull request, and some issues may produce multiple pull requests. 16 | 17 | Create an issue if you notice that there's something missing from the Playbook. If you'd like to discuss the issue with others, use a label like "collaboration", "help wanted", or "question". If you intend to open a pull request to resolve the issue you've created, consider assigning the issue to yourself. 18 | 19 | A good issue is [sufficiently detailed](https://github.com/springernature/frontend-playbook/issues/45) for anybody to be able to understand what it's about. If there are existing issues already created that are related to yours, then please link to them to provide further context. 20 | 21 | ### Opening pull requests 22 | 23 | Please create a new short-lived feature branch for your changes, then create a pull request. Once your changes have been approved, you can merge them to the default branch. [Read more about what we're looking for when we review](practices/code-review.md). 24 | 25 | Include a summary of your pull request when you open it. We prefer to use commit messages to explain _what_ a change will do, and pull request summaries to explain _why_ the change was made. [Read further guidelines on commit messages](git/git.md) - many of these guidelines can also apply to pull request summaries! 26 | 27 | If you work at Springer Nature, please remember to keep discussion inside the issues and pull requests, avoiding Slack, hallway conversations etc. Remember that this repo is public, and the discussions we have can be of benefit to people apart from us. 28 | 29 | ### Merging pull requests 30 | With short-lived feature branches, a key rule is that [branches should be quickly merged and deleted](https://trunkbaseddevelopment.com/short-lived-feature-branches/). 31 | 32 | With a playbook PR, __this rule does not apply__. The aim is to get many people reading or contributing-to the pull request (and the likelihood of a conflict upon merge is very very low). 33 | 34 | Because of this, it is fine (in many cases highly _desired_) to propose something, then wait a week or so before reminding people that there is a PR open. Let people know you'll be merging in a week or so, assuming there's no continuing discussion. That way, more people will have a chance to contribute. 35 | 36 | ### Publicising your changes 37 | 38 | A bot notifies the #frontend Slack room when work is merged, because changes to the playbook are relevant to all Frontend developers at Springer Nature. 39 | 40 | We hope the wider development community will be interested in the work we have committed here. We welcome feedback and involvement from all - so feel free to link to your latest contribution on your social media platform of choice. 41 | -------------------------------------------------------------------------------- /practices/open-source-support.md: -------------------------------------------------------------------------------- 1 | # Open source support 2 | 3 | - [Versioning](#versioning) 4 | - [Release process](#release-process) 5 | - [CI tests](#ci-tests) 6 | - [Node versions](#node-versions) 7 | - [Security](#security) 8 | - [Support for old versions](#support-for-old-versions) 9 | 10 | 11 | ## Versioning 12 | 13 | Our open source projects are versioned with [SemVer](../git/semver.md). You should read through the [SemVer documentation](http://semver.org) if you're going to release new versions. 14 | 15 | 16 | ## Release process 17 | 18 | To publish a *new* version of one of our open source projects: 19 | 20 | * Switch to the default branch. Version commits are the only ones that shouldn't be committed to a feature branch. 21 | * Consider what type of release this is: `major`, `minor` or `patch` according to SemVer. If you're unsure which, check with the rest of the team or re-read the [SemVer docs](https://semver.org/). Also verify if there are any references to the old version in the `README.md` or any other files, and update them too. 22 | * Add an entry to the `HISTORY.md` file outlining the changes in the new version. Take your time, this log should be useful to developers who use this project - it should help them make decisions about whether they can or should upgrade. If there are additional commits on the default branch since the last version, be sure to include a description of what they do in your history update - talk to the developers who committed them, if necessary. 23 | * Run `npm version` depending on the SemVer type of release - e.g. `npm version minor` for a minor release. This will: 24 | * increment the version in your `package.json`, based on the type of release. 25 | * commit this version bump. 26 | * create a tag for the current release in your local repository. 27 | * You can also use the above command to conveniently publish a release candidate, e.g. `npm version 4.0.0-rc1`. Once you are finished with the release candidates and ready for a major release, use `npm version major`. 28 | * It's possible to do those three steps manually - and you will need to do that for a first OSS release - but using the convenience method of `npm version` reduces human error and increases consistency. 29 | * Before publishing to NPM for real, run `npm publish --dry-run` ([docs](https://docs.npmjs.com/cli/v9/commands/npm-publish#dry-run)) to see what will happen. 30 | * Push both the commit and the new tags to origin: `git push && git push --tags`. 31 | * Depending on how the project is set up, the build system may automatically publish your new version based on the tag. Otherwise you may have to run `npm publish` to publish the package in [npm](https://www.npmjs.com/). If you don't have permission yet, request it from one of the existing collaborators. 32 | 33 | 34 | ## CI tests 35 | 36 | We aim for every project to run its unit tests automatically every time a change is committed to its repo. 37 | 38 | At the moment we recommend [GitHub Actions](https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-nodejs) for our projects but other options are available. 39 | 40 | The default branch should be protected so other branches can't be merged unless the tests have passed on those branches. 41 | 42 | 43 | ## Node versions 44 | 45 | On [node-based projects](https://nodejs.org) we aim to support every version that the Node foundation offers [Long-term support (LTS)](https://github.com/nodejs/Release) for. That means that we won't offer support for odd versions like Node 19 and 21. 46 | 47 | Dropping support for a node version from the test matrix must be only done as part of a major release, as we consider it a breaking change. 48 | 49 | 50 | ## Security 51 | 52 | Whenever possible, we'll use automated tools and alerts in order to check for vulnerabilities in our projects or their dependencies. 53 | 54 | 55 | ## Support for old versions 56 | 57 | We aim to support old versions for 6 months after the next major version has been released. Support for old versions will be usually limited to security issues or important bugfixes. 58 | 59 | -------------------------------------------------------------------------------- /practices/structured-data.md: -------------------------------------------------------------------------------- 1 | # Structured data 2 | 3 | In the context of the web, structured data refers to information used to describe and classify the content of a webpage. For example; on a scientific article page, who the author is, what the article title is, and so on. Structured data contributes towards the vision of the [Semantic Web](https://en.wikipedia.org/wiki/Semantic_Web#Semantic_Web_solutions) and provides SEO benefit. 4 | 5 | There are 4 widely accepted ways to implement structured data: 6 | - [JSON-LD](https://en.wikipedia.org/wiki/JSON-LD) (a W3C Recommendation) 7 | - [RDFa](https://en.wikipedia.org/wiki/RDFa) (a W3C Recommendation) 8 | - [Microdata](https://en.wikipedia.org/wiki/Microdata_(HTML)) 9 | - [Microformat](https://en.wikipedia.org/wiki/Microformat) 10 | 11 | 12 | ## How we implement structured data 13 | 14 | We primarily use JSON-LD. Information is defined in JSON using the [RDF](https://en.wikipedia.org/wiki/Resource_Description_Framework) format. You can add these inside ` 58 | ``` 59 | 60 | ## Why JSON-LD? 61 | Using JSON-LD instead of marking up HTML with one of the other techniques has benefits: 62 | 63 | - Separation of structured data and HTML. Provides information about the page without binding it to specific HTML elements. This improves the maintainability of both HTML and structured data. 64 | - Generally speaking, it will be easier to generate from the backend. This is especially true for apps that already deal with JSON data as part of their implementation. 65 | - Easier for client apps to consume as those apps no longer need to trawl through HTML to extract. 66 | - JSON-LD is an official [W3C Recommendation](https://en.wikipedia.org/wiki/World_Wide_Web_Consortium#W3C_recommendation_(REC)). 67 | - Google [recommends](https://developers.google.com/search/docs/guides/intro-structured-data) JSON-LD for structured data. 68 | 69 | ## Vocabulary 70 | A shared, standardised vocabulary ensures that structured data is interpreted consistently by people and machines. We use the vocabulary defined and maintained at [https://www.schema.org](https://www.schema.org). Since its creation in 2011 by Google, Bing, Yahoo! and Yandex this vocabulary has been widely adopted and is the most commonly implemented. 71 | 72 | Tip - after adding a new JSON-LD script to your website, be sure to validate your use of vocabulary by using [Google’s structured data test tool](https://search.google.com/structured-data/testing-tool). 73 | -------------------------------------------------------------------------------- /accessibility/03-accessibility-in-emails.md: -------------------------------------------------------------------------------- 1 | # Accessibility in emails 2 | 3 | Accessibility in emails can be summarised with 3 key points: 4 | 5 | 1. Accessible emails allow you to reach a wider audience. 6 | 1. Writing and visual design are key components of an accessible email campaign, so ensure that UX and content folk are involved in all discussions. 7 | 1. Email templates can be made immediately more accessible with a few simple coding techniques. 8 | 9 | Creating accessible emails is not fundamentally different from creating accessible websites. 10 | 11 | Here are the few differing constraints and techniques that should be considered. 12 | 13 | ## Layout 14 | 15 | Rich visual emails typically use tables for layout. This is because email clients use old and conservative browser engines that do not cope well nor consistently with CSS-based layouts. 16 | 17 | - Using ARIA to set `role="presentation"` on layout tables will help prevent them being seen as data tables by screen readers, and allow screen reader users to read the email contents easily. 18 | 19 | ## Specify a language 20 | 21 | Emails, even if sent in English, can be read out loud by browsers and operating systems using other languages. 22 | 23 | - Setting the language of the email on the root element will allow assistive technology to use the appropriate language profile. 24 | 25 | ## Use logical source order 26 | 27 | Screenreaders will rely on the logical source order of the HTML when they read out content. 28 | 29 | - Use the logical source order for the language you are writing in. 30 | - For most western languages, English included, this is left to right and top to bottom. 31 | - This includes the table cells and rows used for email layout. 32 | 33 | ## Alternative text 34 | 35 | Marketing emails tend to make heavy use of images, so it is important to ensure alt text is used well. 36 | 37 | - Alt text should be used as it would be on a web site. 38 | - If the image conveys meaning, add an alt description. 39 | - If the image is purely presentational, add an empty alt attribute (`alt=""`) to allow the screenreader to skip it. 40 | - If the image is an image of text, the alt attribute must contain that same text. 41 | - Never leave an image without an alt attribute as the assistive tech will read out the filename instead. If you're sure the image doesn't need alt text, use an empty alt attribute (`alt=""`). 42 | - Do not use alt text to prompt the user to enable images in their email client. 43 | 44 | ## Fonts 45 | 46 | Before the age of webfonts, browser content was restricted to a short list of ~10 “web-safe” fonts, or text in images. HTML emails are largely still subject to this restriction. While many email clients will allow an embedded webfont, the biggest one – GMail – does not. Also a webfont is another embedded resource in the email so using a webfont forces every user (including those on mobile) to download the custom font just to read a short email. 47 | 48 | TL;DR: use Courier for monospace, Times or Georgia for serif, and Arial/Helvetica for sans-serif, and **always** specify the default fallback at the end of the font stack. 49 | 50 | ## Use semantic content 51 | 52 | Semantic HTML helps screenreaders to read out content, and allows the email to be visually interpreted even if CSS is not available. 53 | 54 | - Pre-HTML5 elements `

` and `

`, `

`, are likely to work in all clients. 55 | 56 | ## Avoid HTML5 elements 57 | 58 | Any HTML elements that appeared in the HTML5 specification may be stripped by more conservative email clients. 59 | 60 | - Avoid using HTML5 elements, such as `
`, `