Minimal JavaScript function to detect version of Internet Explorer or Edge

If possible your code should detect features, not browsers. But sometimes you just need to sniff the browser. And when you do, you're probably fighting a Microsoft product.

The following function returns a Number like 10, 11, 12, 13 for Internet Explorer or Edge (anything above 11 is Edge). It returns undefined for any other browser.

function ieVersion(uaString) {
uaString = uaString || navigator.userAgent;
var match = /...


How to make changes to a Ruby gem (as a Rails developer)

At makandra, we've built a few gems over the years. Some of these are quite popular: spreewald (475k downloads), active_type (330k downloads), and geordi (210k downloads) for example (numbers from 2018).

Developing a Ruby gem is different from developing Rails applications, with the biggest difference: there is no Rails. This means:

  • no defined structure (neither for code nor directories)
  • no autoloading of classes, i.e. you need to require all files yourself
  • no [active_support](…

HTML forms with multiple submit buttons

Most forms have a single submit button that will save the record when pressed.

Sometimes a form needs additional submit buttons like "accept" or "reject". Such buttons usually attempt a state transition while updating the record.

To process a form with multiple buttons, your server-side code will need to know which button was pressed. To do so you can give each submit button a different [formaction] attribute. This will override the …


Trigger native mouse events with Javascript

The attached Coffeescript helper will let you create mouse events:

$element = $('div')

The dispatched events are real DOM events, which will trigger both native and jQuery handlers.
jQuery's .trigger is simpler, but will only trigger event handlers that were bound by jQuery's .on.

Real user actions t…

Chrome bug: Wrong stacking order when transitioning composited elements

Google Chrome has a subtle rendering bug that hits me once in a while. It usually occurs in sliders with HTML content.

The issue

When a slider contains a composited[1] element, the element will overlap any other element when sliding, being rendered as frontmost element. After the slider has settled, stacking order jumps back to normal.

It seems like Chrome is doing its compositing wrong. This doesn't happen in Firefox.

The cause

The issue only occurs if:

  • two elements A and B are nested inside an element C
  • A overlaps B (part…

Haml: Generating a unique selector for an element

Having a unique selector for an element is useful to later select it from JavaScript or to update a fragment with an Unpoly.

Haml lets you use square brackets ([]) to generate a unique class name and ID from a given Ruby object. Haml will infer a class attribute from the given object's Ruby class. It will also infer an id attribute from the given object's Ruby class and #id method.

This is especially useful with ActiveRecord instances, which have a persisted #id and will hence **generate the same selector o…

Introduction to Google Tag Manager (for web developers who know Google Analytics)

As a web developer, you know Google Analytics (GA). Probably you've dropped the GA snippet into more than one website, maybe you've even used its Javascript API to implement tracking at the event level.

Google Tag Manager (GTM) is a related tool, but on a higher level and thus with much more power. GTM is not a replacement for GA. Rather, it can make GA configurable without changing anything in the application's code base (and much more beyond, see below).

Only prefer GTM if the customer requests it, or if he is updating his tracking r…

Rails: Flagging all cookies as secure-only to pass a security audit

Why secure-only cookies used to be necessary

Cookies have an optional secure flag. It tells the browser to not send the cookie for a non-https request.

It used to be important to activate the secure flag even on sites that automatically redirect users from http:// to https://. The reason was that most users will only enter a scheme-less domain like into their location bar, which will default to `http://m…


Do not use transparent PNGs for iOS favicons

Safari on iOS accepts an apple-touch-icon favicon that is used for stuff like desktop bookmarks. Always define a solid background color for them.

If you use PNGs with a transparent background, Safari will use just set a black background on your pretty icon. This is almost never what you want.
You can fix that by applying a white background via ImageMagick like this:

convert a...

Devise: Invalidating all sessions for a user

Background information about session storage in Rails

Rails has a default mechanism to store the session in the CookieStore. This is a cookie which holds the entire user session hash in the browser. This cookie is serialized, encoded with base64, and signed.

How Devise handles authentication

Devise uses this CookieStore. To track a users session, a salt is stored in the session cookie when a user logs in.
When a user logs out this CookieStore is overwrit…

Linked contentRepeats

Designing HTML email

The 90s are calling: they want their tables back. Unfortunately, you'll need them all for laying out your HTML emails. (It is really that bad.)

Email client HTML rendering is way more scattered than browser HTML. While you might have a pretty good understanding of what features and patterns you can use to support all major browsers, I doubt anyone masters this craft for HTML email clients.

The only way to ensure your email looks good (acceptable, at least) in all mail clients, is to check it. Litmus is your go-to solu…

Linked contentRepeats

Tasks, microtasks, queues and schedules -

The way that Javascript schedules timeouts and promise callbacks is more complicated than you think. This can be the reason why callbacks are not executed in the order that they are queued.

Please read this article!

This is an extract of the example in the article which demonstrates the execution order of tasks and microtasks.

console.log('script start');

setTimeout(function() {
}, 0);

Promise.resolve().then(function() {
}).then(function() {
}); …

Cucumber steps to travel through time with Timecop

These steps are now part of Spreewald.

Here are some useful examples how to use the attached Cucumber Timecop steps:

When the date is 2011-05-06
When the time is 2011-05-06 17:30

There is also one really awesome step that lets you travel to the past or to the future:

When /^it is (\d+|a|some) (seconds?|minutes?|hours?|days?|months?|years?) (later|earlier)$/

As you can see, you describe the *time unit amo…

Linked content

CSS: Using interaction media detection to disable hover styles for devices that have no hover

Since late 2015, all major browsers (still excluding Firefox) support pointing device media queries. These can be used to distinguish e.g. coarse from fine pointers (e.g. finger vs mouse), or a device with hover support from one without (e.g. desktop with mouse vs tablet).


When hover styles modify the DOM, most mobile devices activate the hover styles on first tap. A second tap is required to trigger a click. While this can be handy, at times it makes the UX worse.

Another issue with hover styles is that they tend to st…

Linked content

Logic in media queries

Here is how to model basic logic in media queries.


With keyword and.

# Target viewport widths between 500 and 800px
@media (min-width: 500px) and (max-width: 800px)



# Target viewport widths below 500 or above 800px
@media (max-width: 500px), (min-width: 800px)


Needs a little overhead with not all and.

# Target devices that can't hover
@media not all and (hover)

See CSS: Using interaction media detection on why you'd need this.


Find an ActiveRecord by any column (useful for Cucumber steps)

The attached patch lets you find a record by a string or number in any column:


There's also a bang variant that raises ActiveRecord::NotFound if no record matches the given value:


Boolean and binary columns are excluded from the search because that would be crazy.

I recommend copying the attachment to features/support/find_by_anything.rb, since it is most useful in Cucumber step …


How to make your application assets cachable in Rails

Note: Modern Rails has two build pipelines, the asset pipeline (or "Sprockets") and Webpacker. The principles below apply for both, but the examples shown are for Sprockets.

Every page in your application uses many assets, such as images, javascripts and stylesheets. Without your intervention, the browser will request these assets again and again on every request. There is no magic in Rails that gives you automatic caching for assets. In fact, if you haven't been paying attention to this, your application is probabl…

Linked contentRepeats

Printing background color of elements

Browsers' printing methods usually don't print background colors. In most cases this is the desired behavior, because you don't want to spent tons of ink printing the background of a web page. But in some cases you want to print the background color of elements, e.g. bars of a chart. For those elements you need to set the following css styles:

Chrome and Safari:

-webkit-print-color-adjust: exact;


color-adjust: exact;
This website uses cookies to improve usability and analyze traffic.
Accept or learn more