Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HTML, CSS, and the client-side app

HTML, CSS, and the client-side app

Everyone knows client-side applications are built with JavaScript. Right? JavaScript ties the application together, but a considerable amount of most applications deals with markup and presentation. As much as they affect JavaScript, state, event handling, and default browser behaviour also impact HTML and CSS in the choices we make, optimizations we can take advantage of, and the architecture of our applications as a whole. And the HTML and CSS that make up the structure of our applications need to be managed just as much as our JavaScript does. We’ll talk about how HTML and CSS fit into the the big picture and how to take greater advantage of them in a context where we frequently consider them last.

Garann Means

May 03, 2013
Tweet

More Decks by Garann Means

Other Decks in Technology

Transcript

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

    View Slide

  2. ah, the view..

    View Slide

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

    View Slide

  4. 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

    View Slide

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

    View Slide

  6. yet the view is still
    the end product.

    View Slide

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

    View Slide

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

    View Slide

  9. booooooring.

    View Slide

  10. 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

    View Slide

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

    View Slide

  12. consider a dot.
    dot

    View Slide

  13. consider a dot.

    View Slide

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

    View Slide

  15. 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;
    });

    View Slide

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

    View Slide

  17. ..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

    View Slide

  18. especially when the user
    shows up.

    View Slide

  19. especially when the user
    shows up.

    View Slide

  20. NOW HTML and CSS are the
    authority on the data.

    View Slide

  21. NOW HTML and CSS are the
    authority on the data.

    View Slide

  22. View Slide

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

    View Slide

  24. 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

    View Slide

  25. this is the app
    behind your app.

    View Slide

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

    View Slide

  27. over-nesting



    a cool title

    more stuff
    different stuff



    Finally tho



    View Slide

  28. when we could just..


    a cool title
    more stuff
    different stuff


    Finally tho


    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  32. 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

    View Slide

  33. messy templating
    You
    {{=it.username}}

    {{=it.followers}}
    Your news
    {{~it.news :item}}

    {{=news.title}}
    by {{=news.username}}
    {{=news.body}}

    {{~}}
    Add some news



    View Slide

  34. divide and conquer
    You
    {{##def.userInfo}}
    Your news
    {{##def.newsItems}}
    Add some news
    {{##def.newsForm}}

    View Slide

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

    View Slide

  36. 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;
    }

    View Slide

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

    View Slide

  38. 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

    View Slide

  39. ok, so what do you do?

    View Slide

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

    View Slide

  41. HTML is the best
    jQuery plugin
    ever.

    View Slide

  42. More than meets the eye:
    dot

    View Slide

  43. More than meets the eye:
    dot

    View Slide

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

    View Slide

  45. but it also has behavior
    clickable
    draggable
    editable
    form attribute functions

    View Slide

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

    View Slide

  47. and proper typing
    semantic tags
    media elements
    new form element types

    View Slide

  48. View Slide

  49. 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;
    };
    ...
    }

    View Slide

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

    View Slide

  51. could that not become
    its own application?

    View Slide

  52. better example
    title

    View Slide

  53. better example
    here is my cool title!

    View Slide

  54. better example
    here is my cool title!
    title

    here is my cool title!


    View Slide

  55. even that’s
    more than we need.

    View Slide

  56. better better example
    here is my cool title!

    here is my cool title!

    View Slide

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

    View Slide

  58. 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 );
    });
    }
    });

    View Slide

  59. 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;
    }
    }

    View Slide

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

    View Slide

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

    View Slide

  62. useful HTML
    begins with
    useful templates.

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  67. 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

    View Slide

  68. 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 ) );
    }
    });
    }
    }

    View Slide

  69. 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?

    View Slide

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

    View Slide

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

    View Slide

  72. templates initialize
    native element behaviors
    element states
    application state

    View Slide

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

    View Slide

  74. 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;
    });

    View Slide

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

    View Slide

  76. 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

    View Slide

  77. CSS is all the magic you need.

    View Slide

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

    View Slide

  79. well why the heck not?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  83. 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

    View Slide

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

    View Slide

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

    View Slide

  86. 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;
    }

    View Slide

  87. 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

    View Slide

  88. View Slide

  89. 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

    View Slide

  90. tying everything together

    View Slide

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

    View Slide

  92. your app
    is more awesome

    View Slide

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

    View Slide