Slide 1

Slide 1 text

HTML, CSS, and the Client-Side App Garann Means / @garannm

Slide 2

Slide 2 text

ah, the view..

Slide 3

Slide 3 text

not a lot of respect lots of jQuery where all that icky DOM stuff goes in off-the-shelf frameworks, may be unimplemented

Slide 4

Slide 4 text

at some point, the view was the app before XHRs, everything had to be synchronous one page per request pages became the core of the app

Slide 5

Slide 5 text

SPAs changed that view is just a repository can fill with data, input fields, monitoring etc.

Slide 6

Slide 6 text

yet the view is still the end product.

Slide 7

Slide 7 text

fair definition: presented to the user surface for interaction HTML and CSS, not just JavaScript

Slide 8

Slide 8 text

we talk about JS all the time frameworks new language features HTML5 without the HTML

Slide 9

Slide 9 text

booooooring.

Slide 10

Slide 10 text

HTML and CSS, on the other hand.. the scary part! wrangling them is painful observing them is tricky implementations differ between browsers the part you can’t screw up

Slide 11

Slide 11 text

we don’t need to treat HTML and CSS like it’s 2002.

Slide 12

Slide 12 text

consider a dot. dot

Slide 13

Slide 13 text

consider a dot.

Slide 14

Slide 14 text

consider a dot. .point { background-color: #B87E3D; height: 20px; width: 20px; border-radius: 10px; }

Slide 15

Slide 15 text

but it’s more than that. define( [ “text!graph.tmpl” ], function( tmpl ) { var that = this; this.points = { ... “47”: { x: 432, y: 210 }, ... }; this.render = function() { var el; for ( var pt in this.points ) { el = document.getElementById( “pt” + pt ); el.style.top = that.points[ pt ].y; el.style.left = that.points[ pt ].x; } }; return this; });

Slide 16

Slide 16 text

what we know to be true HTML is content CSS is presentation they display information but are not information themselves

Slide 17

Slide 17 text

..is wrong. HTML may define an object CSS may contain data about it either might define behavior that’s as crucial to the app as JS

Slide 18

Slide 18 text

especially when the user shows up.

Slide 19

Slide 19 text

especially when the user shows up.

Slide 20

Slide 20 text

NOW HTML and CSS are the authority on the data.

Slide 21

Slide 21 text

NOW HTML and CSS are the authority on the data.

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

this still fits the pattern model supplies initial data view reflects data and state event handlers update both

Slide 24

Slide 24 text

but control has shifted not encompassed by static CSS server has no idea what’s happening view responds without getting permission from the rest of the app

Slide 25

Slide 25 text

this is the app behind your app.

Slide 26

Slide 26 text

how we mess that up: nesting needlessly rewriting built-in behavior formless blobs of markup as templates shotgun approach CSS

Slide 27

Slide 27 text

over-nesting

Finally tho

Slide 28

Slide 28 text

when we could just..

Finally tho

Slide 29

Slide 29 text

we’re not shipping china. stop triple-wrapping everything makes things slow makes markup less meaningful resist adding elements for design objectives like padding

Slide 30

Slide 30 text

control freak app code events: { “click .enter-info”: “enterInfo” }, enterInfo: function() { var info = this.$el.next( “.info-form” ); info.show(); }

Slide 31

Slide 31 text

..is unnecessary .enter-info:target + .info-form { display: block; }

Slide 32

Slide 32 text

let HTML and CSS do their thing use anchors for links use built-in form validation use lists for listing things try not to involve JS in visual changes

Slide 33

Slide 33 text

messy templating

You

{{=it.username}}
{{=it.followers}}

Your news

{{~it.news :item}}

{{=news.title}}

by {{=news.username}}

{{=news.body}}

{{~}}

Add some news

Slide 34

Slide 34 text

divide and conquer

You

{{##def.userInfo}}

Your news

{{##def.newsItems}}

Add some news

{{##def.newsForm}}

Slide 35

Slide 35 text

tidy templating partials for child objects partials for independent widgets compile and concatenate on the server lets markup be consistent for all uses

Slide 36

Slide 36 text

it’s !important not to do this ul { list-style-type: none; margin: 0px; padding: 0px; } #content .news p.body ul { list-style-type: disc; margin: 20px; padding: 20px; } ul.not-a-list { list-style-type: none!important; margin: 0px!important; padding: 0px!important; }

Slide 37

Slide 37 text

normalize and plan ul.not-a-list { list-style-type: none; margin: 0px; padding: 0px; }

Slide 38

Slide 38 text

build functional css no substitute for a well-maintained styleguide keep defaults sensible separate CSS and JS hooks accept more CSS classes as a fair price for more enhancement

Slide 39

Slide 39 text

ok, so what do you do?

Slide 40

Slide 40 text

better views make HTML strongly-typed up your template game make CSS stateful consider an “app” that’s bigger than JS application code

Slide 41

Slide 41 text

HTML is the best jQuery plugin ever.

Slide 42

Slide 42 text

More than meets the eye: dot

Slide 43

Slide 43 text

More than meets the eye: dot

Slide 44

Slide 44 text

html will always be ui represents data with or without content element to data is a natural relationship

Slide 45

Slide 45 text

but it also has behavior clickable draggable editable form attribute functions

Slide 46

Slide 46 text

it has relationships nesting : namespacing lists : arrays or hashes fallbacks : overridable behavior

Slide 47

Slide 47 text

and proper typing semantic tags media elements new form element types

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

say every dot has a class. function Dot( opts ) { this.el = opts.el; this.x = opts.x || 20; this.y = opts.y || 20; this.update = function() { this.x = this.el.style.left; this.y = this.el.style.top; }; ... }

Slide 50

Slide 50 text

and we override its properties var pt47 = new Dot({ el: $( “#pt47” ), x: 432, y: 210 }); pt47.save = function() { this.update(); $.post( “/movedot”, this, ... ); };

Slide 51

Slide 51 text

could that not become its own application?

Slide 52

Slide 52 text

better example title

Slide 53

Slide 53 text

better example here is my cool title!

Slide 54

Slide 54 text

better example here is my cool title! title
here is my cool title!

Slide 55

Slide 55 text

even that’s more than we need.

Slide 56

Slide 56 text

better better example here is my cool title!
here is my cool title!

Slide 57

Slide 57 text

how far is that from an app? presents data: ✓ switch between display and edit: ✓ stores changes: ✓

Slide 58

Slide 58 text

best blogging app ever var dirty = false; function setDirty() { dirty = true; $( “#blogEntry” ).off( “input” ); } $( “#blogEntry” ).on( “input”, setDirty ); $( “#blogEntry” ).on( “blur”, function( e ) { if ( dirty ) { $.post( “/updateBlog”, this.innerText, function() { dirty = false; $( “#blogEntry” ).on( “input”, setDirty ); }); } });

Slide 59

Slide 59 text

or in a framework this.dirty: false, events: { “input #blogEntry”: “setDirty”, “blur #blogEntry”: “storeChanges” }, setDirty: function () { this.dirty = true; }, storeChanges: function() { if ( this.dirty ) { this.model.save( { body: this.$el.text() } ); this.dirty = false; } }

Slide 60

Slide 60 text

what we skipped submit button submit button handler markup and style for two modes (display and edit) code to switch between

Slide 61

Slide 61 text

integrating useful html observe broadcasted events move current data to permanent data store programmatically reset maybe: load polyfills done!

Slide 62

Slide 62 text

useful HTML begins with useful templates.

Slide 63

Slide 63 text

takes some research just use what came with your MVC framework, right? or what came with the server-side framework? BZZZZZT incorrect

Slide 64

Slide 64 text

should be specific to your app are templates shared? do they correspond to viewmodels? level of granularity? how are they compiled and packaged?

Slide 65

Slide 65 text

assume the default template engine is perfect. for the reference app.

Slide 66

Slide 66 text

almost always don’t be afraid of a little logic if it’s client-side, cache it distrust magic

Slide 67

Slide 67 text

write a renderer to manage caching and loading to do viewmodel type stuff e.g. composing data from pieces because having template engine API code in your view kinda sucks

Slide 68

Slide 68 text

a renderer function render( opts ) { var tmpl = tmplCache[ opts.name ]; $.extend( true, opts.data, staticData ); if ( tmpl ) { return opts.container ? opts.container.append( tmpl( opts.data ) ) : tmpl( opts.data ); } if ( !tmpl && opts.url ) { var p = tmplCache.partials; $.get( opts.url, function( raw ) { tmpl = opts.name ? tmplCache[ opts.name ] = doT.template( raw, p ) : doT.template( raw, p ); if ( opts.container ) { opts.container.append( tmpl( opts.data ) ); } }); } }

Slide 69

Slide 69 text

consider reuse client and server, obvs which pieces are chrome? which pieces will appear multiple places? do you need conditionals, or can you use CSS classes?

Slide 70

Slide 70 text

consider packaging what needs to load by default what is lazy-loaded what about admin vs. normal user what about other languages

Slide 71

Slide 71 text

a template is more than the visible area of your model.

Slide 72

Slide 72 text

templates initialize native element behaviors element states application state

Slide 73

Slide 73 text

organize everything templates for content one template minimum per widget templates for application states that require different markup or content

Slide 74

Slide 74 text

template as view define( [ "text!item.dot", "UserView", "CatView" ], function( itemtmpl, UserView, CatView ) { var ItemView = { init: function( container, data ) { tmplCache.ItemView = itemtmpl.template(); this.container = container; Object.observe( data, this.render ); // delegated event handlers go here }, render: function( updates ) { Renderer.render( { name: "ItemView", data: updates.object }); } }; return ItemView; });

Slide 75

Slide 75 text

template-driven build up dependencies in code partials CSS keep event handlers with the templates they select on

Slide 76

Slide 76 text

upgrade those views not a reflection of a model may not have one! should wire up its own rendering therefore: its own object even if it’s a partial

Slide 77

Slide 77 text

CSS is all the magic you need.

Slide 78

Slide 78 text

typical css, typical views expect to be present already switch out stylesheets for “page” changes rarely tied directly to an app

Slide 79

Slide 79 text

well why the heck not?

Slide 80

Slide 80 text

at minimum, css is state place in workflow user roles errors drilling-down

Slide 81

Slide 81 text

your CSS may also contain: data content animations event triggers application workflows

Slide 82

Slide 82 text

those are app pieces, and should be managed like it.

Slide 83

Slide 83 text

start with OOCSS your JS objects are modular your HTML is in templates which are in view modules modules can be required by a dependency manager GUESS WAT

Slide 84

Slide 84 text

what goes in the default normalization layout, fonts, headers, paragraphs, etc. generic error states generic widget styling (e.g. overlays) composable properties

Slide 85

Slide 85 text

lazy-load CSS as templates for optional add-ons for a/b testing for translated content for interactions

Slide 86

Slide 86 text

you don’t have to wait for JS to change the state .high-contrast:target + .content { background-color: #fff; color: #000; font-size: 16px; } body:not(.admin) .ctrl-panel { display: none; }

Slide 87

Slide 87 text

in yr widgets, doing yr clicky things again: don’t add JS to make visual changes if you don’t have to clicks that change display properties clicks that show and hide triggering animations

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

using CSS behavior in your app in terms of JS, should be wireless CSS behavior often listens to the same events JS does separate code in a separate file thus, treat it as a module

Slide 90

Slide 90 text

tying everything together

Slide 91

Slide 91 text

your app leans heavily on HTML and CSS trusts the DOM helps JavaScript narrow its responsibilities considers everything a module

Slide 92

Slide 92 text

your app is more awesome

Slide 93

Slide 93 text

thanks! @garannm / garann.com hammer icon from the noun project