SlideShare une entreprise Scribd logo
1  sur  157
FROM: Marc Andreessen (marca@eit.com)
TO: www-talk@w3.org
Thu, 17 Feb 1994 13:11:31 --100
RE: Indented <MENU>s
************************
***********
In fact, it has been a constant
source of delight for me over the
past year to get to continually tell
hordes (literally) of people who
want to -- strap yourselves in, here
it comes -- control what their
documents look like in ways that
would be trivial in TeX, Microsoft
Word, and every other common text
processing environment: "Sorry,
you're screwed."
<center>
paintlayoutstyledomparsingnetwork compose
paintlayoutstyledomparsingnetwork compose
Why on earth are
you looking this
closely at my files?
You win a prize :]
Seriously, just tell
me you noticed
this ridiculiously
small text and I
paintlayoutstyledomparsingnetwork compose
var sum=1+2
keyword identifier assignment int addition int
“hey, that’s a keyword!”“and that’s an identifier!”“thats an integer!”“another integer!”“oh cool! an addition operator”“looks like an assignment operator”
paintlayoutstyledomparsingnetwork compose
#document
body
header div
p p
<!DOCTYPE html>
<body>
<header>hello</header>
<div>
<p>world</p>
<p>:]</p>
</div>
</body>
<!DOCTYPE html>
<body>
<header>hello</header>
<div>
<p>world</p>
<p>:]</p>
</div>
</body>
paintlayoutstyledomparsingnetwork compose
#document
body
header div
p p
#document
body
header div
* {
background: red
}
div p {
background: blue
}
p:last-of-type {
background: orange
}
* {
background: red
}
div p
p:last-of-type
div p {
background: blue
}
* {
background: red
}
p:last-of-type {
background: orange
}
div p {
background: blue
}
#document
body
header div
p pp p
paintlayoutstyledomparsingnetwork compose
body
div
p
body{
width: 250px
}
div {
width: 10em;
}
p {
width: 50%
}
body
header div
p p
bodybody{
width: 250px
}
body{
width: 250px
}
div {
width: 10em;
}
p {
width: 50%
}
header div
p p
div
p
body{
width: 250px
}
div {
width: 10em;
}
p {
width: 50%
}
div
p p
divdiv {
width: 10em;
}
div {
width: 160px;
}
body{
width: 250px
}
p {
width: 50%
}
p p
pp {
width: 50%
}
p {
width: 80px
}
body{
width: 250px
}
p {
width: 50px
}
p
pp {
width: 80px
}
paintlayoutstyledomparsingnetwork compose
0101
011111011
0101101111010
1110101010010
101001010010111010
10100101001010110101001101010
paintlayoutstyledomparsingnetwork compose
p:last-of-type {
transform: translate3d(0,0,0)
}
paintlayoutstyledomparsingnetwork compose
paintlayoutstyledomparsingnetwork compose
paintlayoutstyledomparsingnetwork compose
document.documentElement.classList.add('foo')document.body.style.paddingLeft = '2px'
paintlayoutstyledomparsingnetwork compose
cssgrid
cssgrid
years
paintlayoutstyledomparsingnetwork compose
CSS Properties and Values API
CSSOM
PaintWorklet
LayoutWorklet
AnimationWorklet
CSS Parser
Font Metrics
Properties and Values API
CSS Custom Properties(aka CSS variables)
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
You Can’t Animate Strings
Properties and Values API
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
CSS.registerProperty({
name: "--distance",
syntax: "<length>",
initialValue: ’0'
})
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
CSS.registerProperty({
name: "--distance",
syntax: "<length>",
initialValue: ’0'
})
required: any string
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
CSS.registerProperty({
name: "--distance",
syntax: "<length>",
initialValue: ’0'
})
optional: <length>
<number>
<percentage>
<color>
<image>
<url>
<integer>
<angle>
<time>
<resolution>
<ident>
*
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
CSS.registerProperty({
name: "--distance",
syntax: "<length>",
initialValue: ’0'
})
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
CSS.registerProperty({
name: "--distance",
syntax: "<length>",
initialValue: ’0'
})
:root {
--distance: 400px;
}
div {
width: var(--distance);
height: var(--distance);
background: #F9391F;
transition: --distance: 1s;
}
div:hover {
--distance: 150px;
}
CSS.registerProperty({
name: "--distance",
syntax: "<length>",
initialValue: ’0'
})
CSSOMCSS Object ModelCSS Typed Object Model
^
^
Here is a some
dummy text
Here is a a much
much longer version
of some dummy text
that will ultimately
cause the textbox to
overflow the
container that we
are within and as a
window.getComputedStyle('#elem').width == '200px';window.getComputedStyle('#elem').width == ’187px';
function getInnerWidth (elem) {
var style = window.getComputedStyle(elem);
var width = elem.offsetWidth;
var right = parseFloat(style.paddingRight);
var left = parseFloat(style.paddingLeft);
var bRight = parseFloat(style.borderRightWidth);
var bLeft = parseFloat(style.borderLeftWidth);
return width - right - left - bRight - bLeft;
};
function getInnerWidth (elem) {
var style = window.getComputedStyle(elem);
var width = elem.offsetWidth;
var right = parseFloat(style.paddingRight);
var left = parseFloat(style.paddingLeft);
var bRight = parseFloat(style.borderRightWidth);
var bLeft = parseFloat(style.borderLeftWidth);
return width - right - left - bRight - bLeft;
};
function getInnerWidth (elem) {
var style = window.getComputedStyle(elem);
var width = elem.offsetWidth;
var right = parseFloat(style.paddingRight);
var left = parseFloat(style.paddingLeft);
var bRight = parseFloat(style.borderRightWidth);
var bLeft = parseFloat(style.borderLeftWidth);
return width - right - left - bRight - bLeft;
};
function getInnerWidth (elem) {
var style = window.getComputedStyle(elem);
var width = elem.offsetWidth;
var right = parseFloat(style.paddingRight);
var left = parseFloat(style.paddingLeft);
var bRight = parseFloat(style.borderRightWidth);
var bLeft = parseFloat(style.borderLeftWidth);
return width - right - left - bRight - bLeft;
};
function getInnerWidth (elem) {
var style = window.getComputedStyle(elem);
var width = elem.offsetWidth;
var right = parseFloat(style.paddingRight);
var left = parseFloat(style.paddingLeft);
var bRight = parseFloat(style.borderRightWidth);
var bLeft = parseFloat(style.borderLeftWidth);
return width - right - left - bRight - bLeft;
};
function getInnerWidth (elem) {
var style = window.getComputedStyleMap(elem);
var width = elem.offsetWidth;
var right = style.paddingRight.value;
var left = style.paddingLeft.value;
var bRight = style.borderRightWidth.value;
var bLeft = style.borderLeftWidth.value;
return width - right - left - bRight - bLeft;
};
function getInnerWidth (elem) {
var style = window.getComputedStyleMap(elem);
var width = elem.offsetWidth;
var right = style.paddingRight.value;
var left = style.paddingLeft.value;
var bRight = style.borderRightWidth.value;
var bLeft = style.borderLeftWidth.value;
return width - right - left - bRight - bLeft;
};
function getInnerWidth (elem) {
var style = window.getComputedStyleMap(elem);
var width = elem.offsetWidth;
var right = style.paddingRight.value;
var left = style.paddingLeft.value;
var bRight = style.borderRightWidth.value;
var bLeft = style.borderLeftWidth.value;
return width - right - left - bRight - bLeft;
};
Before:
After:
DOM API
DOM API
➡ String ➡ Parse to number ➡ Calculations
➡ Calculations
getComputedStyleMap(elem)
elem.styleMap
getComputedStyleMap(elem) // to query any current value
elem.styleMap
getComputedStyleMap(elem) // to query any current value
elem.styleMap // for styles that have been
// set via CSS explicitly
style.get('width').unit == ’em'style.get('width').unit == ’vmax'
var style = document.querySelector('#elem').styleMap
style.get('width').value == '200'
style.get('width').unit == 'px'
var style = document.querySelector('#elem').styleMap
style.set('width', new CSSUnitValue(50, 'em'))
var style = document.querySelector('#elem').styleMap
style.set('width', new CSSUnitValue(50, 'em'))
var style = document.querySelector('#elem').styleMap
var x = style.get(’background-position').x
x.value == 50
x.unit == ’percent'
// CSSUnitValue(50, "percent")
var y = style.get(’background-position').y
x.px == -10
x.percent == 100
x.unit == undefined
// CSSCalcValue({percent: 100, px: -10})
#elem {
background-position: center bottom 10px;
}
#elem {
background-position: center bottom 10px;
}
#elem {
background-position: center bottom 10px;
}
it’s about efficiency,
not ease of use
CSSUnparsedValue
CSSKeywordValue
CSSUnitValue
CSSCalcValue
CSSTransformValue
CSSPositionValue
CSSImageValue
CSSFontFaceValue
Worklets
Worklets
WebWorkers
commit 90b52e847359ae902d3f7ce7bc511cadfbc29ea8
Author: Alexey Proskuryakov <ap@webkit.org>
Date: Thu Nov 6 2008 07:04:47 +0000
Implement Worker global object
self.onmessage = (e) {
let result =
doSomething(e.data)
postMessage(result)
}
var myWorker = new Worker('worker.js');
myWorker.postMessage(’testing 123');
myWorker.onmessage = (e) => {
doSomethingWithResult(e.data);
}
WebWorkers
WebWorkers
individual threads
event based
Worklets
API based
thread agnostic
paintlayoutstyledomparsingnetwork compose
paintlayoutstyledomparsingnetwork compose
CSS Layout API
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
<!doctype html>
<div id="myElement">
<div id="child1"></div>
<div id="child2"></div>
</div>
<style>
#myElement {
width: 500px;
height: 500px;
display: layout('masonry')
}
</style>
<script>
window.layoutWorklet.addModule('masonry.js')
</script>
// masonry.js
registerLayout('masonry', class {
*layout(space, children, styleMap) {
var inlineSize = resolveInlineSize(space, styleMap)
var bordersAndPadding = resolveBordersAndPadding(varraintSpace,
styleMap)
var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap)
var availableInlineSize = inlineSize -
bordersAndPadding.inlineStart -
bordersAndPadding.inlineEnd -
scrollbarSize.inline;
var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) -
bordersAndPadding.blockStart -
bordersAndPadding.blockEnd -
scrollbarSize.block;
...
// masonry.js
registerLayout('masonry', class {
*layout(space, children, styleMap) {
var inlineSize = resolveInlineSize(space, styleMap)
var bordersAndPadding = resolveBordersAndPadding(varraintSpace,
styleMap)
var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap)
var availableInlineSize = inlineSize -
bordersAndPadding.inlineStart -
bordersAndPadding.inlineEnd -
scrollbarSize.inline;
var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) -
bordersAndPadding.blockStart -
bordersAndPadding.blockEnd -
scrollbarSize.block;
...
// masonry.js
registerLayout('masonry', class {
*layout(space, children, styleMap) {
var inlineSize = resolveInlineSize(space, styleMap)
var bordersAndPadding = resolveBordersAndPadding(varraintSpace,
styleMap)
var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap)
var availableInlineSize = inlineSize -
bordersAndPadding.inlineStart -
bordersAndPadding.inlineEnd -
scrollbarSize.inline;
var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) -
bordersAndPadding.blockStart -
bordersAndPadding.blockEnd -
scrollbarSize.block;
...
// masonry.js
registerLayout('masonry', class {
*layout(space, children, styleMap) {
var inlineSize = resolveInlineSize(space, styleMap)
var bordersAndPadding = resolveBordersAndPadding(varraintSpace,
styleMap)
var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap)
var availableInlineSize = inlineSize -
bordersAndPadding.inlineStart -
bordersAndPadding.inlineEnd -
scrollbarSize.inline;
var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) -
bordersAndPadding.blockStart -
bordersAndPadding.blockEnd -
scrollbarSize.block;
...
// masonry.js
registerLayout('masonry', class {
*layout(space, children, styleMap) {
var inlineSize = resolveInlineSize(space, styleMap)
var bordersAndPadding = resolveBordersAndPadding(varraintSpace,
styleMap)
var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap)
var availableInlineSize = inlineSize -
bordersAndPadding.inlineStart -
bordersAndPadding.inlineEnd -
scrollbarSize.inline;
var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) -
bordersAndPadding.blockStart -
bordersAndPadding.blockEnd -
scrollbarSize.block;
...
yuck
it’s about efficiency,
not ease of use
bit.ly/css-layout-api
// masonry.js
registerLayout('masonry', class {
*layout(space, children, styleMap) {
var inlineSize = resolveInlineSize(space, styleMap)
var bordersAndPadding = resolveBordersAndPadding(varraintSpace,
styleMap)
var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap)
var availableInlineSize = inlineSize -
bordersAndPadding.inlineStart -
bordersAndPadding.inlineEnd -
scrollbarSize.inline;
var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) -
bordersAndPadding.blockStart -
bordersAndPadding.blockEnd -
scrollbarSize.block;
...
// masonry.js
registerLayout('masonry', class {
*layout(space, children, styleMap) {
var inlineSize = resolveInlineSize(space, styleMap)
var bordersAndPadding = resolveBordersAndPadding(varraintSpace,
styleMap)
var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap)
var availableInlineSize = inlineSize -
bordersAndPadding.inlineStart -
bordersAndPadding.inlineEnd -
scrollbarSize.inline;
var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) -
bordersAndPadding.blockStart -
bordersAndPadding.blockEnd -
scrollbarSize.block;
...
paintWorklet
CSS Paint API
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
// qr.js
// slightly modified version of
// https://github.com/yyx990803/QR.js
import QR from 'QR'
registerPaint('qr', class {
static get inputProperties() { return [ '--qr-url' ]; }
paint(ctx, geom, properties) {
let url = properties.get('--qr-url').value
const minSize = Math.min(geom.width, geom.height);
if (url) {
QR.draw(url, ctx, minSize, 2)
}
}
});
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
const txt = document.querySelector('textarea')
txt.addEventListener('input', (e) => {
txt.style.setProperty('--qr-url', txt.value)
});
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
const txt = document.querySelector('textarea')
txt.addEventListener('input', (e) => {
txt.style.setProperty('--qr-url', txt.value)
});
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
const txt = document.querySelector('textarea')
txt.addEventListener('input', (e) => {
txt.style.setProperty('--qr-url', txt.value)
});
paintWorklet.addModule('qr.js')
</script>
<!doctype html>
<textarea id="myElement"></textarea>
<style>
#myElement {
background-color: #5d1e6f;
background-image: paint(qr);
--qr-url: https://patrickkettner.com;
width: 500px;
height: 500px;
}
</style>
<script>
const txt = document.querySelector('textarea')
txt.addEventListener('input', (e) => {
txt.style.setProperty('--qr-url', txt.value)
});
paintWorklet.addModule('qr.js')
</script>
it’s about efficiency,
not ease of use
start playing
with nightlies
give feedback!
https://aka.ms/EdgeUserVoice
thanks!
patrickkettner
patrickkettner
patrickkettner
patrickkettner
patrickkettner@microsoft.com

Contenu connexe

Tendances

Groovy every day
Groovy every dayGroovy every day
Groovy every dayPaul Woods
 
McrFRED 39 | CSS Processors
McrFRED 39 | CSS ProcessorsMcrFRED 39 | CSS Processors
McrFRED 39 | CSS ProcessorsTristan Ashley
 
Ruby - Uma Introdução
Ruby - Uma IntroduçãoRuby - Uma Introdução
Ruby - Uma IntroduçãoÍgor Bonadio
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a bossgsterndale
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaLin Yo-An
 
Introducción rápida a SQL
Introducción rápida a SQLIntroducción rápida a SQL
Introducción rápida a SQLCarlos Hernando
 
Mkscript sh
Mkscript shMkscript sh
Mkscript shBen Pope
 
Functional Pe(a)rls - the Purely Functional Datastructures edition
Functional Pe(a)rls - the Purely Functional Datastructures editionFunctional Pe(a)rls - the Purely Functional Datastructures edition
Functional Pe(a)rls - the Purely Functional Datastructures editionosfameron
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.VimLin Yo-An
 
Beautiful PHP CLI Scripts
Beautiful PHP CLI ScriptsBeautiful PHP CLI Scripts
Beautiful PHP CLI ScriptsJesse Donat
 
Accessible Web Components_Techshare India 2014
Accessible Web Components_Techshare India 2014Accessible Web Components_Techshare India 2014
Accessible Web Components_Techshare India 2014BarrierBreak
 
Scala in a Java 8 World
Scala in a Java 8 WorldScala in a Java 8 World
Scala in a Java 8 WorldDaniel Blyth
 
PHP Strings and Patterns
PHP Strings and PatternsPHP Strings and Patterns
PHP Strings and PatternsHenry Osborne
 
Simple flat ui css accordion
Simple flat ui css accordionSimple flat ui css accordion
Simple flat ui css accordionSamsury Blog
 

Tendances (20)

Groovy every day
Groovy every dayGroovy every day
Groovy every day
 
McrFRED 39 | CSS Processors
McrFRED 39 | CSS ProcessorsMcrFRED 39 | CSS Processors
McrFRED 39 | CSS Processors
 
Ruby - Uma Introdução
Ruby - Uma IntroduçãoRuby - Uma Introdução
Ruby - Uma Introdução
 
Arrays in php
Arrays in phpArrays in php
Arrays in php
 
Refactor like a boss
Refactor like a bossRefactor like a boss
Refactor like a boss
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim Perlchina
 
Introducción rápida a SQL
Introducción rápida a SQLIntroducción rápida a SQL
Introducción rápida a SQL
 
Mkscript sh
Mkscript shMkscript sh
Mkscript sh
 
Functional Pe(a)rls - the Purely Functional Datastructures edition
Functional Pe(a)rls - the Purely Functional Datastructures editionFunctional Pe(a)rls - the Purely Functional Datastructures edition
Functional Pe(a)rls - the Purely Functional Datastructures edition
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.Vim
 
Beautiful PHP CLI Scripts
Beautiful PHP CLI ScriptsBeautiful PHP CLI Scripts
Beautiful PHP CLI Scripts
 
Barcelona.pm Curs1211 sess01
Barcelona.pm Curs1211 sess01Barcelona.pm Curs1211 sess01
Barcelona.pm Curs1211 sess01
 
Having Fun Programming!
Having Fun Programming!Having Fun Programming!
Having Fun Programming!
 
Accessible Web Components_Techshare India 2014
Accessible Web Components_Techshare India 2014Accessible Web Components_Techshare India 2014
Accessible Web Components_Techshare India 2014
 
Scala in a Java 8 World
Scala in a Java 8 WorldScala in a Java 8 World
Scala in a Java 8 World
 
Learning How To Use Jquery #5
Learning How To Use Jquery #5Learning How To Use Jquery #5
Learning How To Use Jquery #5
 
PHP Strings and Patterns
PHP Strings and PatternsPHP Strings and Patterns
PHP Strings and Patterns
 
Oo Perl
Oo PerlOo Perl
Oo Perl
 
Simple flat ui css accordion
Simple flat ui css accordionSimple flat ui css accordion
Simple flat ui css accordion
 
Notes for gm
Notes for gmNotes for gm
Notes for gm
 

Similaire à Patrick Kettner - Creating magic with houdini

HTML5 and CSS3 Refresher
HTML5 and CSS3 RefresherHTML5 and CSS3 Refresher
HTML5 and CSS3 RefresherIvano Malavolta
 
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)Adam Darowski
 
Prototyping w/HTML5 and CSS3
Prototyping w/HTML5 and CSS3Prototyping w/HTML5 and CSS3
Prototyping w/HTML5 and CSS3Todd Zaki Warfel
 
Mobile-first OOCSS, Sass & Compass at BBC Responsive News
Mobile-first OOCSS, Sass & Compass at BBC Responsive NewsMobile-first OOCSS, Sass & Compass at BBC Responsive News
Mobile-first OOCSS, Sass & Compass at BBC Responsive NewsKaelig Deloumeau-Prigent
 
Compass, Sass, and the Enlightened CSS Developer
Compass, Sass, and the Enlightened CSS DeveloperCompass, Sass, and the Enlightened CSS Developer
Compass, Sass, and the Enlightened CSS DeveloperWynn Netherland
 
My discussion Student A A8 - Cross-Site Request Forgery (CSR.docx
My discussion Student A A8 - Cross-Site Request Forgery (CSR.docxMy discussion Student A A8 - Cross-Site Request Forgery (CSR.docx
My discussion Student A A8 - Cross-Site Request Forgery (CSR.docxgilpinleeanna
 
Cheap frontend tricks
Cheap frontend tricksCheap frontend tricks
Cheap frontend tricksambiescent
 
Wrangling the CSS Beast with Sass
Wrangling the CSS Beast  with SassWrangling the CSS Beast  with Sass
Wrangling the CSS Beast with SassRob Friesel
 
HTML5 and CSS3: Exploring Mobile Possibilities - London Ajax Mobile Event
HTML5 and CSS3: Exploring Mobile Possibilities - London Ajax Mobile EventHTML5 and CSS3: Exploring Mobile Possibilities - London Ajax Mobile Event
HTML5 and CSS3: Exploring Mobile Possibilities - London Ajax Mobile EventRobert Nyman
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2ady36
 
Preprocessor presentation
Preprocessor presentationPreprocessor presentation
Preprocessor presentationMario Noble
 
CSS: A Slippery Slope to the Backend
CSS: A Slippery Slope to the BackendCSS: A Slippery Slope to the Backend
CSS: A Slippery Slope to the BackendFITC
 
HTML5 and CSS3 – exploring mobile possibilities - Frontend Conference Zürich
HTML5 and CSS3 – exploring mobile possibilities - Frontend Conference ZürichHTML5 and CSS3 – exploring mobile possibilities - Frontend Conference Zürich
HTML5 and CSS3 – exploring mobile possibilities - Frontend Conference ZürichRobert Nyman
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim Perlchinaguestcf9240
 
Simple Blue Blog Template XML 的副本
Simple Blue Blog Template XML 的副本Simple Blue Blog Template XML 的副本
Simple Blue Blog Template XML 的副本a5494535
 
You Can Do It! Start Using Perl to Handle Your Voyager Needs
You Can Do It! Start Using Perl to Handle Your Voyager NeedsYou Can Do It! Start Using Perl to Handle Your Voyager Needs
You Can Do It! Start Using Perl to Handle Your Voyager NeedsRoy Zimmer
 

Similaire à Patrick Kettner - Creating magic with houdini (20)

HTML5 and CSS3 Refresher
HTML5 and CSS3 RefresherHTML5 and CSS3 Refresher
HTML5 and CSS3 Refresher
 
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
Sassive Aggressive: Using Sass to Make Your Life Easier (Refresh Boston Version)
 
Prototyping w/HTML5 and CSS3
Prototyping w/HTML5 and CSS3Prototyping w/HTML5 and CSS3
Prototyping w/HTML5 and CSS3
 
Theme verdadeiro
Theme verdadeiroTheme verdadeiro
Theme verdadeiro
 
Mobile-first OOCSS, Sass & Compass at BBC Responsive News
Mobile-first OOCSS, Sass & Compass at BBC Responsive NewsMobile-first OOCSS, Sass & Compass at BBC Responsive News
Mobile-first OOCSS, Sass & Compass at BBC Responsive News
 
Compass, Sass, and the Enlightened CSS Developer
Compass, Sass, and the Enlightened CSS DeveloperCompass, Sass, and the Enlightened CSS Developer
Compass, Sass, and the Enlightened CSS Developer
 
My discussion Student A A8 - Cross-Site Request Forgery (CSR.docx
My discussion Student A A8 - Cross-Site Request Forgery (CSR.docxMy discussion Student A A8 - Cross-Site Request Forgery (CSR.docx
My discussion Student A A8 - Cross-Site Request Forgery (CSR.docx
 
Cheap frontend tricks
Cheap frontend tricksCheap frontend tricks
Cheap frontend tricks
 
Wrangling the CSS Beast with Sass
Wrangling the CSS Beast  with SassWrangling the CSS Beast  with Sass
Wrangling the CSS Beast with Sass
 
HTML5 and CSS3: Exploring Mobile Possibilities - London Ajax Mobile Event
HTML5 and CSS3: Exploring Mobile Possibilities - London Ajax Mobile EventHTML5 and CSS3: Exploring Mobile Possibilities - London Ajax Mobile Event
HTML5 and CSS3: Exploring Mobile Possibilities - London Ajax Mobile Event
 
Tmx9
Tmx9Tmx9
Tmx9
 
FCIP SASS Talk
FCIP SASS TalkFCIP SASS Talk
FCIP SASS Talk
 
R57php 1231677414471772-2
R57php 1231677414471772-2R57php 1231677414471772-2
R57php 1231677414471772-2
 
Preprocessor presentation
Preprocessor presentationPreprocessor presentation
Preprocessor presentation
 
CSS: A Slippery Slope to the Backend
CSS: A Slippery Slope to the BackendCSS: A Slippery Slope to the Backend
CSS: A Slippery Slope to the Backend
 
HTML5 and CSS3 – exploring mobile possibilities - Frontend Conference Zürich
HTML5 and CSS3 – exploring mobile possibilities - Frontend Conference ZürichHTML5 and CSS3 – exploring mobile possibilities - Frontend Conference Zürich
HTML5 and CSS3 – exploring mobile possibilities - Frontend Conference Zürich
 
Perl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim PerlchinaPerl.Hacks.On.Vim Perlchina
Perl.Hacks.On.Vim Perlchina
 
Simple Blue Blog Template XML 的副本
Simple Blue Blog Template XML 的副本Simple Blue Blog Template XML 的副本
Simple Blue Blog Template XML 的副本
 
Vim Hacks
Vim HacksVim Hacks
Vim Hacks
 
You Can Do It! Start Using Perl to Handle Your Voyager Needs
You Can Do It! Start Using Perl to Handle Your Voyager NeedsYou Can Do It! Start Using Perl to Handle Your Voyager Needs
You Can Do It! Start Using Perl to Handle Your Voyager Needs
 

Plus de OdessaJS Conf

'GraphQL Schema Design' by Borys Mohyla. OdessaJS'2021
'GraphQL Schema Design' by Borys Mohyla. OdessaJS'2021'GraphQL Schema Design' by Borys Mohyla. OdessaJS'2021
'GraphQL Schema Design' by Borys Mohyla. OdessaJS'2021OdessaJS Conf
 
'How i came up with my talk' by Yurii Artiukh. OdessaJS'2021
'How i came up with my talk' by Yurii Artiukh. OdessaJS'2021'How i came up with my talk' by Yurii Artiukh. OdessaJS'2021
'How i came up with my talk' by Yurii Artiukh. OdessaJS'2021OdessaJS Conf
 
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021OdessaJS Conf
 
Олексій Павленко. CONTRACT PROTECTION ON THE FRONTEND SIDE: HOW TO ORGANIZE R...
Олексій Павленко. CONTRACT PROTECTION ON THE FRONTEND SIDE: HOW TO ORGANIZE R...Олексій Павленко. CONTRACT PROTECTION ON THE FRONTEND SIDE: HOW TO ORGANIZE R...
Олексій Павленко. CONTRACT PROTECTION ON THE FRONTEND SIDE: HOW TO ORGANIZE R...OdessaJS Conf
 
Андрій Троян. Розробка мікросервісів з NestJS. OdessaJS'2021
Андрій Троян. Розробка мікросервісів з NestJS. OdessaJS'2021Андрій Троян. Розробка мікросервісів з NestJS. OdessaJS'2021
Андрій Троян. Розробка мікросервісів з NestJS. OdessaJS'2021OdessaJS Conf
 
Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...
Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...
Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...OdessaJS Conf
 
Максим Климишин "Що такого особливого у пропозиції вартості шаблону Micro Fro...
Максим Климишин "Що такого особливого у пропозиції вартості шаблону Micro Fro...Максим Климишин "Що такого особливого у пропозиції вартості шаблону Micro Fro...
Максим Климишин "Що такого особливого у пропозиції вартості шаблону Micro Fro...OdessaJS Conf
 
Павло Галушко. GOOD CODE MYTHS. OdessaJS'2021
Павло Галушко. GOOD CODE MYTHS. OdessaJS'2021Павло Галушко. GOOD CODE MYTHS. OdessaJS'2021
Павло Галушко. GOOD CODE MYTHS. OdessaJS'2021OdessaJS Conf
 
"NODEJS & GRAPHQL COOKBOOK. LET’S TALK ABOUT MICRO-SERVICES" by Антон Чередні...
"NODEJS & GRAPHQL COOKBOOK. LET’S TALK ABOUT MICRO-SERVICES" by Антон Чередні..."NODEJS & GRAPHQL COOKBOOK. LET’S TALK ABOUT MICRO-SERVICES" by Антон Чередні...
"NODEJS & GRAPHQL COOKBOOK. LET’S TALK ABOUT MICRO-SERVICES" by Антон Чередні...OdessaJS Conf
 
'BUILDING ANGULAR APPS WITH NX' by Anastasia Necheporenko
'BUILDING ANGULAR APPS WITH NX' by Anastasia Necheporenko'BUILDING ANGULAR APPS WITH NX' by Anastasia Necheporenko
'BUILDING ANGULAR APPS WITH NX' by Anastasia NecheporenkoOdessaJS Conf
 
'IS THERE JAVASCRIPT ON SWAGGER PLUGINS?' by Dmytro Gusev
'IS THERE JAVASCRIPT ON SWAGGER PLUGINS?' by  Dmytro Gusev'IS THERE JAVASCRIPT ON SWAGGER PLUGINS?' by  Dmytro Gusev
'IS THERE JAVASCRIPT ON SWAGGER PLUGINS?' by Dmytro GusevOdessaJS Conf
 
'ETHEREUM SMART CONTRACTS ON JS' by Yaroslav Dvorovenko
'ETHEREUM SMART CONTRACTS ON JS' by Yaroslav Dvorovenko'ETHEREUM SMART CONTRACTS ON JS' by Yaroslav Dvorovenko
'ETHEREUM SMART CONTRACTS ON JS' by Yaroslav DvorovenkoOdessaJS Conf
 
'GOLANG USAGE IN DEVELOPMENT OF NODE.JS APPLICATIONS (NODE.JS: IN GO WE TRUST...
'GOLANG USAGE IN DEVELOPMENT OF NODE.JS APPLICATIONS (NODE.JS: IN GO WE TRUST...'GOLANG USAGE IN DEVELOPMENT OF NODE.JS APPLICATIONS (NODE.JS: IN GO WE TRUST...
'GOLANG USAGE IN DEVELOPMENT OF NODE.JS APPLICATIONS (NODE.JS: IN GO WE TRUST...OdessaJS Conf
 
'MICROFRONTENDS WITH REACT' by Liliia Karpenko
 'MICROFRONTENDS WITH REACT' by Liliia Karpenko 'MICROFRONTENDS WITH REACT' by Liliia Karpenko
'MICROFRONTENDS WITH REACT' by Liliia KarpenkoOdessaJS Conf
 
'Web performance metrics' BY ROMAN SAVITSKYI at OdessaJS'2020
'Web performance metrics' BY ROMAN SAVITSKYI at OdessaJS'2020'Web performance metrics' BY ROMAN SAVITSKYI at OdessaJS'2020
'Web performance metrics' BY ROMAN SAVITSKYI at OdessaJS'2020OdessaJS Conf
 
'STORY OF ANOTHER ANIMATION' by YURII ARTYUKH at OdessaJS'2020
'STORY OF ANOTHER ANIMATION' by  YURII ARTYUKH at OdessaJS'2020'STORY OF ANOTHER ANIMATION' by  YURII ARTYUKH at OdessaJS'2020
'STORY OF ANOTHER ANIMATION' by YURII ARTYUKH at OdessaJS'2020OdessaJS Conf
 
'JavaScript was invented in Odessa' by DMITRIY GUSEV at OdessaJS'2020
'JavaScript was invented in Odessa' by DMITRIY GUSEV at OdessaJS'2020'JavaScript was invented in Odessa' by DMITRIY GUSEV at OdessaJS'2020
'JavaScript was invented in Odessa' by DMITRIY GUSEV at OdessaJS'2020OdessaJS Conf
 
'Why svelte' by BORYS MOHYLA at OdessaJS'2020
'Why svelte' by BORYS MOHYLA at OdessaJS'2020'Why svelte' by BORYS MOHYLA at OdessaJS'2020
'Why svelte' by BORYS MOHYLA at OdessaJS'2020OdessaJS Conf
 
'Effective node.js development' by Viktor Turskyi at OdessaJS'2020
'Effective node.js development' by Viktor Turskyi at OdessaJS'2020'Effective node.js development' by Viktor Turskyi at OdessaJS'2020
'Effective node.js development' by Viktor Turskyi at OdessaJS'2020OdessaJS Conf
 
'Tensorflow.js in real life' by Pavlo Galushko at OdessaJS'2020
'Tensorflow.js in real life' by Pavlo Galushko at OdessaJS'2020'Tensorflow.js in real life' by Pavlo Galushko at OdessaJS'2020
'Tensorflow.js in real life' by Pavlo Galushko at OdessaJS'2020OdessaJS Conf
 

Plus de OdessaJS Conf (20)

'GraphQL Schema Design' by Borys Mohyla. OdessaJS'2021
'GraphQL Schema Design' by Borys Mohyla. OdessaJS'2021'GraphQL Schema Design' by Borys Mohyla. OdessaJS'2021
'GraphQL Schema Design' by Borys Mohyla. OdessaJS'2021
 
'How i came up with my talk' by Yurii Artiukh. OdessaJS'2021
'How i came up with my talk' by Yurii Artiukh. OdessaJS'2021'How i came up with my talk' by Yurii Artiukh. OdessaJS'2021
'How i came up with my talk' by Yurii Artiukh. OdessaJS'2021
 
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
 
Олексій Павленко. CONTRACT PROTECTION ON THE FRONTEND SIDE: HOW TO ORGANIZE R...
Олексій Павленко. CONTRACT PROTECTION ON THE FRONTEND SIDE: HOW TO ORGANIZE R...Олексій Павленко. CONTRACT PROTECTION ON THE FRONTEND SIDE: HOW TO ORGANIZE R...
Олексій Павленко. CONTRACT PROTECTION ON THE FRONTEND SIDE: HOW TO ORGANIZE R...
 
Андрій Троян. Розробка мікросервісів з NestJS. OdessaJS'2021
Андрій Троян. Розробка мікросервісів з NestJS. OdessaJS'2021Андрій Троян. Розробка мікросервісів з NestJS. OdessaJS'2021
Андрій Троян. Розробка мікросервісів з NestJS. OdessaJS'2021
 
Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...
Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...
Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...
 
Максим Климишин "Що такого особливого у пропозиції вартості шаблону Micro Fro...
Максим Климишин "Що такого особливого у пропозиції вартості шаблону Micro Fro...Максим Климишин "Що такого особливого у пропозиції вартості шаблону Micro Fro...
Максим Климишин "Що такого особливого у пропозиції вартості шаблону Micro Fro...
 
Павло Галушко. GOOD CODE MYTHS. OdessaJS'2021
Павло Галушко. GOOD CODE MYTHS. OdessaJS'2021Павло Галушко. GOOD CODE MYTHS. OdessaJS'2021
Павло Галушко. GOOD CODE MYTHS. OdessaJS'2021
 
"NODEJS & GRAPHQL COOKBOOK. LET’S TALK ABOUT MICRO-SERVICES" by Антон Чередні...
"NODEJS & GRAPHQL COOKBOOK. LET’S TALK ABOUT MICRO-SERVICES" by Антон Чередні..."NODEJS & GRAPHQL COOKBOOK. LET’S TALK ABOUT MICRO-SERVICES" by Антон Чередні...
"NODEJS & GRAPHQL COOKBOOK. LET’S TALK ABOUT MICRO-SERVICES" by Антон Чередні...
 
'BUILDING ANGULAR APPS WITH NX' by Anastasia Necheporenko
'BUILDING ANGULAR APPS WITH NX' by Anastasia Necheporenko'BUILDING ANGULAR APPS WITH NX' by Anastasia Necheporenko
'BUILDING ANGULAR APPS WITH NX' by Anastasia Necheporenko
 
'IS THERE JAVASCRIPT ON SWAGGER PLUGINS?' by Dmytro Gusev
'IS THERE JAVASCRIPT ON SWAGGER PLUGINS?' by  Dmytro Gusev'IS THERE JAVASCRIPT ON SWAGGER PLUGINS?' by  Dmytro Gusev
'IS THERE JAVASCRIPT ON SWAGGER PLUGINS?' by Dmytro Gusev
 
'ETHEREUM SMART CONTRACTS ON JS' by Yaroslav Dvorovenko
'ETHEREUM SMART CONTRACTS ON JS' by Yaroslav Dvorovenko'ETHEREUM SMART CONTRACTS ON JS' by Yaroslav Dvorovenko
'ETHEREUM SMART CONTRACTS ON JS' by Yaroslav Dvorovenko
 
'GOLANG USAGE IN DEVELOPMENT OF NODE.JS APPLICATIONS (NODE.JS: IN GO WE TRUST...
'GOLANG USAGE IN DEVELOPMENT OF NODE.JS APPLICATIONS (NODE.JS: IN GO WE TRUST...'GOLANG USAGE IN DEVELOPMENT OF NODE.JS APPLICATIONS (NODE.JS: IN GO WE TRUST...
'GOLANG USAGE IN DEVELOPMENT OF NODE.JS APPLICATIONS (NODE.JS: IN GO WE TRUST...
 
'MICROFRONTENDS WITH REACT' by Liliia Karpenko
 'MICROFRONTENDS WITH REACT' by Liliia Karpenko 'MICROFRONTENDS WITH REACT' by Liliia Karpenko
'MICROFRONTENDS WITH REACT' by Liliia Karpenko
 
'Web performance metrics' BY ROMAN SAVITSKYI at OdessaJS'2020
'Web performance metrics' BY ROMAN SAVITSKYI at OdessaJS'2020'Web performance metrics' BY ROMAN SAVITSKYI at OdessaJS'2020
'Web performance metrics' BY ROMAN SAVITSKYI at OdessaJS'2020
 
'STORY OF ANOTHER ANIMATION' by YURII ARTYUKH at OdessaJS'2020
'STORY OF ANOTHER ANIMATION' by  YURII ARTYUKH at OdessaJS'2020'STORY OF ANOTHER ANIMATION' by  YURII ARTYUKH at OdessaJS'2020
'STORY OF ANOTHER ANIMATION' by YURII ARTYUKH at OdessaJS'2020
 
'JavaScript was invented in Odessa' by DMITRIY GUSEV at OdessaJS'2020
'JavaScript was invented in Odessa' by DMITRIY GUSEV at OdessaJS'2020'JavaScript was invented in Odessa' by DMITRIY GUSEV at OdessaJS'2020
'JavaScript was invented in Odessa' by DMITRIY GUSEV at OdessaJS'2020
 
'Why svelte' by BORYS MOHYLA at OdessaJS'2020
'Why svelte' by BORYS MOHYLA at OdessaJS'2020'Why svelte' by BORYS MOHYLA at OdessaJS'2020
'Why svelte' by BORYS MOHYLA at OdessaJS'2020
 
'Effective node.js development' by Viktor Turskyi at OdessaJS'2020
'Effective node.js development' by Viktor Turskyi at OdessaJS'2020'Effective node.js development' by Viktor Turskyi at OdessaJS'2020
'Effective node.js development' by Viktor Turskyi at OdessaJS'2020
 
'Tensorflow.js in real life' by Pavlo Galushko at OdessaJS'2020
'Tensorflow.js in real life' by Pavlo Galushko at OdessaJS'2020'Tensorflow.js in real life' by Pavlo Galushko at OdessaJS'2020
'Tensorflow.js in real life' by Pavlo Galushko at OdessaJS'2020
 

Dernier

Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxfnnc6jmgwh
 
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructureitnewsafrica
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 

Dernier (20)

Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
 
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical InfrastructureVarsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
Varsha Sewlal- Cyber Attacks on Critical Critical Infrastructure
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 

Patrick Kettner - Creating magic with houdini

  • 1.
  • 2.
  • 3.
  • 4.
  • 5. FROM: Marc Andreessen (marca@eit.com) TO: www-talk@w3.org Thu, 17 Feb 1994 13:11:31 --100 RE: Indented <MENU>s ************************ *********** In fact, it has been a constant source of delight for me over the past year to get to continually tell hordes (literally) of people who want to -- strap yourselves in, here it comes -- control what their documents look like in ways that would be trivial in TeX, Microsoft Word, and every other common text processing environment: "Sorry, you're screwed."
  • 6.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 15. paintlayoutstyledomparsingnetwork compose Why on earth are you looking this closely at my files? You win a prize :] Seriously, just tell me you noticed this ridiculiously small text and I
  • 17. var sum=1+2 keyword identifier assignment int addition int “hey, that’s a keyword!”“and that’s an identifier!”“thats an integer!”“another integer!”“oh cool! an addition operator”“looks like an assignment operator”
  • 19. #document body header div p p <!DOCTYPE html> <body> <header>hello</header> <div> <p>world</p> <p>:]</p> </div> </body> <!DOCTYPE html> <body> <header>hello</header> <div> <p>world</p> <p>:]</p> </div> </body>
  • 21. #document body header div p p #document body header div * { background: red } div p { background: blue } p:last-of-type { background: orange } * { background: red } div p p:last-of-type div p { background: blue } * { background: red } p:last-of-type { background: orange } div p { background: blue } #document body header div p pp p
  • 23. body{ width: 250px } div { width: 10em; } p { width: 50% } body header div p p bodybody{ width: 250px }
  • 24. body{ width: 250px } div { width: 10em; } p { width: 50% } header div p p div p
  • 25. body{ width: 250px } div { width: 10em; } p { width: 50% } div p p divdiv { width: 10em; } div { width: 160px; }
  • 26. body{ width: 250px } p { width: 50% } p p pp { width: 50% } p { width: 80px }
  • 27. body{ width: 250px } p { width: 50px } p pp { width: 80px }
  • 28.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 40.
  • 41.
  • 46.
  • 49.
  • 50. years
  • 51.
  • 53. CSS Properties and Values API CSSOM PaintWorklet LayoutWorklet AnimationWorklet CSS Parser Font Metrics
  • 55. CSS Custom Properties(aka CSS variables)
  • 56.
  • 57. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; }
  • 58. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; }
  • 59. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; }
  • 60. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; }
  • 61. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; }
  • 62. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; }
  • 65. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; } CSS.registerProperty({ name: "--distance", syntax: "<length>", initialValue: ’0' })
  • 66. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; } CSS.registerProperty({ name: "--distance", syntax: "<length>", initialValue: ’0' }) required: any string
  • 67. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; } CSS.registerProperty({ name: "--distance", syntax: "<length>", initialValue: ’0' }) optional: <length> <number> <percentage> <color> <image> <url> <integer> <angle> <time> <resolution> <ident> *
  • 68. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; } CSS.registerProperty({ name: "--distance", syntax: "<length>", initialValue: ’0' })
  • 69. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; } CSS.registerProperty({ name: "--distance", syntax: "<length>", initialValue: ’0' })
  • 70. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: #F9391F; transition: --distance: 1s; } div:hover { --distance: 150px; } CSS.registerProperty({ name: "--distance", syntax: "<length>", initialValue: ’0' })
  • 71. CSSOMCSS Object ModelCSS Typed Object Model
  • 72. ^ ^ Here is a some dummy text Here is a a much much longer version of some dummy text that will ultimately cause the textbox to overflow the container that we are within and as a window.getComputedStyle('#elem').width == '200px';window.getComputedStyle('#elem').width == ’187px';
  • 73. function getInnerWidth (elem) { var style = window.getComputedStyle(elem); var width = elem.offsetWidth; var right = parseFloat(style.paddingRight); var left = parseFloat(style.paddingLeft); var bRight = parseFloat(style.borderRightWidth); var bLeft = parseFloat(style.borderLeftWidth); return width - right - left - bRight - bLeft; };
  • 74. function getInnerWidth (elem) { var style = window.getComputedStyle(elem); var width = elem.offsetWidth; var right = parseFloat(style.paddingRight); var left = parseFloat(style.paddingLeft); var bRight = parseFloat(style.borderRightWidth); var bLeft = parseFloat(style.borderLeftWidth); return width - right - left - bRight - bLeft; };
  • 75. function getInnerWidth (elem) { var style = window.getComputedStyle(elem); var width = elem.offsetWidth; var right = parseFloat(style.paddingRight); var left = parseFloat(style.paddingLeft); var bRight = parseFloat(style.borderRightWidth); var bLeft = parseFloat(style.borderLeftWidth); return width - right - left - bRight - bLeft; };
  • 76. function getInnerWidth (elem) { var style = window.getComputedStyle(elem); var width = elem.offsetWidth; var right = parseFloat(style.paddingRight); var left = parseFloat(style.paddingLeft); var bRight = parseFloat(style.borderRightWidth); var bLeft = parseFloat(style.borderLeftWidth); return width - right - left - bRight - bLeft; };
  • 77. function getInnerWidth (elem) { var style = window.getComputedStyle(elem); var width = elem.offsetWidth; var right = parseFloat(style.paddingRight); var left = parseFloat(style.paddingLeft); var bRight = parseFloat(style.borderRightWidth); var bLeft = parseFloat(style.borderLeftWidth); return width - right - left - bRight - bLeft; };
  • 78. function getInnerWidth (elem) { var style = window.getComputedStyleMap(elem); var width = elem.offsetWidth; var right = style.paddingRight.value; var left = style.paddingLeft.value; var bRight = style.borderRightWidth.value; var bLeft = style.borderLeftWidth.value; return width - right - left - bRight - bLeft; };
  • 79. function getInnerWidth (elem) { var style = window.getComputedStyleMap(elem); var width = elem.offsetWidth; var right = style.paddingRight.value; var left = style.paddingLeft.value; var bRight = style.borderRightWidth.value; var bLeft = style.borderLeftWidth.value; return width - right - left - bRight - bLeft; };
  • 80. function getInnerWidth (elem) { var style = window.getComputedStyleMap(elem); var width = elem.offsetWidth; var right = style.paddingRight.value; var left = style.paddingLeft.value; var bRight = style.borderRightWidth.value; var bLeft = style.borderLeftWidth.value; return width - right - left - bRight - bLeft; };
  • 81. Before: After: DOM API DOM API ➡ String ➡ Parse to number ➡ Calculations ➡ Calculations
  • 83. getComputedStyleMap(elem) // to query any current value elem.styleMap
  • 84. getComputedStyleMap(elem) // to query any current value elem.styleMap // for styles that have been // set via CSS explicitly
  • 85. style.get('width').unit == ’em'style.get('width').unit == ’vmax' var style = document.querySelector('#elem').styleMap style.get('width').value == '200' style.get('width').unit == 'px'
  • 86. var style = document.querySelector('#elem').styleMap style.set('width', new CSSUnitValue(50, 'em')) var style = document.querySelector('#elem').styleMap style.set('width', new CSSUnitValue(50, 'em'))
  • 87. var style = document.querySelector('#elem').styleMap var x = style.get(’background-position').x x.value == 50 x.unit == ’percent' // CSSUnitValue(50, "percent") var y = style.get(’background-position').y x.px == -10 x.percent == 100 x.unit == undefined // CSSCalcValue({percent: 100, px: -10}) #elem { background-position: center bottom 10px; } #elem { background-position: center bottom 10px; } #elem { background-position: center bottom 10px; }
  • 90.
  • 94. commit 90b52e847359ae902d3f7ce7bc511cadfbc29ea8 Author: Alexey Proskuryakov <ap@webkit.org> Date: Thu Nov 6 2008 07:04:47 +0000 Implement Worker global object
  • 95. self.onmessage = (e) { let result = doSomething(e.data) postMessage(result) } var myWorker = new Worker('worker.js'); myWorker.postMessage(’testing 123'); myWorker.onmessage = (e) => { doSomethingWithResult(e.data); } WebWorkers
  • 100.
  • 102. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 103. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 104. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 105. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 106. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 107. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 108. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 109. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 110. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 111. <!doctype html> <div id="myElement"> <div id="child1"></div> <div id="child2"></div> </div> <style> #myElement { width: 500px; height: 500px; display: layout('masonry') } </style> <script> window.layoutWorklet.addModule('masonry.js') </script>
  • 112. // masonry.js registerLayout('masonry', class { *layout(space, children, styleMap) { var inlineSize = resolveInlineSize(space, styleMap) var bordersAndPadding = resolveBordersAndPadding(varraintSpace, styleMap) var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap) var availableInlineSize = inlineSize - bordersAndPadding.inlineStart - bordersAndPadding.inlineEnd - scrollbarSize.inline; var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) - bordersAndPadding.blockStart - bordersAndPadding.blockEnd - scrollbarSize.block; ...
  • 113. // masonry.js registerLayout('masonry', class { *layout(space, children, styleMap) { var inlineSize = resolveInlineSize(space, styleMap) var bordersAndPadding = resolveBordersAndPadding(varraintSpace, styleMap) var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap) var availableInlineSize = inlineSize - bordersAndPadding.inlineStart - bordersAndPadding.inlineEnd - scrollbarSize.inline; var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) - bordersAndPadding.blockStart - bordersAndPadding.blockEnd - scrollbarSize.block; ...
  • 114. // masonry.js registerLayout('masonry', class { *layout(space, children, styleMap) { var inlineSize = resolveInlineSize(space, styleMap) var bordersAndPadding = resolveBordersAndPadding(varraintSpace, styleMap) var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap) var availableInlineSize = inlineSize - bordersAndPadding.inlineStart - bordersAndPadding.inlineEnd - scrollbarSize.inline; var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) - bordersAndPadding.blockStart - bordersAndPadding.blockEnd - scrollbarSize.block; ...
  • 115. // masonry.js registerLayout('masonry', class { *layout(space, children, styleMap) { var inlineSize = resolveInlineSize(space, styleMap) var bordersAndPadding = resolveBordersAndPadding(varraintSpace, styleMap) var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap) var availableInlineSize = inlineSize - bordersAndPadding.inlineStart - bordersAndPadding.inlineEnd - scrollbarSize.inline; var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) - bordersAndPadding.blockStart - bordersAndPadding.blockEnd - scrollbarSize.block; ...
  • 116. // masonry.js registerLayout('masonry', class { *layout(space, children, styleMap) { var inlineSize = resolveInlineSize(space, styleMap) var bordersAndPadding = resolveBordersAndPadding(varraintSpace, styleMap) var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap) var availableInlineSize = inlineSize - bordersAndPadding.inlineStart - bordersAndPadding.inlineEnd - scrollbarSize.inline; var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) - bordersAndPadding.blockStart - bordersAndPadding.blockEnd - scrollbarSize.block; ...
  • 117. yuck
  • 120. // masonry.js registerLayout('masonry', class { *layout(space, children, styleMap) { var inlineSize = resolveInlineSize(space, styleMap) var bordersAndPadding = resolveBordersAndPadding(varraintSpace, styleMap) var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap) var availableInlineSize = inlineSize - bordersAndPadding.inlineStart - bordersAndPadding.inlineEnd - scrollbarSize.inline; var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) - bordersAndPadding.blockStart - bordersAndPadding.blockEnd - scrollbarSize.block; ...
  • 121. // masonry.js registerLayout('masonry', class { *layout(space, children, styleMap) { var inlineSize = resolveInlineSize(space, styleMap) var bordersAndPadding = resolveBordersAndPadding(varraintSpace, styleMap) var scrollbarSize = resolveScrollbarSize(varraintSpace, styleMap) var availableInlineSize = inlineSize - bordersAndPadding.inlineStart - bordersAndPadding.inlineEnd - scrollbarSize.inline; var availableBlockSize = resolveBlockSize(varraintSpace, styleMap) - bordersAndPadding.blockStart - bordersAndPadding.blockEnd - scrollbarSize.block; ...
  • 122.
  • 123.
  • 126. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 127. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 128. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 129. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 130. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 131. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 132. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 133. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 134. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 135. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 136. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 137. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 138. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 139. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 140. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 141. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 142. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 143. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 144. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 145. // qr.js // slightly modified version of // https://github.com/yyx990803/QR.js import QR from 'QR' registerPaint('qr', class { static get inputProperties() { return [ '--qr-url' ]; } paint(ctx, geom, properties) { let url = properties.get('--qr-url').value const minSize = Math.min(geom.width, geom.height); if (url) { QR.draw(url, ctx, minSize, 2) } } });
  • 146.
  • 147. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> paintWorklet.addModule('qr.js') </script>
  • 148. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> const txt = document.querySelector('textarea') txt.addEventListener('input', (e) => { txt.style.setProperty('--qr-url', txt.value) }); paintWorklet.addModule('qr.js') </script>
  • 149. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> const txt = document.querySelector('textarea') txt.addEventListener('input', (e) => { txt.style.setProperty('--qr-url', txt.value) }); paintWorklet.addModule('qr.js') </script>
  • 150. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> const txt = document.querySelector('textarea') txt.addEventListener('input', (e) => { txt.style.setProperty('--qr-url', txt.value) }); paintWorklet.addModule('qr.js') </script>
  • 151. <!doctype html> <textarea id="myElement"></textarea> <style> #myElement { background-color: #5d1e6f; background-image: paint(qr); --qr-url: https://patrickkettner.com; width: 500px; height: 500px; } </style> <script> const txt = document.querySelector('textarea') txt.addEventListener('input', (e) => { txt.style.setProperty('--qr-url', txt.value) }); paintWorklet.addModule('qr.js') </script>
  • 152.

Notes de l'éditeur

  1. body { height: 100vh; width: 100vw; background: transparent radial-gradient(at calc(var(--mouse-x, 0) * 100%) calc(var(--mouse-y, 0) * 100%), cornflowerblue, white) no-repeat 0 0; } var root = document.documentElement; document.addEventListener('mousemove', function (evt) { var x = evt.clientX / innerWidth; var y = evt.clientY / innerHeight; root.style.setProperty('--mouse-x', x); root.style.setProperty('--mouse-y', y); })
  2. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  3. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  4. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  5. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  6. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  7. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  8. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  9. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  10. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  11. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  12. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  13. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  14. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  15. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  16. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  17. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  18. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  19. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  20. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  21. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  22. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  23. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  24. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  25. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  26. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  27. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  28. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  29. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  30. :root { --distance: 400px; } div { width: var(--distance); height: var(--distance); background: cornflowerblue; transition: --distance: 1s; } div:hover { background: green; --distance: 150px; }
  31. Added to webkit ri in 2008