Archive

Posts Tagged ‘UI’

Chrome’s sound indicator – a welcomed innovation for lessening embarrasment

February 13, 2014 1 comment

Which tab is playing music? It's easy to tell now

I sat at my desk early in the morning while the office was mostly empty. A coworker arrived, said hello and sat down to work. She put on her headphones and started blasting music. The only problem? Her headphones were unplugged and the music was playing for the whole office to hear.

Accidental noise like this is very embarrassing. I welcome all innovations that make this less likely to occur. I was blown away when I used an iPod for the first time and unplugged the headphones. Unlike the CD players I had used before, the music paused. With the iPod it didn’t make sense to continue to play music without the headphones plugged in, since there was no internal speaker.

I am happy that both iPhone and Android adopted this convention as well. You’re much less likely to embarrass yourself if the sound stops as soon as headphones are removed rather than automatically switching over to the external speakers. I wish that laptops did the same, but alas.

I live most of my work day in a browser. I often end up with a whole slew of tabs. Suddenly I hear some sort of noise – one of the dozen pages I have open is blaring an ad. I usually have to search each tab one by one to try to find the culprit. Chrome recently launched a new feature to visually distinguish which tab is making noise. This is a brilliant innovation, and one I welcome in my quest not to make a fool out of myself in front of others.

Disclaimer: I work at Google. The opinions expressed are my own and do not represent that of my employer.

Advertisements
Categories: iPod, UI Tags: , , , , , ,

OpenTable’s Violation of the Principle of Least Astonishment

September 30, 2013 Leave a comment

I was taking an OpenTable survey about a recent dining experience, when I noticed a poor piece of user interface design.

Screen Shot 2013-09-28 at 9.31.50 AM

The last question asks about the noise of the restaurant.

Quiet
Quiet – reasonable first choice.

Moderate
Moderate – yup, still with you.

Energetic

Energetic! Yes. What could be louder than energetic?

Do not recall

Do not recall.

This is a rather strange (and bad) choice for an option, as it doesn’t follow the convention of the other controls on the page (or that I’ve ever seen on any survey ever). I would wager that more than half of the entries in their database they get for the “Do not recall” entry were intended to be “extremely loud” but the survey participant didn’t even stop to see the text change but instead assumed that the largest value would correspond with the loudest entry.

This design is a clear violation of the Principle of Least Astonishment, since it violates the strong convention that on a survey, lower is to the left and higher is to the right. Furthermore, a ‘do not recall’ answer should either be inferred from not answering the question, or by an alternate control (e.g. a checkbox) that would disable the control with the noise level readings.

Kindle Paperwhite – Touching is good

November 6, 2012 1 comment

When I was in college, one of the students had the original version of the Kindle. It was big, clunky, and slow, but I instantly saw its potential. I’ve since owned three copies of the gray Kindle with keyboard (don’t ask), and that was a huge advance in terms of form factor, speed, and resolution.

I recently bought a Paperwhite to replace my most recently broken Kindle. Here are my initial thoughts after having used it for about 2 weeks.

Video clip of pressing to define

Video clip of dragging to select text

 

Good

  • Refresh rate is noticeably faster
  • Resolution is better – text is very crisp
  • Getting definitions of a word is much easier – takes one long press on the word rather than navigating through the whole page with the directional pad
  • Extremely small; fits easily into a jacket pocket
  • Light works very well and does not strain my eyes
  • UI has improved – navigating through books stored on the cloud vs on the device is very straightforward
  • Highlighting is very intuitive and easy to do
  • High quality virtual keyboard – very responsive
  • All the games I tried have been updated to support virtual keyboard – including the New York Times crossword puzzles
  • Much easier to find the books to borrow in this version – use the same unified Kindle store to search, then if it’s available, will show up as a download/borrow option
  • Nice option to see how much time is left in the chapter vs book – tap in lower left corner or access from the menu
  • Really great walkthrough of the different tap zones and what they do when you first turn on the device

Bad

  • For both the highlight and define gesture, you need to hold your finger on the start word for a fraction of a second longer than I’d like. If you move your finger or remove it before that time, you’ll turn the page. I’ve accidentally turned the page a few times.
  • Since the only way to turn the page is by tapping the screen, it’s easy to accidentally click on a link. When the link is external, it’s easy to undo – hit back on the browser. If it’s internal, to a later chapter, you get dumped later in the book with no way to get back. This is extremely confusing and disorienting. If you only read novels, this is a non-issue, but for tech books it can be a problem.

Ugly

  • Light is uneven at the bottom; more evident in a dark room

Conclusion

This device is amazing, and any negatives I’ve highlighted are far outweighed by the positives. Everyone I’ve shown it to has loved it, and even those who were concerned about a touch screen on an e-reader have appreciated its responsiveness and UI.

This is by far the best e-reader I’ve ever used. Here’s hoping I have better luck with this version than the last three.

Categories: Uncategorized Tags: , , , ,

Wind Map – a visualization to make Tufte proud

June 9, 2012 2 comments

Wind map picture

Edward Tufte is a noted proponent of designing data rich visualizations. His books, including the seminal The Visual Display of Quantitative Information have influenced countless designers and engineers. When I first saw Fernanda Viégas and Martin Wattenberg’s Wind map project via Michael Kleber’s Google+ post, I immediately became entranced with it. After studying it for some time, I feel that the designers must have been intimately familiar with Tufte’s work. Let us examine how this triumph of data visualization succeeds.

Minimalist and data dense

Tufte describes the data density of charts based on the amount of information conveyed per measure of area. There are two ways of increasing data density – increasing the amount of information conveyed, and decreasing the amount of non-essential pixels in the image.

No chart junk

You’ll immediately notice what’s not in the image – there’s no compass rose, no latitude or longitude lines, or any other grid lines separating the map from the rest of the page. There aren’t even dividing lines between the states. It isn’t a map at all about political boundaries, so this extra information would only detract from the data being conveyed.

More info

This map conveys two variables, wind speed and wind direction, for thousands of points across the United States. A chart conveying the same information would take far more space and the viewer would have no way of seeing the patterns that exist.

Does not abuse color

In the hands of less restrained designers, this map would be awash in color. You see this often in weather maps and elevation maps, as illustrated below:

Snowfall example
Egregious elevation map
Egregious elevation map 2

The problem is that it is difficult to place colors in a meaningful order quickly. Yes, there is the standard ROYGBIV color ordering of the rainbow, but it’s difficult to apply quickly. Quick – what’s ‘bigger’ – orange or mauve? How about pink or green? Yellow or purple?. It is much easier to compare colors based on their saturation or intensity rather than hue. Color is great for categorical differences, but not so great for conveying quantitative information. Stephen Few sums it up nicely in his great PDF “Practical Rules for Using Color in Charts

When using color to encode a sequential range of quantitative values, stick with a single hue (or a small set of closely related hues) and vary intensity from pale colors for low values to increasingly darker and brighter colors for high values

The designers uses five shades of gray, each of which is distinguishable from the others, rather than a rainbow of colors. Five options is a nice tradeoff between granularity and ease of telling the shades apart.

Excellent use of the medium

In a print medium, the shades of gray would have had to suffice to illustrate how fast the wind was moving. In this medium, the designers used animation to illustrate the speed and direction of the wind in a truly mesmerizing way.

Conclusion

This visualization does a lot of things right. In particular, it uses a great deal of restraint in conveying the information. Unlike some of the other examples I showed, it does not have extra chart junk wasting space, it does not abuse color to try to convey quantitative information, and it is absolutely aesthetically pleasing.

Glazed Lists – an essential Java library for lists and tables

May 2, 2012 9 comments

Swing is the built in toolkit for creating user interfaces for Java programs. While these types of standalone desktop applications are becoming less prevalent, perhaps due to increasing functionality of webapps, there are still some industries which are highly reliant on them. If you find yourself creating a Java desktop application, you will probably have to learn Swing, and you will also probably have to learn to display information to the user in list or table form. In standard Java Swing applications, it is difficult, or at least annoying, to do the following three tasks:

  1. Displaying domain specific models
  2. Filtering
  3. Sorting

Glazed Lists is an open source project that makes all three of these tasks trivial. Its primary author, Jesse Wilson, is a current Google employee. Let’s examine each of these aspects in turn.

Provides a simplified API for representing objects within a JTable

Swing uses the Model View Controller paradigm throughout. Thus the table or list merely presents a view for an underlying model data structure. Part of your job in displaying data in a Swing table is to define the TableModel implementation which provides the data for the JTable to display.

Swing provides an AbstractTableModel that does most of the work for you, requiring you only to implement the following methods:

public int getRowCount();
public int getColumnCount();
public Object getValueAt(int row, int column);

Here’s a simple domain model object we might want to visualize in a table:

public class Person {
    int age;
    String name;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() { return age; }

    public String getName() { return name; }
}

The logical way of doing that would be two have two columns, one for the age, one for the name. Let’s make a table model for this case:

public class PersonTableModel extends AbstractTableModel {
    private static final String[] columns = {"Name", "Age"};
    private final List people;

    public PersonTableModel(List people) {
        // Make a defensive copy
        this.people = new ArrayList(people);
    }

    public int getRowCount() {
        return people.size();
    }
    public int getColumnCount() {
        return columns.length;
    }
    public Object getValueAt(int row, int column) {
        Person p = people.get(row);
        if (column == 0) {
            return p.getName();
        } else {
            return p.getAge();
        }
    }
}

This certainly works, but it requires a fair bit of boilerplate. Furthermore, the code above does not provide any way of modifying the list of people after it is copied by the TableModel.

Glazed Lists simplifies your life by treating the table not as an arbitrary two dimensional grid, but instead as a collection of rows, where the rows are kept in sync with changes to the domain models that they represent. All you have to do is define how a row is laid out, and Glazed Lists takes care of the rest.

The interface you need to use in order to define how the table looks and which aspects of your model objects are exposed is called [TableFormat][].

The interface is as follows:

  • int getColumnCount() – The number of columns to display.
  • String getColumnName(int column) – Gets the title of the specified column.
  • Object getColumnValue(E baseObject, int column) – Gets the value of the specified field for the specified object.

This should remind you of the TableModel interface presented previously, but note how the getColumnValue method is different – rather than getting a row and column, and forcing you to look up the object corresponding to that row, you are provided the object directly.

Here is a TableFormat which allows Person objects to be easily visible in a JTable:

public class PersonTableFormat implements TableFormat {

    String[] columnNames = {"Name", "Age"};
    private static final int NAME_INDEX = 0;
    private static final int AGE_INDEX = 1;

    public int getColumnCount() { return columnNames.length; }

    public String getColumnName(int column) { return columnNames[i]; }

    public Object getColumnValue(Person baseObject, int column) {
        switch (column) {
            case NAME_INDEX:
                return baseObject.getName();
            case AGE_INDEX:
                return baseObject.getAge();
            default:
                throw new IllegalArgumentException("Expected column 0 or 1, got " + column);
        }
    }
}

While this isn’t too hard to write, it’s still a lot of boilerplate (and not significantly different from the previous example). Glazed Lists makes it even easier than this. The entire class definition above can be replaced with three lines:

TableFormat personTableFormat = GlazedLists.tableFormat(Person.class,
    // Names of the properties to fetch
    new String[] {"name","age"},
    // Names for the columns
    new String[] {"Name", "Age"});

What’s this doing? And how can it do all that I had previously in one line of code? Well, it requires and takes advantage of JavaBeans naming convention. The static function uses reflection to find the methods mapping to properties named “name” and “age”. In this case, it looks for two methods, getName() and getAge(), both of which it finds. (If I didn’t name my methods appropriately, I would get a runtime exception). The second array defines the strings that should be used to identify the corresponding entry in the properties array. In other words, element 0 in the names column is used to identify the property name at index 0.

This TableFormat class alone is insufficient to display data in a table. To do that, you need a class which fulfills the TableModel interface I described previously. Fortunately, Glazed Lists makes this easy.

The fundamental building block of Glazed Lists is the EventList class. It is similar to the ArrayList class in Java, except that it has support for observers. If you’re not familiar with the Observer/Observable design pattern, it allows objects (observers) to register themselves and receive notifications whenever a different object (the observable) is changed. For instance, when a new item is added to the EventList, the UI element representing it on screen automatically refreshes itself.

The EventTableModel class fulfills the TableModel interface, making use of the EventList and TableFormat we described earlier. The EventList is the data provider, and the TableFormat determines how to extract the data from the EventList and display it in the table.

EventList people = new BasicEventList();
// Add all the elements
for (Person p : getPeople()) {
    personList.add(p);
}
TableFormat personTableFormat = GlazedLists.tableFormat(Person.class,
    // Names of the properties to fetch
    new String[] {"name","age"},
    // Names for the columns
    new String[] {"Name", "Age"});
EventTableModel tableModel = new EventTableModel(people, personTableFormat);
JTable table = new JTable(tableModel);
// Any modifications to the ‘people’ list is automatically reflected in the table

Provides a simplified means of filtering a table or list

Perhaps one of the most important features of any interactive table is the ability to filter out extraneous information. Glazed Lists makes this possible by chaining together EventList transformations; these transformations provide a different view of the underlying data. When the original model is modified, the filtered views automatically pick up the changes and update accordingly.

Say we want to provide the ability to filter the list based on people’s names. We will add a listener to a text field which listens for changes (new letters typed or deleted), and filters the list in real time. Once we have an EventList of some sort, it is easy to create a new “view” of that same list, filtering out entries you don’t want to see. You do this by wrapping the list in a FilterList, and then assigning some sort of filter criterion. Let’s start simple with a filtered list which only shows those users whose names start with the letter ‘A’.

EventList personList = new BasicEventList();
personList.add(new Person("Anthony Hopkins", 74));
personList.add(new Person("Barack Obama", 50));
personList.add(new Person("American McGee", 39));

Matcher personFilter = new Matcher() {
    public boolean matches(Person p) {
        return p.getName().startsWith("A");
    }
};
// Create a filtered list
FilterList filteredList = new FilterList(personList, personFilter);
// Displaying the people in a list as opposed to a table; could also create EventTableModel
// as in the last example.
EventListModel filteredListModel = new EventListModel(personList)
JList list = new JList(filteredListModel);
// At this point, shows Anthony Hopkins and American McGee

The filter I’ve defined above is static – once it’s instantiated, its filter condition never changes. Glazed Lists supports dynamic filters as well, through the MatcherEditor interface. We will see how to use a MatcherEditor instance for a text field, but first we need to tell Glazed Lists which strings to use when filtering for a given object. We do this with the TextFilterator interface.

Picture illustrating a FilterList which accepts only those people whose name starts with 'A'

 

public class PersonTextFilterator imlements TextFilterator {
    // Slightly strange interface, but done for efficiency reasons
    public getFilterStrings(List baseList, Person element) {
        baseList.add(element.getName());
        // Allow users to filter by age as well
        baseList.add(String.valueOf(element.getAge()));
    }
}

The MatcherEditor class to use in our case is TextComponentMatcherEditor. We provide it with the text field that it will use as the filter source, as well as an instance of the PersonTextFilterator class we just defined.

EventList personList = new BasicEventList();
personList.add(new Person("Anthony Hopkins", 74));
personList.add(new Person("Barack Obama", 50));
personList.add(new Person("American McGee", 39));

JTextField filterTextField = new JTextField();
// Add the text field to the UI - add to a JPanel

// Hook the text field up to a filter list
MatcherEditor filter = new TextComponentMatcherEditor(filterTextField, new PersonTextFilterator());

// Create a filtered list
FilterList filteredList = new FilterList(personList, filter);
EventListModel filteredListModel = new EventListModel(filteredList)
JList list = new JList(filteredListModel);
// List automatically updates in response to typing in the text field

Each transformed EventList is itself an EventList, meaning it can also be used as the basis of an EventListModel or EventTableModel. This chaining capability is extremely powerful.

Provides sorting capabilities

Finally, Glazed Lists makes it extremely easy to implement rich sorting capabilities in your tables or lists.

As we saw in the last example, it is possible to wrap a given EventList to provide a different view. In this case, we will have a sorted view of the data, which automatically updates whenever the underlying data changes.

To create the SortedList, you need to make your domain object implement Comparable, or create a Comparator. For instance,

public class PersonNameComparator implements Comparator {
    public int compare(Person p1, Person p2) {
        return p1.getName().compareTo(p2.getName());
    }
}
EventList personList = new BasicEventList();
personList.add(new Person("Anthony Hopkins", 74));
personList.add(new Person("Barack Obama", 50));
personList.add(new Person("American McGee", 39));

Comparator nameComparator = new PersonNameComparator();
// Create a sorted list decorator
SortedList sortedList = new SortedList(personList, nameComparator);
EventListModel sortedListModel = new EventListModel(sortedList)
JList list = new JList(filteredListModel);

A SortedList, wrapping a standard EventList

While the above example works for JLists, it’s nice to be able to sort a JTable as well. This is not too hard, either, as long as you have set up a TableFormat instance as described in the first section of this post. In essence, the TableFormat defines the type of each column, which is then used to sort the table whenever the corresponding column header is clicked. This behavior is defined in the TableComparatorChooser class, which exposes a static method to perform the installation on the target JTable. Here’s an example:

Comparator nameComparator = new PersonNameComparator();
// Create a sorted list decorator
SortedList sortedList = new SortedList(personList, nameComparator);
EventTableModel peopleTableModel = new EventTableModel(sortedList, new PersonTableFormat());
JTable peopleTable = new JTable(peopleTableModel);

// Use MULTIPLE_COLUMN_MOUSE to allow sorting by multiple columns, or SINGLE_COLUMN
// to sort by just a single column
TableComparatorChooser tableSorter = TableComparatorChooser.install(
    peopleTable, sortedList, TableComparatorChooser.MULTIPLE_COLUMN_MOUSE);

// At this point, clicking on the table headers will sort by this column

As the more detailed Glazed Lists tutorial warns,

By default, TableComparatorChooser sorts by casting column values to Comparable. If your column’s values are not Comparable, you’ll have to manually remove the default Comparator using TableComparatorChooser.getComparatorsForColumn(column).clear().

As long as your columns are represented by Comparable classes such as Number or String, you shouldn’t have to worry about this caveat.

Conclusion

Glazed Lists is one of the best Java Swing libraries I’ve ever used. It simplifies life for the programmer as well as the end user of the software project, since tables that allow sorting and filtering are far more useful than those which do not. If you do any sort of Swing programming, you owe it to yourself to try this library out. You can find much more information, including the aforementioned tutorial, on the Glazed List website.

 

Chaining together multiple list transformations makes it easy to create powerful programs

An interview with William Wilson, self-taught developer of Fret Tester and more

March 13, 2012 2 comments

I recently had the opportunity to speak with William Wilson, the man behind Fret Tester, the best guitar fretboard learning application available for iOS, and one of the nicest designed apps I’ve used. I wrote about its great UI features in my previous post, The Best iPhone Guitar Fretboard App: Usability Lessons Learned. I wanted to pick the designer’s brain to see what lessons he could impart about designing usable applications. Here’s what he had to say.


Please tell me a little about your background. Do you design mobile applications for a living or as a hobby?

Guitar Hero Pullquote

I’m actually a professional guitarist. I make my living teaching and performing classical and Spanish guitar in San Diego. I’ve always loved programming, starting with Basic, then HyperCard, Java, Flash, and eventually C. I started designing apps for my guitar students as a way to compete with Guitar Hero. I got tired of hearing: “Sorry Mr. Wilson, I didn’t practice, but I played Guitar Hero, does that count?” My first attempts were in Java, and were really awful. I’ve since done about 15 flash games (on my site guitargames.net) and 4 iOS apps. I’ve mostly learned from books and online tutorials. Right now it’s a hobby, but I’d love to do more of it.


As a musician first and foremost, what were the deficiencies you saw in the other published guitar apps and how did you aim to address them?

Traditionally when learning the neck students start with the natural (not sharp and flat) notes. That way they establish landmarks on the neck. I didn’t see this feature being a big part of any app. For me having the iPhone version just display the natural notes made sense (with a button to shift into sharps). Plus it’s tough to fit 12 buttons on the screen without clutter.

One of the biggest challenges I saw was how to zoom in on the neck. With many of the apps, I tried I lost a sense of where I was on the neck. But if the whole neck was shown it was too small. I decided to have my app zoom to the area that was being tested, but to allow sufficient area on either side so the user had a sense for where they were. Plus I included the option to zoom all the way out should the user prefer it. Related to this, I thought many of the apps lacked reinforcement. When you pushed the correct answer your finger covered it. I added the key style buttons so users could see what note the pushed and thus reinforce the correct answer.

Fret Tester screenshot

Fret Tester screenshot - note that only the natural keys are shown and that the incorrect answer that was pressed pops up above the obstructing finger


How have your students received your work? Have you seen a measurable improvement in their progress?

I wish I could say that the app was a runaway success with my students… Unfortunately there is a mindset out there that you aren’t practicing unless you have a guitar in your hand. Mental practice is too often neglected, both with note naming and music theory. For the students who have taken my advice and used the app I’ve seen good things. I think separating the mental and physical complexities of the guitar is the way to go.


What advice would you offer to other people who are not programmers by trade but have an idea for a program or application that could simplify or improve some aspect of their everyday life? What resources have you found that were useful in turning your dream into reality?

There are tons of great resources out there. I always recommend http://masters-of-the-void.com/ as a first step. Also Steven Kochan’s Programming in Objective C is great for learning to write for iOS.

Obvious pullquote

Outside “traditional” programming there were three books that greatly influenced me. One is The Non-Designer’s Design Book by Robin Williams, it will help you design a decent looking app. Second is Dave Woolridge’s Business of iPhone App Development, make sure you can sell one or two before you spend a year creating an app. And finally Don’t Make Me Think by Steve Krug, a guide for good UI principles.

Also I would say make sure to beta test often. I had about 8 people test Fret Tester and learned something from everyone. I like to hand someone my phone and say, try this. You’d be amazed at how they struggle to find something you thought was obvious.


You mentioned making sure that you can sell a product before you invest too much time in producing it. How do you recommend that app developers do this? Do you create a bare bones v 0.0 prototype and put it on the app store to gauge interest? Or do you have an alternative technique for market research?

Wife nuts pullquote

First I look around and see if there are similar apps already out there. If there are a ton, and they’re good, I move on. If there are none I also move on, since there probably isn’t a market for what I’m designing, I want to at least see things that are similar. My goal is to design an app that reaches an already existing need. Not that I’m always successful in it. After reading Woolridge’s book, as well as listening to Seth Godin’s Purple Cow (Audio Book) I’ve improved in this area. I also just talk to people about my idea. If my wife looks at me like I’m nuts (which happens frequently) I try to rethink things.


Are you working on any new projects currently? Or do you have ideas for the next thing you want to work on?

Yes, I’ve been playing around with Adobe’s new Stage 3D and the Starling Framework. It seems promising. I’m hoping to release my first game using it soon. It is called Tab Warrior and is kind of a cross between Fret Tester and Space Invaders. Also, I’m going to try my hand at an Android app this year.


Great to hear. Thank you for taking the time to speak with me. Do you have any parting thoughts for the readers?

80% pullquote

One thing I read in Apple’s docs was to only include features in an app that 80% of users will use. That totally changed my approach. If you look at Apple’s success I think its largely the result of keeping things simple and easy to use, and gearing products for the average user. Take the same approach in your apps.


Thank you to Mr. William Wilson for granting me this interview. You can find more about him on his website, WilliamWilson.com. See my Google+ album for more screenshots of Fret Tester.

Closing a subset of tabs in Google Chrome

March 5, 2012 Leave a comment

Do you use Google Chrome? Do you sometimes want to close multiple tabs at once? Here are three ways to do that, two of which are not immediately obvious.

Close Tabs to the Right

This is the standard way I’ve been using to close tabs. You right click on a tab, choose “Close Tabs to the Right”, and all tabs to the right of that tab are closed. This works well for two reasons:

  1. When you manually create a new tab, it opens on the far right
  2. When you open links in a new tab, it will open immediately to the right of the tab you’re currently in.

Thus if you have opened a few tangentially related tabs from a main article, you can click on the main article’s tabs, choose Close Tabs to the Right, and all of those newly opened tabs will go away.

Ctrl/Meta click tabs

You can add tabs to the current selection by holding control (Windows/Linux) or command (OSX) while clicking on additional tabs. This is exactly the same behavior as when you are selecting multiple files from the desktop GUI. Once you have the tabs you want to close selected, you can right click on any one of the selected tabs and choose “Close Tabs.” This approach works better than the “Close Tabs to the Right” approach when the tabs you want to close are not all next to each other.

Control click example

Why might you want to do this rather than clicking the X in each tab individually? I can think of two main reasons.

The first is that it provides you with a much larger click target for each tab. With this method, you can click almost the entire tab to add it to the selection, then right click almost the entire area of any of these tabs to bring up the context menu to close tabs. The X button itself, by contrast, has a small clickable area that requires more dexterity. (See the Wikipedia article on Fitt’s Law for more information on the relationship between accurate navigation to a UI element and the size of that UI element)

The second reason you might use this method is that it allows you to make your selections all at once before closing any one of them. If you close them one at a time, the tabs move around to take up the empty space. The Chrome team has done an amazing team with the UI design of the standard close tab functionality (e.g. the close button will always stay under your mouse cursor as the tabs reshuffle, and they only will change size once your cursor leaves the tab bar), but it might still be more intuitive to select them all at once while their location is fixed rather than finding them in the changing tab bar as each consecutive tab is closed.

See this excellent blog post by Basil Safwat for more on the Chrome tab close behavior.

Shift click tabs

Finally, you can extend the selection of tabs by shift clicking on any other tab. In other words, the currently opened tab is one endpoint of the selection, you shift click on any other tab (either to the left or right), and that becomes the other endpoint in the selection interval. Here is an illustration of the process:

Shift click example

Once you have your selection, you can right click on any of them and choose Close Tabs as mentioned earlier. This approach is best when you have a contiguous span of tabs you want to close, but there are some tabs to the right that you want to keep open.

Conclusion

I hope you found this brief foray into the ways of closing multiple tabs in Chrome as interesting. I think most Chrome users know of the Close Tabs to the Right option, but I would guess most people don’t know about about the shift click and ctrl/command click ways of selecting tabs.

Categories: Uncategorized Tags: , , , ,