Monday, March 10, 2014

Auto Margin in CSS

Auto margin is normally used to center an element horizontally. Basically, set margin to auto will cause margin-left and margin-right to be set by browser so that the element is centered horizontally in its containing block. An exception is that margin-left can not be less than 0 in this automatic setting, thus margin-left will not go negative if the width of the element is larger than the width of the containing block.

Auto margin can also be used to center element vertically. This is much rarer though. This happens when the element is absolutely positioned and when top and bottom are set. If that is the case, then the element will be centered both horizontally and vertically in its positioning parent. The difference is that margin-top can be negative but margin-left can not. In other words, when its positioning parent is narrower than itself in width, then it won't be centered horizontally, just as the discussion in previous paragraph. However, when its positioning parent is shorter than itself in height, it will still be centered vertically, by having a negative margin-top. This is useful when you want to have a image background that is always centered even if the view port size is small, as used in the second CSS trick in this article. Notice that the trick in the article has the flaw that when the window is very narrow in width, the background will no longer be centered due to non-negative margin-left discussed above, while it is still fine for the vertical centering no matter how short the window is.

Thursday, February 27, 2014

Ignoring Mouse Event on DOM Element Using CSS 'pointer-events' Property

Yesterday, I was trying to write my simple Javascript tooltip library that can handle customized feature such as tooltip width, orientation of appearance, and also support arbitrary div content. An example page is here.

Basically, the tooltip div element is positioned absolutely and it shall fade in and out when the trigger text's mouseenter and mouseleave events are fired.

The first difficulty is when the trigger text, say a span, span across multiple lines, such as example two. In CSS term, this span has more than one bounding boxes. This is not a problem if the trigger is a block element as a block element has exactly one bounding box. The desired effect is that the tooltip shall appear next to the bounding box that the mouse enters. This can be solved using the getClientRects method to get all the bounding rectangles of an inline element and decide which of them is entered by the mouse.

The second difficulty, which I want to record here, is as follows. Sometime, due to resizing of browser window, the tooltip will cover part of the trigger text. In extreme case, the tooltip will cover up the entire trigger. As a result, when the tooltip covers the trigger, mouseleave event will be fired on the trigger, even if the mouse is still "on" the trigger. Then the tooltip will fade out and the mouseenter will be fired again... Of course, due to browser event handle time, this will not repeat indefinitely, but it still causes an unpleasant glitch, as show in this JS fiddle. After having some discussion on StackOverflow, I finally found the solution, then "pointer-events" CSS property, which can be used to disable any pointer event on the tooltip and let the event go through to the trigger underneath it, as shown in this JS fiddle. This saved my day.

More info can be found here or here.

Sunday, February 23, 2014

Synchronize YouTube videos

Recently, I created a website to synchronize YouTube videos. The idea is that there is a master video and all other videos (called slave videos)  will be synchronized to the master one, in the sense that all playback action on the master video will be reflected on slave videos. This is useful when you want to watch a clip with friends on the other side of the Internet and want to keep your videos play synchronously, even if you pause or seek.

The master page send all playback actions to the web server for temporary storage using standard Ajax. The slave page, on the other hand, need to get these event updates from the server. This is a problem because in the HTTP paradigm, web clients are supposed to send queries to web server, not the other way around. The technology used here is called Comet, which is also called reverse Ajax. The idea of Comet is to allow server to push data to the client. There are multiple methods and framework to achieve Comet. The method I chose is called long polling. As its name suggests, the client need to poll the server continuously with high frequency to ask for update. This is normally done by send a new XMLHttpRequest at the end of the onload callback of the previous XMLHttpRequest. In my code, I add some rate limit so about 2 polling are executed per second. This seems to work but will be harder to scale as the server is being queried continuously, even if there is no event to update.

Saturday, February 1, 2014

Keep the same heights for multi-column layouts in CSS

When having a multiple column layout using float, it is sometimes important to ensure that the columns all having the same height. This is especially important when the columns have backgrounds that are different from the background of the container.

There are quite a few way ensure identical heights: .

Among those, my favorite one is the Flexbox Method by Paul Irish. The flexbox method make use of very large padding and is a pure CSS solution.

Suppose we have a div "container", whose direct children are the columns, then the flexbox only requires extra-large padding and negative margin with the same magnitude, as follows:

HTML
CSS

The mechanism is simple, since the column has a very large bottom padding, the background extends downwards almost infinitely. Then a negative margin make sure that the effective height of the column is not affected. The container will automatically cut of the extra backgrounds so nothing pokes out.

Wednesday, January 29, 2014

Random JavaScript Tips (1)

After learning JavaScript for 2 days, there are quite a bit of difference between it and Java. One big difference that I am stilling getting used to is the omission of block scope.

In JavaScript, all variable declaration are hoisted to the top of enclosing function or the global script, where as in Java the best practice is to declare variables in the nearest enclosing block. According the creator of JavaScript, Brendon, this design choice is due to short of time when they developed it: a relevant question on StackOverflow.

A more important fact is the implementation of a full Closure in JavaScript. The closure a nested function, together with the reference to local variables of all its outer functions. This is very similar to how Java handle nested classes, where inner class can access the instance variables and methods of (the instance of) it outer class. However, Java don't have a function level closure. For example, the anonymous inner class or local class can only access local variables of enclosing method that are declared final. So this is not real closure.