You are on page 1of 88

* Beautiful Markup

Curing DIV-itis with Semantic HTML,
CSS and Presenters

JOHN ATHAYDE, INFOETHER
RAILS CONF 2010 BALTIMORE, MARYLAND

Wednesday, June 9, 2010

Wednesday, June 9, 2010

Wednesday, June 9, 2010

Wednesday, June 9, 2010
http://www.flickr.com/photos/frengo/992920521/

2010 . MARYLAND Wednesday. CSS and [maybe] Presenters JOHN ATHAYDE. INFOETHER RAILS CONF 2010 BALTIMORE. June 9. * Beautiful Markup Curing DIV-itis with Semantic HTML.

(or please stop killing baby animals with your HTML and CSS) Wednesday. June 9. 2010 .

June 9. 2010 .. Let’s Assume.. » YOU KNOW HTML & CSS BASICS » YOU KNOW RAILS » YOU WANT TO MAKE IT BETTER Wednesday.

June 9. STOP Please. 2010 . Wednesday.

Wednesday.. June 9. * Let’s Talk About.. what the problem is in the first place. 2010 .

June 9.flickr.com/photos/toby_d1/3588461929/ Views are still.. The Wild West Wednesday.. 2010 .http://www.

member_contributed %> <li class="add_to_cart"> <% if composition. :locals => {:class_name => composition. composition.each_with_index do |listing.png".title.github.:title => "Add to Playlist"). a 60 line partial (called 30 times in one page) <ol class="narrow_playlist"> <% playlist. :title => composition. downloads_path(:audio_item_id => composition. :ratable => composition}%> <li> <%= link_to_function(image_tag("icon_load_in_player..superclass.com/78365 Wednesday.name).title.preview_url %>"> <span class="hide_me">Preview</span>&nbsp.network? %> <%= link_to image_tag("button_playlist_download. An example. "addCompositionToPlayerPlaylist(#{composition. label_release_track_path(composition. :method => :post%> <% else %> <%= link_to(image_tag("cart. :alt => "Add to cart". "") %> </li> <% if !composition.slug.png".title %></h6> <h6><%= link_to awesome_truncate(composition.title %></h6> </td> <td class="listing_icon_col" rowspan="3"> <ul class="playlist_site_actions"> <li class="preview"> <a class="sm2_link" href="<%= composition. :title => "Preview").30).id. composition_path(composition).audio_items. :method => :post) %> <% end -%> </li> <% end -%> </ul> </td> </tr> <tr> <td></td> <td><h6 class="artist"><%= linked_profiles(composition) %></h6></td> </tr> <tr> <td></td> <td> <ul class="playlist_social_actions"> <%= render :partial => "/ratings/rating_list".first. June 9. 2010 ..slug). :salable_type => composition. </a> <%= link_to_function(image_tag("icon_speaker_preview.gif".class.gif".&nbsp.&nbsp.class. :title => composition. selections_path(:salable_id => composition. :alt => "Preview".30). :title => "Add to cart").composition %> <% position = i %> <li class="playlist_item"> <table class="playlist_listing"> <tr> <td class="listing_rank_col"> <%= position+1 %> </td> <td class="listing_title_col"> <h6><%#= link_to awesome_truncate(composition.label. :alt => "Download").id})" %> </li> </ul> </td> </tr> </table> </li> <% end %> <% end -%> </ol> http://gist.release.listings. :alt => "Add to Playlist".name. i| -%> <% if i < show %> <% composition = listing.id).

&nbsp.name).each_with_index do |listing.preview_url %>"><span class="hide_me">Preview</span>&nbsp. :salable_type => composition.listings. :alt => "Download").gif".gif".network? %> !!!!!!!!!!<%= link_to image_tag("button_playlist_download.id})") %> !!!!!!!!!!!!</li> !!!!!!!!!!</ul> !!!!!!</li> <% end %> <% end -%> </ol> Wednesday.class.30). :ratable => composition}%> !!!!!!!!!!!!<li> !!!!!!!!!!!!!!<%= link_to_function(image_tag("icon_load_in_player.</a> !!!!!!!!<% if composition.superclass. selections_path(:salable_id => composition. :alt => "Add to cart". 2010 . :alt => "Add to Playlist".id). :title => "Add to cart"). :title => composition..:title => "Add to Playlist").composition %> !!!!!!<% position = i %> !!!!!!<li class="playlist_item"> !!!!!!!!<p class="track_title"><%= link_to awesome_truncate(composition. <ol class="latest_uploads"> !!<% playlist.first. June 9..title %></p> !!!!!!!!<p class="sm2_link"><a href="<%= composition.id. i| -%> !!!!<% if i < show %> !!!!!!<% composition = listing.class. composition_path(composition).&nbsp. downloads_path(:audio_item_id => composition. :method => :post%> !!!!!!!!<% else %> !!!!!!!!!!<%= link_to(image_tag("cart. :method => :post) %> !!!!!!!!<% end -%></p> !!!!!!!!<p class="artist_name"><%= linked_profiles(composition) %></p> !!!!!!!!!!<ul class="playlist_social_actions"> !!!!!!!!!!!!<%= render :partial => "/ratings/rating_list". A quick cleanup.title.name. "addCompositionToPlayerPlaylist(#{composition.audio_items.png". :locals => {:class_name => composition.

June 9. 2010 . Do The Math. 60 LOC Partial* 30 = 1800 LOC 24 LOC Partial* 30 = 720 LOC (that’s a whole lotta books) Wednesday.

2010 . Didn’t even touch: * Helper methods * Presenters * Brazillian Jujitsu Wednesday. June 9.

2010 . June 9. (don’t use this) Wednesday.

address %></div> .email <div class="right column"> #bio= current_user. June 9.right. Bake Off! <%= ERB %> #profile <div id="profile"> .column </div> #email= current_user.bio <div id="email"> <%= current_user.left.bio %></div> </div> </div> Wednesday.column <div class="left column"> #date= print_date <div id="date"><%= print_date %></div> #address= <div id="address"> current_user.email %></div> <div id="bio"><%= current_user.address <%= current_user. 2010 .

June 9. 2010 .email <div class="right column"> #bio= current_user.left.email %></div> <div id="bio"><%= current_user.address %></div> .bio <div id="email"> <%= current_user.column <div class="left column"> #date= print_date <div id="date"><%= print_date %></div> #address= <div id="address"> current_user. Bake Off! <%= ERB %> #profile <div id="profile"> .address <%= current_user.bio %></div> </div> </div> Wednesday.column </div> #email= current_user.right.

2010 . June 9. DIV Wednesday.

DIVDIV DIV DIV DI Wednesday. 2010 . June 9.

June 9.IV DIVDIV DIV Wednesday. 2010 DIV DI .

) DI . 2010 DIV (OMG.IV DI DIVDIV DIV Wednesday. June 9.

June 9. 2010 .) Wednesday. IF YOU LIKED IT THEN YOU SHOULDA PUT A DIV ON IT (oh yes. he went there.

June 9. (don’t use this) ^ yo u ’re d o i ng u kno w w hat unle s s yo Wednesday. 2010 . Revision.

June 9.. Wednesday. 2010 . * Don’t Hate haml The tool is not the problem..

.flickr. June 9. 2010 http://www.The hand coders do it too.com/photos/scooter811/1475730494/ . Wednesday..

big. form. del. var. span. strike. p. font. strong. legend. sub. address. ol. h3. tfoot. June 9. dfn. Learn the elements They aren’t scary. iframe. h4. th. dl. li. acronym. small. div. q. sup. img. tr. h6. td Wednesday. abbr. code. h2. dd. html. s. caption. applet. em. h5. h1. thead. label. blockquote. ul. fieldset. 2010 . tbody. body. kbd. samp. ins. a. tt. cite. table. object. dt. pre.

smashingmagazine.com/2010/05/13/ css-2-1-and-css-3-help-cheat-sheets-pdf/ http://www. 2010 . June 9.com/2009/07/06/ html-5-cheat-sheet-pdf/ Wednesday.smashingmagazine. Helping hands Cheat Sheets! http://www.

2010 . HIERARCHY Where it’s at. June 9. Wednesday.

Item 3<br /> </div> Wednesday. everything is the same. 2010 .Item 1<br /> . <div class="headline">This is a page headline.Item 2<br /> . No Hierarchy Not semantic.</div> <div class="list">This is going to be a list of items:<br /> . I like cheese.</div> <div class="subhead">This is a section head</div> <div class="body">This is body text and it goes on for miles and miles. June 9.

June 9. No Hierarchy Not semantic. everything is the same. Wednesday. 2010 .

</p> <p>This is going to be a list of items:</p> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> Wednesday. June 9. Semantic.</h1> <h2>This is a section head</h2> <p>This is body text and it goes on for miles and miles. 2010 . HTML Tags used for meaning <h1>This is a page headline. I like cheese.

Semantic. 2010 . June 9. HTML Tags used for meaning Wednesday.

com/photos/roll_initiative/3278642272/ IS DANGEROUS Wednesday.flickr. 2010 . Generated Markup THIS ONE http://www. June 9.

<%= div_for @product do %> <% end %> <div id=”product123” class=”products”> </div> Wednesday. 2010 . June 9. div_for? Don’t use this.

. content_tag But only if you must. :class => "bar") %> <% end %> <li id="product_123" class="product bar"> li.product. June 9. @product. 2010 . <%= content_tag_for(:li.bar {} Wednesday..

products li {} ul.products li.each do |product| %> <li id="product_<%= @product. June 9...id %>" class="bar"> <% end %> </ul> <ul class=”products”> <li id="product_123" class="bar"> .products {} ul. Could be cleaner Write html. 2010 .bar {} Wednesday. </ul> ul. <ul class=”products”> <% @product.

Helpers
Avoid Markup

def full_name(person)
“<p class=”name”>#{@person.first_name} #{@person.last_name}</p>”
end

def full_name
“#{@person.first_name} #{@person.last_name}”
end

Wednesday, June 9, 2010

Helpers
Summarization is where they shine.

def referrer_for(account)
if account.referrer
referral = “Referred_by #{account.referrer.name}”
if account.web_contact?
“#{referral} via Web registration”
else
referral
end
else
“Web registration”
end
end

Wednesday, June 9, 2010

HTML IS CODE
Stop having code generate code.

Wednesday, June 9, 2010

Zen Coding
Use a tool, not a generator
div#page>img.logo+ul#navigation>li*5>a

<div id="page">
<img src=”” class="logo" />
<ul id="navigation">
        <li><a href=""></a></li>
        <li><a href=""></a></li>
        <li><a href=""></a></li>
        <li><a href=""></a></li>
        <li><a href=""></a></li>
    </ul>
</div>

PROJECT FILES:
code.google.com/p/zen-coding/

Wednesday, June 9, 2010

June 9... 2010 . Wednesday. * Why it matters Not all user agents are created equal.

June 9. 2010 . WEB ACCESSIBILITY Take care of your users Wednesday.

Wednesday.flickr. 2010 http://www.Google is a blind user.com/photos/scooter811/1475730494/ . June 9.

June 9. §508 www.gov Wednesday. 2010 .section508.

2010 . June 9. START SMALL Cover the basics all the time. WAI Level 1 Checklist: www.org/TR/WCAG10/full-checklist.w3.html Wednesday.

name}”). product_path(@product).png”. :title => “Take a look at #{@product.png”. :title => “Take a look at #{@product.name}” Wednesday. 2010 . June 9. :alt => “#{@product.name}” link_to (image_tag “product_12758.name}” image_tag “product_12758.name. product_path(@product). :alt => “# {@product. Web Accessibility ERB Examples link_to @product.

Web Accessibility = Well Formed HTML Not just an afterthought. June 9. 2010 . Wednesday.

. June 9. from all those classic UI hacks! Wednesday.. * Legacy issues. 2010 .

in/~lX Wednesday. 2010 . Seriously. June 9. Rounded Corners. <div class="b"> <div class="l"> <div class="r"> <div class="bl"> <div class="br"> <div class="tl"> <div class="tr box"> <%= content %> </div> </div> </div> </div> </div> </div> </div> http://frst.

/* IE9. June 9.5 */ -webkit-border-radius: 5px. Chrome */ -moz-border-radius: 5px. “CSS3” The Beast. border-radius: 5px. 2010 . Opera 10. Rounded Corners.box-to-be-rounded { border: 1px solid #ccc. /* Firefox */ } Wednesday. /* Safari. <div class=”box-to-be-rounded”> <%= content %> </div> .

text_field :first_name %> span.} Wednesday.label :first_name %> <span class=”required”>*</span><br /> <%= f. June 9.required {color: red. Required Fields Love the form you’re with. 2010 . <%= f.

required { color: red. 2010 . } label. June 9.html Wednesday. :class => “required” %> <%= f.required:after { content: “*”.quirksmode.label :first_name. } Not supported in MSIE 7 and below.text_field :first_name %> label { display: block.org/css/beforeafter. Required Fields Progressively enhance! <%= f. } label. 8 does not accept images for content REFERENCE: www.

2010 . June 9.com/blog/2006/07/before-and-after-in-ie7-and-below. Required Fields Hackety hacked for MSIE 7 [code redacted to protect the children] http://nanobox.php Wednesday.chipx86.

. Let’s get down to the sexy: Rails Presenters Wednesday. June 9. * Presenting.. 2010 .

2010 http://www.com/photos/shuffle-art/2810247509/ . June 9. Wednesday.Encapsulation.flickr.

June 9. Wednesday.com/photos/chokingsun/3495110670/ .flickr. 2010 http://www.Generic Reuse.

Wednesday.com/photos/_zahira_/4579176204/ .flickr. 2010 http://www.Present it. June 9.

* CSS Tricks. 2010 .. June 9.. The good. bad and ugly of CSS Templates and Dynamic CSS Wednesday.

com/photos/shinez/4004798080/ . 2010 http://www.flickr.Dynamic CSS Wednesday. June 9.

2010 . theming) You have an app that you redeploy Wednesday. June 9. Why Generate? There are a few justified cases * You are supporting themes * You have an insanely large CSS set * to many clients (aka.

Get SASSy Haml back again !darkgrey = #221f10 #sidebar background-color: !darkgrey generates. #sidebar { background-color: #221f10. June 9. } Wednesday. 2010 ...

com/photos/gettysgirl/3481084323/ . sprites Wednesday. 2010 http://www. June 9.Sprites.flickr.

2010 .alistapart. Not Very Fairy reduce the server calls for icons/images BACKGROUND: www. June 9.com/articles/sprites Wednesday.

. :class => "email". <%= image_tag ("email. 2010 ..gif"). :class => "email" %> <%= image_sprite :email. :title => "Email" %> DETAILS: 37signals. June 9. Sprites in Helpers Classic like.com/svn/posts/2336-using-css-sprites-with-rails-helper-methods Wednesday.

:email => {:w => 26. :x => 0. :y => 0}.png')}) no-repeat -#{sprites[image][:x]}px -#{sprites [image][:y]}px. :x => 166. def image_sprite(image. :h => 17. :h => 16. :x => 135. :x => 360. width: #{sprites[image][:w]}px. :y => 0}. :y => 0}. :y => 0}. :y => 0}. :x => 120.com/svn/posts/2336-using-css-sprites-with-rails-helper-methods Wednesday. :y => 0}. :y => 0}. :h => 11. :trash => {:w => 10. :h => 13. :comments_unread => {:w => 13. :y => 0}. :timeclock_off => {:w => 17. :h => 16. :x => 41. :print => {:w => 25. :y => 0} } %(<span class="sprite #{options[:class]}" style="background: url(#{path_to_image ('/images/basecamp_sprites. :y => 0}. :x => 150. :h => 14. :x => 68. :rss => {:w => 14. June 9. #{options[:style]}" title="#{options[:title]}">#{options[:title]}</span>) end DETAILS: 37signals. :h => 13. :ical => {:w => 14. :comments_read => {:w => 13. :x => 375. :h => 11. padding-top: #{sprites[image][:h]}px. :h => 16. :y => 0}. :h => 13. :h => 17. :x => 392. :h => 17. :comments => {:w => 13. :x => 94. options = {}) sprites = { :add_icon => {:w => 16. 2010 . :y => 0}. :timeclock => {:w => 17. :drag => {:w => 11. :x => 105.

June 9. 2010 .flickr.com/photos/owaters/3846053408/ Wednesday. CSS Templates css template (bad) http://www.

flickr. 2010 .. Why? Derived from the print world.. June 9.com/photos/eadaoinflynn/3666328306/ Wednesday. http://www.

June 9. Wednesday. 2010 http://www.flickr.com/photos/bashford/4330125086/ .

grid_4{ width:300px.grid_3{ width:220px.grid_5{ width:380px.container_12 .grid_1{ width:60px.container_12 .grid_6{ width:460px. } .gs Not Semantic . 960. } . } Wednesday.container_12 . } . } .container_12 . June 9. } . 2010 .container_12 .container_12 .grid_2{ width:140px.

Survey says. June 9... 2010 . X Wednesday.

2010 http://www.Toupee. June 9.com/photos/eadaoinflynn/3666328306/ .flickr. Wednesday.

June 9.com/marchdoe/toupee Wednesday. 2010 . LAYERED APPROACH Turn it on and off REFERENCE: github.

* Quick Starts. June 9. Saving time with a gem generator to get up and running with a basic setup Wednesday. 2010 ...

June 9. Put that in your pipe and smoke it! Wednesday. ONE FILE to bring them all and on the server bind them. 2010 .

/javascripts/jquery-ui-1.html. Calling All CSS Classic like.css") screen.css") print. @import url("print. app/layouts/application.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html. 2010 .custom. projector' %> public/stylesheets/application.0 Transitional//EN" "http://www.dtd"> <html xmlns="http://www.org/TR/xhtml1/DTD/xhtml1-transitional. /* Plugin stylesheets */ @import url(".8. charset=utf-8"/> <title><%= APP_CONFIG[:name] %></title> <!-. /* If there are any styles that we want IE5/Mac to see.1/css/cupertino/jquery-ui-1.w3.1.erb <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.css /* Title: Screen styles and MSIE patches Author: John Athayde */ /* import stylesheets and hide from IE/Mac \*/ @import url("reset.css'.8.css") screen.css") screen..w3. June 9.The first style sheet calls the rest --> <%= stylesheet_link_tag 'application.. we put them after this */ Wednesday. @import url("master. :media => 'screen..

MSIE hacks. June 9. 2010 . Javascript. * MSIE 6/7 Specific styles * MSIE 24 bit PNG fixes * Clearfix * Custom Gems (Deadweight/Startups) CSS STARTUP: www.com/boboroshi/infoether-framework Wednesday.github. My Base App Setup Rails 3 app w/CSS. etc.

“Jammit is an industrial strength asset packaging library for Rails. ahead-of-time gzipping..github. and optional Data-URI / MHTML image and font embedding.” JAMMIT INFO: documentcloud. June 9. 2010 . built-in JavaScript template support.. A more robust method that covers javascript too.com/jammit Wednesday. as well as YUI Compressor and Closure Compiler compatibility. providing both the CSS and JavaScript concatenation and compression that you'd expect.

flickr. June 9.com/photos/dierken/948171048 STARTUPS GEM: www. startups http://www.com/infoether/startups Wednesday.github. 2010 .

* Clean up that mess Code audits. 2010 . unused CSS and moving to production Wednesday. June 9.

/* Firefox */ font-size: 1. padding: 5px. input. /* Safari. Wednesday. /* IE9. } Alphabetical. Chrome */ -moz-border-radius: 3px. Organize it! Standardize what you do as a team. Opera 10. with vendor specific switches kept next to official attributes. June 9.5 */ -webkit-border-radius: 3px. 2010 . textarea { border-radius: 3px.4em.

com/dustmeselectors Wednesday. Unused Selectors UI side: Dust Me Selectors FIREFOX ADD-ON: www. June 9.sitepoint. 2010 .

root = 'http://staging.pages = %w( / /page/1 /about ) dw.forms.page.new do |dw| dw.ignore_selectors = /hover|lightbox|superimposed_kittens/ end GEM REPOSITORY: www.pages << proc { fetch('/login') form = agent.mechanize = true dw.submit(form) fetch('/secret-page') } dw. Unused Selectors Gem: Deadweight # lib/tasks/deadweight.stylesheets = %w( /stylesheets/style.com/aanand/deadweight Wednesday.example.github. 2010 . June 9.username = 'username' form.rake require 'deadweight' Deadweight::RakeTask.first form.css ) dw.password = 'password' agent.com' dw.

com/photos/cheeseroc/2202100903/ Don’t write tests around markup if you don’t have to. TESTS http://www. 2010 .flickr. June 9. Wednesday.

http://www.flickr. TIDY Because rendered code is always slightly messy. June 9. 2010 .com/photos/muehlinghaus/3564021462/ Wednesday.

2010 ...w3.rb # above Rails::Initializer block require 'rack/tidy' # inside Rails::Initializer block config.sourceforge.org/users/webficient/middlewares/38-racktidy TIDY Info: www. Rack::Tidy sudo gem install rack-tidy config/environment.html Wednesday. Final delivery.use Rack::Tidy Rack::Tidy Info: coderack. June 9.middleware.org/People/Raggett/tidy/ tidy.net/docs/quickref.

flickr. 2010 .com/photos/chadmiller/145648847/ Do it for the cute baby animals. June 9. Wednesday.http://www.

2010 . Wednesday. Q&A Fire when ready. June 9.

SLIDES: THANKS! www.com/infoether/startups Wednesday.com/boboroshi/infoether-framework TWITTER: STARTUPS GEM: @boboroshi www.github. June 9.infoether.com/railsconf2010/ CSS STARTUP: * www. 2010 .github.