Become an Accessibility BFF with your new friend Pa11y! (Jennifer Wadella)
Hacking the Angular compiler with your own syntax (Kwinten Pisman & Dominic Elm)
End to end testing a world of web, mobile & desktop apps (Mathieu Henri)
WebAuthn Rocks! Stop authenticating as if it were the 60s (Ruben Restrepo)
I may swear
I may be biased
✅ Landmark Roles
✅ Language Attribute
✅ Semantic Headings
✅ Links - :focus state and recognizable
✅ Image alt text
✅ Forms - labels, placeholders, and fieldsets
✅ Audio/video - provide transcripts/subtitles
✅ Color & Contrast
✅ Screen Reading/Keyboard Testing
{
"defaults": {
"standard": "WCAG2AAA"
},
"urls": [
"http://localhost:4200/",
"http://localhost:4200/posts",
{
"url": "http://localhost:4200/cast",
"actions": [
"click element #myButton",
"wait for element modal-container to be hidden"
]
}
]
}JavaScript
Style Calc
Layout
Paint
Composite
16 ms
16 ms
16 ms
10ms
10ms
10ms
10ms
10ms
16 ms
16 ms
10ms
40ms
// Unoptimized
for(let i = 0; i < 100; i++){
const element = document.createElement('div');
document.body.appendChild(element);
}
// Optimized
const fragment = document.createDocumentFragment();
for(let i = 0; i < 100; i++){
const element = document.createElement('div');
fragment.appendChild(element);
}
document.body.appendChild(fragment);Multiple DOM accesses
Avoid layout thrashing
function resizeAllParagraphsToMatchBlockWidth() {
// Puts the browser into a read-write-read-write cycle.
for (var i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = box.offsetWidth + 'px';
}
}
var width = box.offsetWidth;
function resizeAllParagraphsToMatchBlockWidth() {
for (var i = 0; i < paragraphs.length; i++) {
// Now write.
paragraphs[i].style.width = width + 'px';
}
}Avoid Long Running Handlers
Event Throttling
Javascript animations
function animateBox() {
offset = offset + step
box.style.marginLeft = offset + "px";
requestAnimationFrame(animateBox);
}Css animations
Style
Layout
Paint
Composite
Layout
Paint
Composite
Does it change the geometry of the element?
(ex: width, margin, border)
Is it a visual property?
(ex: color, background-color, visibility)
Does it promote the element to a new layer?
(ex: transform, opacity)
Paint
Composite
Composite
const template = document.createElement('template')
template.innerHTML = `
<style>
:host {}
button {}
::slotted(.title) {}
</style>
<slot></slot>
<div class="count"></div>
<button class="dec">👎</button>
`
export class Counter extends HTMLElement {
constructor() {
super()
this._root = this.attachShadow({ mode: 'open' })
this._root.appendChild(template.content.cloneNode(true))
this._viewRef = ({
decBtn: this._root.querySelector('.dec'),
countView: this._root.querySelector('.count'),
})
this._viewRef.decBtn.addEventListener('click', this.handleDec)
}
connectedCallback() {
this.render()
}
disconnectedCallback() {
this._viewRef.decBtn.removeEventListener('click', this.handleDec)
}
render() {
this._viewRef.countView.textContent = String(this.count)
}
}window.customElements.define('counter-webcomponent', Counter);navigator.credentials
.create({
publicKey: {
// random, cryptographically secure, at least 16 bytes
challenge: base64url.decode("<%= challenge %>"),
// relying party
rp: {
name: "Awesome Corp" // sample relying party
},
user: {
id: base64url.decode("<%= id %>"),
name: "<%= name %>",
displayName: "<%= displayName %>"
},
authenticatorSelection: { userVerification: "preferred" },
attestation: "direct",
pubKeyCredParams: [
{
type: "public-key",
alg: -7 // "ES256" IANA COSE Algorithms registry
}
]
}
})
.then(res => {
var json = publicKeyCredentialToJSON(res);
// Send data to relying party's servers
post("/webauthn/register", {
state: "<%= state %>",
provider: "<%= provider %>",
res: JSON.stringify(json)
});
})
.catch(console.error);Where in the spectrum are you today?
Where will you be in 10 years?