Monday, April 28, 2014

A Basic Star Rating Bar jQuery Widget

The first web-based rating system I remember using was provided by Netflix when picking movies to watch. I can remember inspecting the HTML to learn how they built it. At the time, it seemed like an amazing trick given the available browser technology. Today, a rating bar UI widget is pretty common place. Whether you build your own or pick from the pool of existing options depends on your needs. Interested in what was out there, I did some quick research to see what existed related to libraries I already work with like Bootstrap and jQuery UI. On the Bootstrap GitHub issue log, an external project was recommended in the discussion for those interesting in an implementation. I also found there's a plan to build this type of widget into jQuery UI and found a project that already provides such an implementation.

Looking through these projects, it became evident that they are a bit larger than I might really need. I was curious how little code I could write to make a very simple rating bar that would work in a variety of situations. If its small enough, it costs very little in the way of bandwidth and would be easy to extend and adapt to other use cases. The final product I built is about 120 lines of code (both JS and CSS) with comments and blank lines. Follow along through this post to see how I got there. Not interested in how I built it? Then scroll to the end for a jsFiddle demo and links to the final code.

Monday, April 21, 2014

Using CSS3 Transitions to Draw a User's Attention to Change

I've been pondering how to draw a user's attention to a specific area of the page for a little while. I have a application that displays a wealth of information on the screen and receives real-time updates over a Socket.IO connection. The data isn't sorted by recent activity and the user is not initiating the reload of the data so how do you guide a user's eye to something that is currently important? Momentarily highlighting the changed area in color may be a good way to approach the problem. However, I found that it was not always obvious, especially, when color was already being utilized in several other ways to highlight importance. What I really wanted was everything else to fade out a bit to single out the updated item and, to emphasize the change more, apply some kind of effect to that item (color, animation, etc).

As a simple demonstration of what I'm trying to achieve, the following example organizing several content boxes of information. Each item is selected randomly to receive an "update" which simply changes the text and resets the time-since-last-updated counter. A timer generates consistent events and initiates the updating logic:

Sunday, April 13, 2014

Newline Madness: Justified HTML Elements Revisited

A little while ago, I wrote about my fun trying to create evenly spaced, rotated labels. As I pointed out in the post, the evenly space portion was based on a perfectly justified grid technique I found. It solved part of my problem, however, I did find that IE gave me some problems unless I added text-justify: distributed along side the text-lign: justify in the styles. With those minor changes, everything worked fine in my development environment. However, once I tried packaging up my app for production, the solution stopped working.

A little background is necessary to understand what happened. The application has a pile of template HTML which I wanted to compress down as much as possible so I added the grunt htmlmin task to my build process so the extra white space and line breaks where removed from the markup. It turns out that this spacing trick relied on the invisible text nodes created by those line breaks and indentation I used to keep the markup readable during development. Once they weren't there, the content collapsed as if the justification was not even applied.

Sunday, April 6, 2014

HTML Positioning: The Curious Case of Centering the Unknown

It would seem like something as simple as centering an object perfectly, both horizontally and vertically, inside a container should be a basic capability of HTML/CSS. However, I've found that the less you know about your surroundings, the more difficult it gets to accomplish that goal. When you're trying to build something that is fluid and adapts to the available browser size, it becomes challenging to pull off such a simple feat. The best solution I've found that works in the most browsers is using a ghost pseudo-element to allow an element to vertically align inside its parent:

.parent-ghost {
  text-align: center;
  border: 3px solid #555;
  height: 300px;
  width: 70%;
}

.parent-ghost:before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
  margin-right: -0.25em; /* Adjusts for spacing */
}

.child-ghost {
  display: inline-block;
  vertical-align: middle;
  width: 20%;
  height: 20%;
  background-color: #f00;
}




Of course, this does not work in IE7 or older which means you either need to fallback to using tables or decide if the current market usage is actually worth the effort (As of February 2014, IE7 shows 0.0%).

Now, if you're willing to ignore 7% of the browser market, you can make things really simple by using the Flexbox Layout module. Although pretty recent, all modern browsers do support it. However, your IE users are going to have to use IE11 to take advantage of it:

.parent-flex {
  display: flex;
  height: 300px;
  width: 70%;
  border: 3px solid #555;
}

.child-flex {
  width: 20%;
  height: 20%;
  margin: auto;
  background-color: #f00;
}





That's a very simple example of how using Flexbox makes laying out content easier. If you haven't tinkered with it, take a look at the CSS-Tricks guide for an introduction. However, once you start using it, you may never want to go back to the old way. I've have a basic understanding of what features Flexbox offers. Since its been only recently implemented, it hasn't been a priority for me to start using it for all my layout problems. For now, I'll appreciate that the time will come when it will be in common use but will rely on the old bag-of-tricks to layout pages for a bit longer.

Now, my favorite trick to centering objects is to use a CSS3 Transform to translate the object back 50% of its height and width (for simplicity, I've left out the vendor prefix variations):

.parent-translate {
  overflow: hidden;
  height: 300px;
  width: 70%;
  border: 3px solid #555;
  position: relative;
}

.child-translate {
  position: absolute;
  width: 20%;
  height: 20%;
  background-color: #f00;

  top: 50%;
  left: 50%;

  transform: translateX(-50%) translateY(-50%);
  /* Split because IE10 won't honor the percentage in translate(-50%, -50%) */
}





This method is not supported in IE8, so according to the market stats, you'll lose 2.7% of your audience (well, they'll simply see a box with its top/left corner centered in the parent). However, the reason I tend to use this method is because I generally attach a transition on the element to animate it into position. Since its already absolutely positioned, I can animate the top property to slide it into view:

.slide {
  top: -50%;

  transition: top 1s;
}

.slide.in {
  top: 50%;
}


Attach a little JS to trigger the action:

   $( '#slide-in' ).click( function() { $( '.slide' ).addClass( 'in' ); } );
   $( '#slide-out' ).click( function() { $( '.slide' ).removeClass( 'in' ); } );




Now the transition won't work in IE9 so we've lost another 2% of our users. Again, its not a complete failure - the box still toggles into view - it just doesn't slide up or down.

Lately, I've come to the conclusion that the current features available in HTML5/CSS3 greatly ease the effort required to create great content and user experiences. I have a hard time justifying not leveraging these technologies because a small segment of the Internet is stuck in the past. I realize this is not usually the individual user's fault (corporate policy, etc). In the end, you have to pick what is suitable for your audience. I just prefer to attempt to nudge everyone forward or at least be ready for the eventual switch. Its nice to see that the browser is evolving to a better place that enables developers to spend less time positioning content and more time building it.