Category: Front end

CSS Specificity – Survival of the fittest

Most of us have learnt CSS by trial & error & that includes me, it only takes minor success to develop strong interest in what we work on daily basis. However, having said that I strongly believe just know-how of any technology or concept does not cut it. One should make an effort to find out the logic behind the things that set our trial & error standards.

There’s one that I am absolutely in love with & i.e. CSS Specificity. We all have spent countless hours trying to override previously written CSS declarations with the new ones because the deadlines are catching up & we are moreover frustrated because we don’t know how does CSS decides which rule takes precedence over which.

TODAY I’LL HELP YOU ALL KISS/KILL THIS MONSTER!

Consider following 2 CSS declarations:

p{
color:red; value=1

} ulp { 

color:red; value=2

}

It is quite clear to all of us that the latter declaration will takes precedence & win since from the look of it appears MORE SPECIFIC. It is after all, about survival of the fittest.

What do those values mean by the way? They are specificity weightage & that is the deciding factor when it comes to which rule wins! Each selector has predefined value & with the help of a simple cheat sheet we can all safely determine what will work & what won’t.

The table is below:

Selector

Specificity value

Example

Reason

* (Universal Selector)

0

*

Not so specific since it targets all elements

element, pseudo element

1

div,span :first-line, :first-letter, :first-child, :last-child

More specific since it targets very specific elements

class,
pseudo class, attribute selector

10

.anyCssClass :hover,:link, :visited, a[href]

Only targets elements when classes & attributes specified

# (Identifier)

100

#myId

this is the most specific since this can occur only once in the page

inline style (style=””)

1000

<divstyle=”float left;”></div>

This is very close to the element you are trying to style & hence carries more weightage

Time for some action:

ul ol+li (1+1+1)=3

Final value of the declaration above is 3. How? Let me explain

  1. ul is element. Hence 1
  2. ol is also an element. Hence 1
  3. li is obviously an element & yes, 1

We add it all up & get 3. Wasn’t that easy?

Now try & find specificity weightage for following declarations:

    1. li:first-line
    2. h1+*[rel=up]
    3. ul ol li.red
    4. li.red.level
    5. .sith
    6. div p .sith
    7. #sith
    8. body #darkside .sith p

Next time, you are stuck with messy CSS & trying to find your way out, bring up this table & start calculating. You surely would have written stronger selector in no time!

Have more questions, shoot those to us.

Endless page using jQuery and will_paginate

We all know that rendering all the data at once hampers the application’s performance and for that purpose we use pagination so that we can render sets of data with each page. But sometimes for a better user experience, wouldn’t it be a good idea that once the user is finished with a set of data the next set of data is rendered and appended after that, rather that waiting for the user to click the next link for the remaining data and so this is were we implement endless page.

Below is the code that i have used for implementing endless page in my application using jquery and the will_paginate plugin.

1. First make sure that you have will_paginate gem installed.

gem 'will_paginate', '~> 3.0' (Include this gem inside your gemfile)

and run bundle command to install this gem.

2. Inside the Controller

def index
  per_page = 40
  page = params[:page]
  @sorting = sorting?
  if @sorting
    per_page *= (page || 1).to_i
    page = 1
  end
  @users = User.paginate :page => page,
  :per_page => per_page,
  :include => [:profile],
  :order => sort_order.blank? ? 'created_at desc' : sort_order
end

Make sure to call the paginate method

3. The Javascript

jQuery(function() {
  $('#loading').hide();
  if ($('.pagination').length) {
    $('#endless_paginate').prepend('Show more');
    return $('#add_results').click(function() {
      var url;
      url = $('.pagination .next_page').attr('href');
      $('#endless_paginate').show();
      if (url) {
        $('#endless_paginate').hide();
        $('#loading').show();
        return $.getScript(url);
      }
    });
  }
});

Here we check first that if we have a pagination element present , then we prepend the endless_paginate div with a Show more link. Then we declare a url that will have the pagination element and we call the next page element and fetch the url attribute. This pagination element is available to us through the will_paginate gem. Next if the url is present then we would fetch more results with the getScript method to which we would pass the url attribute that would fire the index action and return javascript once executed.

4. Inside index.js.erb

$('#list_header').html("<%= escape_javascript render("list_headers") %>");
$("#list_of_users table tbody")
.append("<%= escape_javascript render("list") %>");
$('.pagination').replaceWith
("<%= escape_javascript will_paginate(@users) %>");
$('#loading').hide();
if($('.pagination').find('span.disabled').length > 0){
  $('#endless_paginate').hide();
}
else{
  $('#endless_paginate').show();
}
$('#pagenone').html("<%= escape_javascript will_paginate(@users) %>");

Here inside the index.js we would append the (list_of_users) div with the rendered list partial that renders the @users. secondly we have to make sure to update the pagination link which we can do with calling the replaceWith on the pagination element and replace it with the will_paginate and pass it @users.
The rest of code is responsible for hiding and showing elements.

5. Changes in the views

Inside index.html.haml

#list_of_users
  %table{:cellpadding => "0", :cellspacing => "0"
   , :width => "100%", :id => "users"}
    %thead#list_header
      = render 'list_headers'
    %tbody#list
      = render 'list'
#loading{:class => 'paddleft'}
  %img{:src => "/images/loading.gif"}/
#endless_paginate{:class => 'appendpaginate'}
#pagenone{:class => 'nopagination'}
  = will_paginate @users

Inside _list_headers.html.haml

%tr#list_header
  %th Image
  %th Screen Name
  %th Name
  %th Last Login
  %th Site
  %th Logins

Inside _list.html.haml

  = render @users

Inside _user.html.haml

%tr{:id => "user_#{user.id}"}
  %td
    - if !user.photos.last.nil?
      = link_to (image_tag(user.photos.last.photo.thumb.url, 
        :alt => 'No Image', :class =>  "sizing"),
        user.photos.last.photo.large.url , :class => "preview")
    - else
      = image_tag("/images/no_image.jpg", :style => "sizing")
  %td= user.profile.screen_name
  %td
    %span.working
      = link_to user.full_name, edit_user_path(user)
  %td= user.last_sign_in_at ? format_date(user.last_sign_in_at) : "N/A"
  %td= user.site.name
  %td.logins.center= user.sign_in_count.nil? ? 0 : user.sign_in_count

User interface design is where s.u.c.c.e.s.s begins

Inspired from article by – Whitney Hess

http://whitneyhess.com

Every one knows how important user interface design is. But often you miss out on focusing on it. Below is a quick rundown on practically thinking about UX.

This is how our Rails development team thinks sees it. Let us know your thoughts.

UserInterfaceDesignIsWhereSuccessBegins

Wondering why a Ruby on Rails development team is so passionate about UX? We being Ruby developers, this is certainly not our forte, nor we try to sell it as as service. But we do realize how important it is and in order to make our clients succesful. Hence we are advocating for it.

 

Making the Addthis widget in ajax response even in jQuery dialog

It is known that the addthis widget does not work when loaded in a ajax call. In order to make it work, you have to reinitialize or reload the addthis_widget.js file. Below is how you could do it:

In your application.js file or the parent page that is making the ajax call, add the below code:

 AddthisInitializer.prototype.initializeAddThis = function() {

var script = 'http://s7.addthis.com/js/xxx/addthis_widget.js#domready=1'; 
 if ( window.addthis ) { 
 window.addthis = null; 
 } $.getScript( script ); 
}
Then to use it in the HTML that is rendered back in your ajax call, you want to render 
the add this icons. Use it like below:
<a addthis:url='http://wherever_you_want_to_go.com' 
href="javascript:void(0)" class="addthis_button_facebook">
 <img src="http://facebook_logo.gif"/>
</a>
<a addthis:url='http://wherever_you_want_to_go.com' 
href="javascript:void(0)" "addthis_button_twitter"> <
img src="http://twitter_logo.gif"/> </a>
<a addthis:url='http://wherever_you_want_to_go.com' 
href="javascript:void(0)" class="addthis_button_tumblr">
 <img src="http://tumblr_logo.gif"/>
</a> 
... and so on.
<script type="text/javascript"> 
 var initializer = new AddThisInitializer();
 $(document).ready( function() {
 initializer.initializeAddThis(); 
 } );
</script>

Progressive Enhancement 101

Progressive enhancement in real life.

We all know about ‘progressive enhancement’ except the perhaps the term itself. The concept is quite simple. In real life we define boundaries of various shades of gray.

For example at school we may group our fellow students based on their studiousness and modify our interaction with them that suits our needs. We may be nicer to the math whiz because we’d like him to help us out with our homework. We might not be nice to the guy that looks and feels useless to our interests.

Granted the above example is kinda pointless because in real life it’s kinda complicated because many interests interact and it all boils down to the net worth of our needs. Say for example the math whiz and you might be in rival groups or you and him might be having a crush on the same girl. It might also turn out that the useless looking guy is actually very rich.

Yet another day to day example.

Progressive enhancement from the TV industry.
Progressive enhancement from the TV industry.

TVs come in various sizes, resolutions, aspect ratios and makes. Professional quality video content has to convey their core message spanning this hodgepodge of end user devices. One way to do this would be to make videos for each type of display. But thankfully, there’s an easier, better and much simpler way… Enter safe areas!

If you refer the diagram above, you’ll see three superimposed black squared. These are the common three TV screen resolutions. You can also see a green square and a red square. These are the ‘action safe area’ and the ‘graphics safe area’ respectively.

Any action in the movie worth seeing must come inside the green square and any text worth seeing must come inside the red square. This implies that text (what is generally meant by ‘graphics’) is more of an important thing that must be conveyed in its entirety than some action happening in the movie; as most of the action will also be inside the graphics safe area anyways.

To account for botched up displays, the graphics safe area is even smaller than the lowest resolution!.

Once, the basics are covered, more value is added to the users that own expensive devices by the extra ‘wow’ content that frames the core message. Consequence being that everybody is happy. Users on low end devices get what they want, users on high end devices get what they want, and the content producers get what they want too. The above constraint helped the content producer progressively enhance the user experience starting form the lowest spec target device to whizzbang 3D HDTV! A teeny weeny little constraint goes a long way.. doesn’t it?

Moving on to the web..

The web as complicated as it is isn’t thankfully as complicated as real life. It was much less complicated say 10 years ago when web pages were generally meant to be viewed -I’m stopping at that and not going into the not so insignificant details of the visual domain such as the array of visual user agents that need to be supported and the exponential complexities they entail.

Accessibility (support for visually impaired people), support for bots (search engine, mashup consumers) etc were ignored as they were insignificant. Most of these grand goals (except perhaps SEO) are still insignificant

Before you let the dogs loose on me, let me assure you that constraints are more awesome than that.

General purpose web development constraints.

  • REST architecture style
  • Semantic HTML
  • Unobtrusive JavaScript
  • Pure CSS styling

Of these, the most important is REST. REST architectural style simply means that URLs are addresses to resources, that you can operate on these resources and get a representation of resources that may have addresses to other resources. So an example from real life would be say, the analogue of the URL would be the physical address to idyllic-software and an action could be decorate and a representation would be a photograph of the decorated interior and the addresses from that resource to the other would be what the person in charge (application designer) would allow you to further mess around with.

Two links from the application state of decorated building to possible other application states would be, water the garden and mop the floor. On the web URLs are constrained by their syntax and HTTP constraints the actions to GET, HEAD, POST, PUT, DELETE. Browsers further constrain that set to just GET and POST

Once you have REST, you can use a web browser to consume it as it is using semantic HTML/XHTML as the data format, styling it with pure CSS for pleasing eye candy, consume it as JSON, XML, XHTML from a pure JavaScript browser application. Or let some bot consume it as pure data. Makes life easier for everybody.

What’s on the table for the average Joe developer.

  • Back end developers worry only about the real problem. (how to get and operate on the data underlying the resource).
  • SEO analysts, Front end developers, liaise on the MarkUp.
  • Front end developers write full applications or add just enough JavaScript to spice up the UX. These consume the RESTful service.
  • Bots can negotiate for structured content with the Server (content negotiation) as it is now easier for the backend devs to push out yet another format which will only be a few lines of code to say serialize an object to JSON or XML. Or else bots can consume straight semantic XHTML/HTML.

Example

Say you’ve a resource located at http://example.com/foo/address. The data for which you get from some data source into say a Ruby Hash like the following:

address = {f_name: 'foo', l_name: 'bar', address: 'one two three', phone: 12345678, email: 'foo@bar.com'}

You mark it up using semantic HTML like say

 <dl class='address'>
  <dd class='first_name'>
    First name
  </dd>
  <dt class='first_name'>
    foo
  </dt>
  <dd class='last_name'>
    Last name
  </dd>
  <dt class='last_name'>
    bar
  </dt>
  <dd class='address'>
    Address
  </dd>
  <dt class='address'>
    one two three
  </dt>
  <dd class='phone'>
    Phone
  </dd>
  <dt class='phone'>
    12345678
  </dt>
  <dd class='email'>
    Email
  </dd>
  <dt class='email'>
    foo@bar.com
  </dt>
</dl>

Which with the following CSS

dl.address {
  background:cornsilk;
  overflow:hidden;
  padding:5px;
}

dl.address > dt,dl.address > dd {
  float:left;
  width:50%;
  background:honeydew;
}

Renders as

First name
foo
Last name
bar
Address
one two three
Phone
12345678

Summary

  • Design your application around the URL, actions on the URL and the links to other resources from the representation of the URL.
  • Try viewing the document as data. Use microformats.
  • Stand back and try adding static eye candy using pure CSS. Stop viewing HTML from a visual design perspective.
  • Add JavaScript to enhance UX. Application should work without the JavaScript anyways.

Coffee-script with Rails 3.x: Getting started

Why should I learn Coffee-Script?

  1. Rails 3.1 is shipping with coffee script.
  2. It adds a fine syntactic sugar to java script making your code even more beautiful and terse.
  3. Easy to learn if you already are working on scripting languages such as ruby or php.
  4. If you always feared wiring inheritance in javascript, coffee-script will make it super easy for you.
  5. Being compiled to java script itself, it integrates seamlessly with your favorite javascript libraries like jquery or prototype or moo tools or anything else.

I am not going to blog about coffee scripting as it is already very well documented. However, it might help to lay down steps to quickly integrate it in your rails application. So here is the 10 minutes drill to it.

Introducing Coffee-Script in you rails 3 application

    1. Add the necessary gems to your gemfile
      gem 'coffee-script'
      gem 'barista' #It will auto compile your .coffee files into .js files.
      gem 'therubyracer', :require => nil #If you do not have nodesjs installed. Install node.js
      gem 'json'
    2. Configure barista for your application.
      rails generate barista:install
    3. Know that you have a config/initializers/barista_config.rb file for customization. You do not need to touch it yet.
    4. Create app/coffeescripts folder
    5. Add in your first coffee script file in there named welcome.coffee with the below code:
      $(document).ready ->
      alert("Welcome to the world of coffee scripts");
    6. Copy coffee-scripts.js to your public/javascript from this link.
    7. Add coffee-script.js and welcome to your javascript includes tag
    8. Add below code in one of your erb files or application layout to see inline coffee script:
      <script type="text/coffeescript">
      firstFunction = ->
      alert('I am inline function')
      firstFunction();
      </script>
    9. Start your rails app and goto http://localhost:3000
    10. Know that barista will start logging in your console window.
    11. You can also use jquery with coffee-script syntax
      <div id="effects">Test to see if it works with jQuery</div>
      <script type="text/coffeescript">
      $(document).ready ->
      $('#effects').fadeOut('slow', ->
      $('#effects').fadeIn('slow')
      )
      </script>

Enjoy Coffee Scripting. Try it!

Subscribe To Our Blog

Get access to proven marketing ideas, latest trends and best practices.

Next up home

Contact

Lets build cool stuff

Share your contact information & we will get in touch!

I want (Tell us more about your dream project)