Introducing eg.InfiniteGrid, a new library for implementing a card layout
Clone this wiki locally
Cards are predominant design pattern that helps users quickly skim and consume various content. Cards were first presented on Pinterest and have spread around the world. Cards are currently dominating web design, which has been used even for Twitter, Google, and Facebook.
Before taking up the main subject, I'd like to talk about Masonry, an open source library that helps you easily implement this layout. This grid layout library, made by David DeSandro, has racked up more than 10,000 GitHub stars, which means it gains huge popularity among developers; it is easy to use and supports a number of third-party products. NAVER Shopping, in fact, was initially implemented by using Masonry. However, it has now been replaced by eg.InfiniteGrid, one of the egjs modules.
Why eg.InfiniteGrid was chosen instead of Masonry?
In this article, we will describe differences between Masonry and eg.InfiniteGrid and explain why we decided to make the change.
Why NAVER had to abandon Masonry?
Masonry provides two main functionalities.
First, it provides a layout functionality that stacks up cards with the "float:left" property to the left or right.
Second, it provides a responsive layout functionality that rearrange cards to fit them to the screen size.
In addition, it also provides a functionality that adds an animation effect while rearranging the layout.
There is no doubt that Masonry is such a good library. The situation, however, is a little different when it comes to NAVER Shopping in which multiple pieces of card-based content are showing up infinitely.
Issue on rearranging cards
The speed of the card rearrangement can become an issue as the number of cards increases. The logic to calculate card time is simple, but it is not always an easy task to calculate card size so as to make cards rearranged. Furthermore, cards generally contain external resources such as images so calculating won't begin until the entire external resources have loaded, resulting in longer time to rearrangement. The speed of the card rearrangement, in particular, is important for mobile devices of which orientation can changes even after card rearrangement has completed.
Let's say that you're planning to arrange cards in two rows for portrait and three rows for landscape. It should redo the calculation if a screen orientation changes for this situation.
Issue on adding cards
It will take longer time to add cards as the number of cards increases, resulting in a lower quality of user experience as this will lead to a drastic fall in user's perceived speed. The number of DOM elements also increases, so the browser uses more memory under this circumstance, which may cause memory shortages on a browser. Even worse, it might cause the browser to close unexpectedly. This problem can often occur in the mobile device of which memory card has a small storage capacity but screen size is big.
Because the issues described above are systemic problems, so there is no way to deal with them using Masonry.
eg.InfiniteGrid provides the same main functionalities as Masonry does, card layout and responsive layout functionality.
However, eg.InfiniteGrid dealt with the systematic problem of Masonry and improved the speed performance, providing a functionality to implement infinite scrolling that can show up content infinitely, as you may be aware from the eg.InfiniteGrid name.
To improve the performance, the structure has changed in which DOM elements appearing on the screen are kept alive as keeping a fixed number, whereas DOM elements appearing off the screen are removed. This structural change can guarantee performance when adding or rearranging cards because it internally keeps a fixed number of DOM elements. Moreover, keeping a fixed number of DOM elements also resolves browser crashes by lowering the memory usage of a browser.
In the next section, we will explain the details of differences between Masonry and eg.InfiniteGrid.
Comparison between Masonry and eg.InfiniteGrid
The following table shows the differences and similarities between Masonry and eg.InfiniteGrid.
|Library dependencies||outlayer, get-size, imagesloaded (optional)||jQuery 1.7.1 or later|
|File capacity||masonry.min.js: 2,615 bytes||infiniteGrid.min.js: 9,226 bytes|
|File capacity (package)||masonry.pkgd.min.js and imagesloaded.pkgd.min.js: 28,954 bytes||infiniteGrid.pkgd.min.js: 15,950 bytes (except jQuery)|
|Supported browsers (desktop)||Internet Explorer 10 or later, latest browser||Internet Explorer 8 or later, latest browser|
|Mobile platforms||iOS, Android||iOS 7 or later, Android 2.3 or later (except 3.0)|
|Infinite rearrangement of cards||Not supported||Supported|
|Fine controls of card rearrangement||Supported||Not supported|
|Animation effect||Supported||Not supported|
The size of eg.InfiniteGrid is 15,950 bytes, which is smaller than that of Masonry if you simply compare two packages. However, it will be larger than the size of Masonry if this library is implemented in the service where jQuery is not used since eg.InfiniteGrid is based on jQuery.
The file size of compressed jQuery 3.1.0 is 86,351 bytes.
eg.InfiniteGrid supports Internet Explorer 8, which means it offers a wider browser coverage than Masonry. On the contrary, Masonry would be a better choice for fine controls of card rearrangement.
However, eg.InfiniteGrid would be a better choice for performance-critical service. Lets' move on to the next section that shows the actual data, describing the performance gaps between Masonry and eg.InfiniteGrid.
Performance during card rearrangement
Cards should be rearranged when the screen size changes or a card-style layout is applied for the first time. It is critically important how long it will take to complete a task (card rearrangement) since users are supposed to see cards being rearranged; the faster speed can improve the users' perceived speed.
To identify that speed, we measured the initial load time of Masonry and eg.InfiniteGrid.
The following graph represents the average completion time to render a layout having 1,000 cards with text and images included; it had been tested for Masonry and eg.InfiniteGrid ten times each.
The initial speed of eg.InfiniteGrid is 63-167 percent faster for both mobile and desktop. It is faster no less than 130 percent on average, in particular, for mobile of which hardware performance is lower than that of desktop.
The detailed test results for mobile are as follows:
- • Test environment: Samsung Galaxy S4, Android 4.2.2 Chrome 52.0.2743.98
|Trial Count||Masonry||eg.InfiniteGrid||Performance Gap|
The detailed test results for desktop are as follows:
- Test environment: MaxOS, Chrome V51.0.2704.103
|Trial Count||Masonry||eg.InfiniteGrid||Performance Gap|
Performance during card addition
Your users should wait so long until the next content shows up if the speed of the card addition is too slow while new cards are constantly being added by user scrolls. This will make them tired of waiting and they will start complaints about the speed of your service. What it makes worse is that they never visit your service again.
To identify that speed, we measured the completion time to render a layout after adding 30 cards total 100 times by using the appended() method of Masonry and the append() method of eg.InfiniteGrid, respectively.
The following video shows how to perform the task of adding cards with text and images included by using Masonry and eg.InfiniteGrid.
<iframe width="560" height="315" src="https://www.youtube.com/embed/6Kv-NV0dZXw" frameborder="0" allowfullscreen></iframe>
- Masonry: http://s.codepen.io/sculove/pen/akakBj
- eg.InfiniteGrid: http://s.codepen.io/sculove/oen/KrZmPd
- The initial number of cards: 30
- Add 30 cards 100 times (total 3,000)
- Samsung Galaxy S4, Android 4.2.2 Chrome 52.0.2743.98
As you can see on the video, it takes 63,488 milliseconds total with Masonry, whereas 18,602 milliseconds with eg.InfiniteGrid; eg.InfiniteGrid works three times as fast as Masonry. Furthermore, the time of card addition continues to rise as the number of cards increases.
Memory usage after card addition
Suppose that you encounter an unexpected error such as accidental closing of browser or screen not responding. Can you put up with the unpleasant experience and continue to use the service? Maybe not.
Those errors are mostly resulted from memory shortages on a browser. You will have a higher chance of encountering these errors on the card-style layout showing multiple pieces of content.
The following graph represents the memory usage of Masonry and eg.InfiniteGrid.
For Masonry, the size of used memory is 30,082 kilobytes.
For eg.InfiniteGrid, the size of used memory is 19,673 kilobytes.
As you can see from the graphs, the size of used memory by using eg.InfiniteGrid (19,673 kilobytes) is less than two-thirds of that by using Masonry (30,082 kilobytes). eg.InfiniteGrid enables to keep a fixed number of DOM elements, thereby the memory usages remaining almost the same, no matter how much content is used. The memory usage with Masonry, however, continues to rise in such a case.
In this article, we have compared Masonry and eg.InfiniteGrid in several aspects of performance including the memory usage and the response time for each card addition or card rearrangement while rendering a layout. The test results showed that eg.InfiniteGrid had better performance than Masonry.
Masonry is truly a useful library; it allows addition of an animation effect to each card and offers finer rearrangements of cards. A serious performance problem can be raised, however, with Masonry when the number of cards being placed increases and the size of screen where cards are showing is too big.
eg.InfiniteGrid, on the other hand, does not have a systemic flaw causing a performance problem since it keeps a fixed number of DOM elements, but animation effects or finer controls of card rearrangements are not supported yet with the library.
eg.InfiniteGrid is just the beginning; we know that our library should offer functionalities such as animation effects and finer controls of card rearrangement, like Masonry. It would be a better choice for you than Masonry, nonetheless, if you plan a service where users are constantly consuming multiple pieces of content like NAVER Shopping.