cott Cheng

Waterfall and Footnote

Popularized by Pinterest, waterfall layout is a smart invention because it could elegantly take up the entire window with flexible positioning. By default, waterfall doesn’t paginate; instead, “pages” are automatically loaded and appended as a user reaches the bottom of the page, providing a non-stop browsing experience, which, in itself, is nice.

So people start to mock it, as they always would, and some of these implementations left a page footer there, right below the waterfall. Predictably, the poor footer gets constantly “flushed” downwards every time I try to have a good look at it, and I can never reach it. (Here is a workaround: disconnect the Internet and the page will stop growing)

If some part of a webpage can never be read and clicked on under reasonably good network condition, what is the point of it being there at all? It gets especially annoying if that part is somewhat intriguing that people want to interact with.

I totally understand that footer is a default web element, but please think twice before going with traditions, especially when trying out something unprecedented. Don’t take rules for granted – they may be flawed, even fallacious. Think about why things are the way they are, and how they can be tweaked or redesigned to better fit a specific case. Question authorities; question everything.

This is my little complaint after 20 seconds of unsuccessful attempts to catch the contacts in the footer of Meishimeike.

Beauty of Loop

Loops are most commonly used to deal with arrays (e.g. finding the maximum number in an array of integers), or perform similar actions for a range of numbers or enumerables (e.g. calculating a Fibonacci number). If the problem space is dynamic (e.g. calculating the sum of 1 to n), loop is often the standard way of traversal (the alternative is recursion); otherwise, it contributes to DRY code by avoiding duplication (compared to an unraveled loop).

However, loop doesn’t easily come to mind when handling a fixed data set that you would have to hard-code anyway. For example, when writing a table of names and titles on a webpage (in Jade), the common approach is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
table
  tbody
    tr
      th Chairman
      td
        a(href='http://alice.com/', target='_blank') Alice
    tr
      th Recruiting
      td
        a(href='http://bob.com/', target='_blank') Bob
    tr
      th Marketing
      td
        a(href='http://chris.com/', target='_blank') Chris

We see the repetitive pattern of table rows, containing a data set that is not literally an array. Repetition is evil, so we should make an array out of the data and loop through it.

1
2
3
4
5
6
7
8
9
10
11
12
13
//- Turn the data into an array
- var people = []
- people[0] = {position: 'Chariman', name: 'Alice', link: 'http://alice.com/'}
- people[1] = {position: 'Recruiting', name: 'Bob', link: 'http://bob.com/'}
- people[2] = {position: 'Marketing', name: 'Chris', link: 'http://chris.com/'}

table
  tbody
    each person in people
      tr
        th= person.position
        td
          a(href='#{person.link}', target='_blank')= person.name

This way, we only have to define the format of each person once, which conforms to the DRY principle (of course, DRY principle is a lot deeper than creating loops):

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

The code becomes cleaner, more maintainable, and less error-prone. You could imagine how much benefit it could bring if there are 50 people in the list.

However, generalization comes at the cost of flexibility, which I’ve discussed a bit in a previous post. For example, if there are two Marketing people, and one of them doesn’t have a website, then the table should look like:

1
2
3
4
5
6
7
8
9
10
11
12
table
  tbody
    tr
      th Chairman
      td
        a(href='http://alice.com/', target='_blank') Alice
    tr
      th(rowspan='2') Marketing
      td Bob
    tr
      td
        a(href='http://chris.com/', target='_blank') Chris

And the loop solution would be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- var positions = []
- positions[0] = {position: 'Chairman', people: []}
- positions[0].people[0] = {name: 'Alice', link: 'http://alice.com/'}
- positions[1] = {position: 'Marketing', people: []}
- positions[1].people[0] = {name: 'Bob'}
- positions[1].people[1] = {name: 'Chris', link: 'http://chris.com/'}

mixin person(person)
  if person.link
    a(href='#{person.link}', target='_blank')= person.name
  else
    = person.name

table
  tbody
    each pos in positions
      tr
        th(rowspan='#{pos.people.length}')= pos.position
        td
          mixin person(pos.people[0])
      - for (var i = 1; i < pos.people.length; i++)
        tr
          td
            mixin person(pos.people[i])

So it’s always a trade-off. If there are not many items to operate on and the operation for each item is simple (or in some cases, wildly different from each other), perhaps loop isn’t the best way out. Despite of that, I’d advocate applying loops whenever possible, because they can make your code a lot more beautiful, and you’ll find your life so much easier because of them.

Bottom line is, don’t make a WET cart :)

Respond to Me

I’ve always been a big fan of UI responsiveness, and I believe it’s one of the indispensable features of a successful UI. I’m not talking about the lightning speed that Instagram has achieved, but that the UI should provide instantaneous feedback to every meaningful action the user performs – respond to him.

Hover effect is a good example of responsiveness. On this website, links turn orange when you move your mouse over them, assuring you that “you are pointing to the link, click ahead”.

Responsiveness is more crucial for user actions to which the handler would take some time to “return”. A UI does not have to be lightning fast (though it’s definitely good to be). In fact, the processing speed is sometimes out of the developers’ control, e.g. if remote API calls are involved. A user can wait, but the UI has to explicitly tell the user that “your request is being processed, please wait”. Otherwise, the user would wonder: did I really click the button? Should I keep waiting, or should I repeat the click? What is going on behind the screen? Put another way, the UI should be upfront about what it is doing, so that the user doesn’t have to guess.

Pocket over Readability

I prefer Pocket over Readability, because Pocket’s Chrome extension is more responsive than its competitor. When I press Ctrl+Shift+P (Pocket’s shortcut), it instantly pops up a banner that reads “Saving to Pocket”, and after a brief wait, the text changes to “Page saved”. When I hit Shift+` (Readability’s shortcut), however, I’ll have to wait several seconds before anything happens, which I find extremely annoying.

My Practices

I’ve been striving to offer best responsiveness in the UIs I build.

In Save2Drive, after user clicks “Save to Drive”, I first pop up a desktop notification that says “Saving link to Google Drive”:

Then I send the HTTP request. After the callback fires, it either changes to “Link saved to Google Drive”:

Or “Failed to save link to Google Drive”:

Renren Album Downloader is a bit more complicated. After the user asks to download an album, the extension will follow these steps, all with explicit real-time status update (UI update happens before the corresponding code runs):

  1. Look for photo URLs in the HTML:

  2. Fetch the photos:

  3. Put everything into a zip:

  4. Finally, tell user it’s done:

Rule of thumb: if you have the user waiting, tell him he’s waiting, and preferably tell him what he’s waiting for.

iPad Is Best Naked

If your iPad wears a screen protector like mine used to, I suggest you rip it off right now. I took the film off three days ago, and the screen has become way more gorgeous than what I had been looking at for an entire summer – the peerless retina display is finally rescued from being completely obscured. And the screen feels much more smooth and sleek too!

Four months ago, before I even began using my new iPad, I installed a matte screen protector because I hate scratches. I still do, but I’ve just learned that the iPad screen itself is in fact highly scratch resistant. If used at home, the screen is unlikely to be threatened at all. However, if often carried around in a bag like mine is, it could use some protection. Smart cover is an option, but I don’t enjoy holding the device with extraneous plastic. So I got a stylish case from SkinAt.

I’m so happy with the discovery and the change.

Pulling Anchor Targets Out of the Fixed Header

I’ve been using Bootstrap in my latest website (if you haven’t tried Bootstrap, you really should! It makes lots of things worlds easier, and has taught me a handful of good practices), where I used a fix-positioned navigation header, one that always stays at the top of the window. In longer pages, I used a secondary in-page navigation.

One particular issue I encountered is that when I click on one of those in-page navs, a big portion of that section will be covered by the header! In case you don’t know what I’m talking about – instead of looking like this as it should:

It looked like this:

See? The “before the weekend” heading goes beneath the nav bar.

So I went to the Bootstrap site, where in-page nav is pervasively used, seeking the “official” solution. A padding-top: 30px; did the trick for them.

But this is not a perfect fix for me. The Bootstrap header is merely 40px high, whereas mine is 87px (main nav and sub nav stacked). 30px between sections is acceptable, 80px isn’t.

To solve my problem, while applying a big padding-top, I have to keep the spacing between sections from going too wide – negative margin-top immediately came to mind. So here comes my final solution that pulls the content from behind the nav bar:

My final solution
1
2
3
4
section {
  padding-top: 87px;
  margin-top: -87px;
}

See it in action in this fiddle.

P.S. As I was trying to find out what others have to say on this topic on Stack Overflow, an answer took me to Nicolas Gallagher’s master list of solutions to this very problem, with analyses on each of his five methods. Great work!

P.P.S. Pardon my ignorance, but what is the official terminology of the “in-page link” I’ve talked about in this post? “Jump link”? I found a few uses of “jump link” after Googling, but honestly I’ve never heard of this term before, and it doesn’t look very much like the way it’s called to me.