Upload
david-rodenas
View
95
Download
1
Embed Size (px)
Citation preview
Introduction to Web Programming
by Dr. David Rodenas
david-rodenas.com twitter.com/drpicox github.com/drpicox
for Java and C# programmers
© 2017
Javascript
basics and
history
@drpicox - ©2017
History
3
Self Scheme
(apply + '(1 2 3 4 5 6)) ===> 21 (set! f (lambda (n) (+ n 100))) (map f '(1 2 3)) ===> (101 102 103)
Mocha
@drpicox - ©2017
History
4
Self Scheme
Mocha
Livescript
@drpicox - ©2017
History
5
Self Scheme
Mocha
Livescript
Java
Javascript
@drpicox - ©2017
History
6
Self Scheme Java
Javascript
ECMAScript
@drpicox - ©2017
History
7
ECMAScript
ECMAScript 1
ECMAScript 2
ECMAScript 3
ECMAScript 4
ECMAScript 5- default- strict
ECMAScript 2015
ECMAScript 2016
ECMAScript 2017
https://github.com/tc39/proposals
@drpicox - ©2017
Compatibility
8
http://kangax.github.io/compat-table/es6/
@drpicox - ©2017
Reference
10
https://developer.mozilla.org/en-US/docs/Web/JavaScript
@drpicox - ©2017
Basics
11
@drpicox - ©2017
Be Carefullet value = getSomeValue(); if (value !== value) { alert('Value is not equal to itself'); }
// is there the alert possible?
12
Javascript
@drpicox - ©2017
Types• Everything is an Object
• Number: 1, 2, 5, 5000, -10, 3.14, 1e2, 1e-2, Infinity, NaN
• String: 'hello', 'a', 'long word'
• Boolean: true, false
• Array: [1,2,3], ['hi', 'there'], [3, 'times', true]
• Date: new Date('December 17, 1995 03:24:00'), Date.now()
• RegExp: /ab+c/g, new RegExp('ab+c', 'g')
• Function: function hello() { return world; }
• Object: any of above, {}, {hello: 'world'}
14
@drpicox - ©2017
Types• Everything is an Object, but
• null
• undefined
15
@drpicox - ©2017
Number• IEEE-754: 1, 2, 5, 5000, -10, 3.14, 1e2, 1e-2, Infinity, NaN, …
• Methods: toFixed, toExponential, …
• Math: it has all methods and constants that Number should have
• Cast to number:
• let number = Number(value);
• let number = parseInt(value, 10);
• let number = +value;
16
immutable
@drpicox - ©2017
Be Carefullet hourA = parseInt('08am'); let hourB = parseInt('08am', 10);
hourA ? hourB ?
17
@drpicox - ©2017
String• Any UCS-2 chain: 'hello', 'a', 'long word', …
• Character is length 1 string
• 'e' === 'hello'[1]
• Properties/Methods: length, slice, trim, concat, split, indexOf, …
• Cast to number:
• let string = String(value);
• let string = value.toString();
• let string = '' + value;
18
immutable
@drpicox - ©2017
Stringlet single = 'single comma string'; let double = "double comma string";
19
immutable
@drpicox - ©2017
Boolean• Just true / false
• Cast to boolean:
• let boolean = Boolean(value)
• let boolean = !!value
20
immutable
@drpicox - ©2017
"Boolean"• FALSY
• false
• null
• undefined
• ''
• 0
• NaN
21
• TRUTHY: any no falsy
• true
• []
• {}
• '0'
• 'false'
• …
Boolean(0) ? Boolean('0') ?
@drpicox - ©2017
Object• Anything but undefined or null: 'hello', 3, {rule: 'world'}, …
• Properties: prototype, constructor, …
• Static Methods: assign, create, defineProperties, defineProperty, freeze, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, getPrototypeOf, is, isExtensible, isFrozen, isSealed, keys, preventExtensions, seal, setPrototypeOf,
• Methods: hasOwnProperty, isPrototypeOf, propertyIsEnumerable, toLocaleString, toSource, toString, valueOf, …
• Built-in objects: Array, ArrayBuffer, Boolean, DataView, Date, Error, EvalError, Float32Array, Float64Array, Function, Generator, GeneratorFunction, Infinity, Int16Array, Int32Array, Int8Array, InternalError, JSON, Map, Math, NaN, Number, Object, Promise, RangeError, Reflect, RegExp, Set, String, Symbol, SyntaxError, TypeError, TypedArray, URIError, Uint16Array, Uint32Arrray, Uint8Array, Uint8ClampedArray, WeakMap, WeakSet, …
22
@drpicox - ©2017
Object// Object is a Map: // pairs string-value (properties)
let object1 = { property: 'anyValue', };
let object2 = new Object(); object.property = 'anyValue';
let object3 = new Object(); object['prop' + 'erty'] = 'anyValue';
23
@drpicox - ©2017
Object// By default, you can set any property object.property = 'anyValue';
// And you can get any value let value = object.property; console.assert(value === 'anyValue');
// even if not defined let notDefined = object.notDefined; console.assert(notDefined === undefined);
24
@drpicox - ©2017
Be Carefullet car = { color: 'blue' };
let carOwners = {}; carOwners[car] = 'elon';
JSON.stringify(carOwners);
25
@drpicox - ©2017
Object• Javascript is “classless” but have inheritance
• Java, C# is class oriented
• Javascript is instance oriented
• Inheritance is performed through prototype
• Every object can become a prototype of other object
• Every object has another object as prototype
• The main prototype of almost all objects is Object.prototype
26
@drpicox - ©2017
Object// By default objects have a Object's prototype
let car1 = { color: 'blue', };
let car2 = Object.create(Object.prototype); car.color = 'blue';
27
carX: .color
Object.prototype:prototype is
@drpicox - ©2017
Object// Object.prototype { constructor: …, hasOwnProperty: …, toString: …, … }
28
@drpicox - ©2017
Object// But it can have no prototype let prototypelessObject = Object.create(null);
// Object.getPrototypeOf(prototypelessObject) ? // Object.getPrototypeOf(Object.prototype) ? // Object.getPrototypeOf(Object) ?
29
prototypelessObject: nullprototype is
@drpicox - ©2017
Object// Objects can have any object as prototype
let car = { color: 'blue', };
let tesla = Object.create(car);
// car.color ? // tesla.color ?
30
car: .color
Object.prototype:tesla: prototype ishas value fallback
prototype ishas value fallback
@drpicox - ©2017
Object// Objects inherits its prototype properties
let car = { color: 'blue', };
let tesla = Object.create(car); tesla.brand = 'tesla';
// tesla.color ? // tesla.brand ? // Object.keys(tesla) ?
31
car: .color
tesla: .brand
@drpicox - ©2017
Object// Objects can overwrite prototype properties
let car = { color: 'blue', };
let ferrari = Object.create(car); ferrari.color = 'red';
// car.color ? // ferrari.color ?
32
car: .color
ferrari: .color
@drpicox - ©2017
Be Carefullet car = { color: 'red' };
let parkingSpot = { car: car, };
let wolowitzParkingSpot = Object.create(parkingSpot); wolowitzParkingSpot.car.color = 'gray';
// wolowitzParkingSpot.car.color ? // car.color ?
33
car: .color
parkingSpot: .car
@drpicox - ©2017
Objectclass Object { private Map<String,Object> properties; private Object prototype;
public Object get(String key) { if (properties.containsKey(key)) { return properties.get(key); } else if (prototype != null) { return prototype.get(key); } else { return Undefined; } }
public void set(String key, Object value) { properties.put(key, value); } }
34
@drpicox - ©2017
Object• In matter of speaking:
• Object.method.property are like Java/C# static members ex: Object.create
• Object.prototype.property are like Java/C# instance members ex: Object.prototype.isPrototypeOf
• Only properties, in matter of speaking:
• methods are properties whose value is a function
• members are properties whose value is not a function
• Object is a map, with an optional fallback map called prototype
35
@drpicox - ©2017
Be Carefullet wordCount = {}; let word; while (word = getSomeWord()) { if (wordCount[word]) { wordCount[word] ++; } else { wordCount[word] = 1; } }
// does it works? always?
36
@drpicox - ©2017
Array• [1,2,3], [42,'sense',{of: 'life'}], [], …
• Properties: length, push/pop, shift/unshift, slice, map/reduce/every/some, indexOf…
• Are sparse
• You can add properties
• [1,2,3].property = 'value';
37
@drpicox - ©2017
Array// Are objects + sugar syntax let array = ['a','b','c'];
array['1'] = 'd';
// array ?
38
@drpicox - ©2017
Array// Have dynamic length let array = ['a','b','c']; array[3] = 'd'; // array.length ? // array ?
array.length = 3; // array ?
array.length = 5; // array ?
39
@drpicox - ©2017
Array// As stack let array = ['b','c','d']; array.push('e'); let e = array.pop();
array.unshift('a'); let a = array.shift();
// As queue array.push('e'); let b = array.shift();
array.unshift('a'); let e = array.pop();
40
// Insert let array = ['a','c','d']; array.splice(1, 0, 'b');
// Remove let array = ['a','x','b','c']; array.splice(1, 1);
// Sort let array = ['c','a','b']; array.sort();
// Reverse let array = ['c','b','a']; array.reverse();
@drpicox - ©2017
Array// As functional array let copy = array.slice(); let numbers = ['a','b',1,2,3,'c'].slice(2,5); let moreNumbers = [1,2,3].concat([4,5]); let odds = numbers.filer(n => n % 2); let doubles = numbers.map(n => n * 2); let sum = numbers.reduce((s,n) => s + n); let allPositives = numbers.every(n => n >= 0); let thereIsATwo = numbers.some(n => n == 2); let firstBig = numbers.find(n => n >= 3); let bigIndex = numbers.findIndex(n => n >= 3); let indexOfTwo = numbers.indexOf(2);
41
@drpicox - ©2017
Function• Are Objects
• Properties: length, name, …
• Methods: apply, bind, call, …
• You can add properties:
• isOdd.property = 'value';
• Do not use new Function('n', 'n * 2') neither arguments
42
@drpicox - ©2017
Function// Function definition function isOdd(n) { return n % 2 === 1; }
// Function expression let isOdd = function(n) { return n % 2 === 1; };
43
@drpicox - ©2017
Function// Function arguments isOdd(1) // === isOdd(1, whatever) isOdd() // === isOdd(undefined)
// Variable arguments function sum(...args) { if (args.length === 0) { return 0; } return args[0] + sum(...args.slice(1)); } sum(1, 2, 3); sum(...[1, 2, 3]);
44
@drpicox - ©2017
Function// Function result function makeHelloWorld(hello, world) { return {hello: hello, world: world}; } makeHelloWorld('hi', 'mars') // {hello: 'hi', world: 'mars}
function collateral() { alert('this function has collateral effects'); } collateral() // undefined
45
@drpicox - ©2017
Be Carefulfunction makeThree() { return 1 + 1 + 1; }
makeThree(); // which is the result?
46
@drpicox - ©2017
Function// Function as arguments (high-order functions) function reduce(zero, fn, ...args) { if (args.length === 0) { return zero; } return fn( args[0], reduce(zero, fn, …args.slice(1)) ); } function add(a, b) { return a + b; } function sum(...args) { return reduce(0, add, ...args); }
47
@drpicox - ©2017
Function// Functions inside functions function sum(...args) { function add(a, b) { return a + b; } return reduce(0, add, ...args); }
function sum(...args) { return reduce(0, function(a, b) { return a + b; }, ...args); }
48
@drpicox - ©2017
Closures// Keep parent variables as state function makeCountdown(prev) { return function() { return prev -= 1; } }
let cd3 = makeCountdown(3); let cd5 = makeCountdown(5);
// cd3() ? cd3() ? // cd5() ? cd5() ? cd3() ? cd5() ?
49
@drpicox - ©2017
Closures// The equivalent in old Java
public IntSupplier makeCountdown(int prev) { final AtomicInteger counter = new AtomicInteger(prev);
return new IntSupplier() { public int getAsInt() { return counter.decrementAndGet(); } }; }
50
@drpicox - ©2017
Closures
51
Function Call 4 Return @address
Stack
Function Call 3 Return @address
Function Call 2 Return @address
Function Call 1 Return @address
Current Stack Frame
Grow
Local Variables
Local Variables
Local Variables
Local Variables
@drpicox - ©2017
Closures
52
Function Call 4 Return @address
Stack
Function Call 3 Return @address
Function Call 2 Return @address
Function Call 1 Return @address
Local Variables
Local Variables
Local Variables
Local Variables
Scopes
Global Scope
Parent Scopenew
new
new
new
@drpicox - ©2017
Closures// Use as callbacks function startClock() { let count = 0; let intervalId = setInterval(function() { console.log(count += 1); }, 1000); return function stopClock() { clearInterval(intervalId); }; }
let stopClock = startClock(); // …wait few seconds… stopClock();
53
@drpicox - ©2017
Closures// Use to create modules let myObj = (function() { let privateState = …; function privateFunction() { … }
return { publicMethodA: function() { …do something with privateState… }, publicMethodB: function() { …do something with privateFunction… }, … }; }());
54
@drpicox - ©2017
Be Carefulfunction countThree() { for (var i = 1; i <= 3; i++) { setTimeout(function() { alert(i); }); } }
55
@drpicox - ©2017
this// there is no method object = { sayHello: function(salute) { alert(salute); } };
object.sayHello('hello');
// only functions let sayHello = object.sayHello; sayHello('hello');
56
METHODgiphy.com
giphy.com
@drpicox - ©2017
this// there is this let bob = { name: 'Bob', sayHello: function(salute) { alert(salute + ' ' + this.name); } };
bob.sayHello('Hello');
// But… what happens here? let sayHello = bob.sayHello; sayHello('Hello');
57
@drpicox - ©2017
this// this is an implicit parameter bob.sayHello('Hi'); bob.sayHello.call(bob, 'Hi');
let sayHello = bob.sayHello; sayHello.call(bob, 'Hi');
// this can be anything sayHello.call({name: 'Chuck'}, 'Hi'); bob.sayHello.call({name: 'Chuck'}, 'Hi');
58
@drpicox - ©2017
this// this can be fixed = binded let alice = {name: 'Alice'} let sayHello = bob.sayHello; let sayToAlice = sayHello.bind(alice);
sayHello.call(alice, 'Hello'); sayToAlice('Hello');
// bind is the same than… function sayToAlice(...args) { return sayHello.call(alice, ...args); }
59
@drpicox - ©2017
this// this still fixed (binded) sayToAlice.call(bob, 'Hello');
object.sayToAlice = sayToAlice; object.sayToAlice('Hello');
60
ES2015 and beyond
coffeescript
atack
@drpicox - ©2017
Strings// multiline strings let multiline = ` this is a long multiline text `;
JSON.stringify(multiline)
62
@drpicox - ©2017
Strings// interpolation in strings let name = 'alice'; let age = 7; let interpolated1 = `${name} had ${age} years old`; let interpolated2 = `Today have ${age + 10}.`;
63
@drpicox - ©2017
Objects// shorthand properties let name = 'liddell'; let surname = 'liddell'; let shortNotationObject = { name, surname };
let longNotationObject = { name: name, surname: surname, };
64
@drpicox - ©2017
Objects// shorthand methods let shortNotationObject = { hello() { alert('hi!'); } };
let longNotationObject = { hello: function() { alert('hi'); } };
65
@drpicox - ©2017
Objects// shorthand getters/setters let shortNotationObject = { _name: 'alice', get name() { return this._name; } set name(name) { return this._name = name; } };
66
@drpicox - ©2017
Objectslet longNotationObject = { _name: 'alice' }; Object.defineProperty(longNotationObject, 'name', { get: function() { return this._name; }, set: function(name) { this._name = name; }, configurable: true, enumerable: true, } );
67
@drpicox - ©2017
Objects// computed property names let prop = 'foo'; let shortNotationObject = { [prop]: 'hey', ['b' + 'ar']: 'there' };
let longNotationObject = {}; longNotationObject[prop] = 'hey'; longNotationObject['b' + 'ar'] = 'there';
68
@drpicox - ©2017
Objectslet fullName = 'fullName'; let surname = 'carroll'; let shortNotationObject = { name: 'alice', surname, sayHello() { alert(this.fullName); }, get [fullName]() { return this.name + ' ' + this.surname; }, set [fullName](fullName) { this.name = fullName.split(' ')[0]; this.surname = fullName.split(' ')[1]; } };
69
@drpicox - ©2017
Arrow Functionslet addV1 = function(a, b) { return a + b; }.bind(this);
let addV2 = (a, b) => a + b;
let addV3 = (a, b) => { return a + b; };
70
@drpicox - ©2017
Arrow Functionslet incV1 = function(n) { return n + 1; }.bind(this);
let incV2 = (n) => n;
let incV3 = (n) => { return n + 1; };
let incV4 = n => n;
71
@drpicox - ©2017
Arrow Functionslet buV1 = function() { alert('bu!'); }.bind(this);
let buV2 = () => alert('bu!');
let buV3 = (n) => { alert('bu!'); };
let incV4 = _ => alert('bu!');
72
@drpicox - ©2017
Arrow Functionslet makeObjV1 = function(hello, world) { return {hello, world}; }.bind(this);
let makeObjV2 = (hello, world) => ({ hello, world });
let makeObjV3 = (hello, world) => { return {hello, world}; };
73
@drpicox - ©2017
Spread/Destructuring - Array// destructuring array let array1to3 = [1,2,3]; let [a, b] = array1to3;
// swap [a, b] = [b, a];
74
@drpicox - ©2017
Spread/Destructuring - Array// spread let array3to5 = [3,4,5]; let array1to5 = [1,2, ...array3to5];
// spread + destructuring let [one, ...array2to5] = array1to5; let [one, ...array2to4, five] = array1to5;
75
@drpicox - ©2017
Spread/Destructuring - Array// copy let array1to3 = [1,2,3]; let arrayCopy = [...array1to3];
// concat let array4to5 = [4,5]; let array1to5 = [...array1to3, ...array4to5];
76
@drpicox - ©2017
Spread/Destructuring Objects // destructuring object let {name, city} = { name: 'bob', vehicle: 'bike', city: 'barcelona', };
77
@drpicox - ©2017
Spread/Destructuring Objects // destructuring object with computed attribute let prop = 'vehicle'; let {[prop]: value} = { name: 'bob', vehicle: 'bike', city: 'barcelona', };
// value === 'bike'
78
@drpicox - ©2017
Spread/Destructuring Objects // restructuring function result function makeBob() { return { name: 'bob', vehicle: 'bike', city: 'barcelona', }; }
let {name, city} = makeBob();
79
@drpicox - ©2017
Spread/Destructuring Objects // function arguments function origin({name, world}) { console.log(`${name} comes from ${world}`); }
let alice = { name: 'alice', world: 'wonderland', }; origin(alice);
80
no-standard
-yet
http://codepen.io/pen?template=QpQQbR
@drpicox - ©2017
Spread/Destructuring Objects // arguments let earthObj = {world: 'earth'}; let earthCopy = {...earthObj};
// merge let helloObj = {hello: 'hi'}; let mergeObj = {...helloObj, ...earthObj};
81
no-standard
-yet
http://codepen.io/pen?template=QpQQbR
@drpicox - ©2017
Spread/Destructuring Objects // spread let earthObj = {world: 'earth'}; let helloWorldObj = {hello: 'hi', ...earthObj};
// destructuring let {world, ...helloObj} = helloWorldObj;
82
no-standard
-yet
http://codepen.io/pen?template=QpQQbR
@drpicox - ©2017
Spread/Destructuring Objects // copy let earthObj = {world: 'earth'}; let earthCopy = {...earthObj};
// merge let helloObj = {hello: 'hi'}; let mergeObj = {...helloObj, ...earthObj};
83
no-standard
-yet
http://codepen.io/pen?template=QpQQbR
@drpicox - ©2017
ClassObject.getPrototypeOf(Function) ?
84
@drpicox - ©2017
ClassObject.getPrototypeOf(Function) ?
typeof Function ?
85
@drpicox - ©2017
ClassObject.getPrototypeOf(Function) === Function.prototype
typeof Function === 'function'
86
@drpicox - ©2017
ClassObject.getPrototypeOf(Function) === Function.prototype Object.getPrototypeOf(Object) ?
typeof Function === 'function' typeof Function ?
87
@drpicox - ©2017
ClassObject.getPrototypeOf(Function) === Function.prototype Object.getPrototypeOf(Object) === Function.prototype Object.getPrototypeOf(Number) === Function.prototype
typeof Function === 'function' typeof Object === 'function' typeof Number === 'function'
88
@drpicox - ©2017
ClassObject.getPrototypeOf(Function) === Function.prototype Object.getPrototypeOf(Object) === Function.prototype Object.getPrototypeOf(Number) === Function.prototype
typeof Function === 'function' typeof Object === 'function' typeof Number === 'function' …
// Functions are constructors! new Number(3)
89
@drpicox - ©2017
Classfunction Animal() { }
let animal = new Animal();
90
Animal.prototype:animal:
@drpicox - ©2017
Classfunction Animal(name) { this.name = name; }
let fievel = new Animal('fievel');
91
Animal.prototype:fievel: .name
@drpicox - ©2017
Classfunction Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(this.name + ' makes a noise'); };
let fievel = new Animal('fievel');
92
Animal.prototype: .speak
fievel: .name
@drpicox - ©2017
Classfunction Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(this.name + ' makes a noise'); };
let fievel = new Animal('fievel'); let tanya = new Animal('tanya');
93
Animal.prototype: .speaktanya:
.name
fievel: .name
@drpicox - ©2017
Classfunction Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(this.name + ' makes a noise'); };
let fievel1 = new Animal('fievel');
let fievel2 = Object.create(Animal.prototype); Animal.call(fievel2, 'fievel');
94
@drpicox - ©2017
Classfunction Animal(name) { this.name = name; } Animal.prototype.speak = function() { … };
function Lion(name) { Animal.call(this, name + ' the lion'); } Lion.prototype = Object.create(Animal.prototype); Lion.prototype.constructor = Lion; Lion.prototype.speak = function() { console.log(this.name + ' roars!'); };
95
Animal.prototype: .speak .constructor
Lion.prototype: .speak .constructor
@drpicox - ©2017
Classclass Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise'); } }
class Lion extends Animal { constructor(name) { super(name + ' the lion'); } speak() { console.log(this.name + ' roars'); } }
96
@drpicox - ©2017
Import / Export• CommonJS
• node.js resolution algorithm
• SystemJS
• custom resolution algorithm: exact file or configuration
98
@drpicox - ©2017
Import / Export// Node.js Resolution Algorithm (from itself) require('./path/file'); require('./path/file.js'); require('./path/file/index.js');
- /src - /path - /file - index.js - me.js
99
@drpicox - ©2017
Import / Export// Node.js Resolution Algorithm (from package) require('package/path/file'); require('package/path/file.js'); require('package/path/file/index.js');
- /src - me.js - /node_modules - /package - /path - file.js
100
@drpicox - ©2017
Import / Export// Node.js Resolution Algorithm (from package^2) require('subpackage/file'); require('subpackage/file.js'); require('subpackage/file/index.js');
- /node_modules - /package - /node_modules - /subpackage - /file - index.js - me.js
101
css
http://www.csszengarden.com/
@drpicox - ©2017
Selectors// Basic selectors <article id="main" class="promoted">…</article>
article { /* apply to all articles */ } #main { /* apply to element id=main */ } .promoted { /* apply to those promoted class */
article#main.promoted { /* can be combined */ }
104
@drpicox - ©2017
Selectors// Scoping selectors <article class="promoted"> <h1>…</h1> </article>
h1 { /* apply to all headings */ } article h1 { /* apply to headings inside articles */ } article.promoted h1 { /* apply to headings inside promoted articles */ }
105
@drpicox - ©2017
Selectors// More selectors
http://www.css3.info/selectors-test/
https://flukeout.github.io/
106
@drpicox - ©2017
Selectors// Priority selectors <article #main class="promoted">…</article>
article.promoted { background: red; color: white; } .promoted { background: blue; text-decoration: underline; } #main { color: yellow; }
https://specificity.keegan.st/
107
@drpicox - ©2017
Position<article> <div class="highlight"></div> … </article>
article { position: relative; } .highlight { position: absolute; top: 0; right: 0; left: 0; bottom: 90%; }
108
@drpicox - ©2017
Float<article> <img src="http://placehold.it/150x150"> … </article>
image { float: left; margin: 10px; }
109
@drpicox - ©2017
Display<article> Lorem Ipsum is simply dummy text <span>of the printing and typesetting</span> industry. Lorem Ipsum has been the standard. </article>
span { display: block; /* inline inline-block */ margin: 10px; /* try padding */ background: yellow; }
110
@drpicox - ©2017
Box Model
111
/* Keyword values */ box-sizing: content-box; box-sizing: border-box;
@drpicox - ©2017
Flex Boxdisplay: flex;
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
https://philipwalton.github.io/solved-by-flexbox/
http://flexboxfroggy.com/
112
@drpicox - ©2017
@media queries// Designed to change appearance in each media
body { font-size: 14px; } @media print { body { font-size: 20pt; } }
113
@drpicox - ©2017
@media queries// Responsive .articles { display: flex; flex-direction: column; }
@media (min-width: 600px) { .articles { flex-direction: row; justify-content: space-around; } }
114
@drpicox - ©2017
virtual pixels<meta name="viewport" content="width=device-width, initial-scale=1">
115
@drpicox - ©2017
relative sizes<div class="box"> regular </div> <div class="small"> <div class="box"> small </div> </div>
.small { font-size: 50%; }
.box { width: 5em; height: 2em; background: yellow; margin: 0.5em 1em; }
116
@drpicox - ©2017
Performancehttps://developers.google.com/web/fundamentals/performance/rendering/
117
@drpicox - ©2017
Performance
118