How to Not Have a Bad Day

Some time ago, when I was still more active on Google+, I used to share a funny little animated GIF from time to time. Not just any semi-funny GIF I came across, but only those that made me laugh really hard and at which I could look a thousand times without becoming bored of them.

Then, when I sat over a boring research paper and started to become demotivated, I would usually scroll through my Google+ timeline, check out one of the GIFs and laugh for five minutes. After that, I was in a good enough mood to finally finish that paper (or whatever other shitty task I had to do). Yet, it’s obviously not convenient to regularly scroll back through one’s Google+ timeline for finding one’s favorite GIFs or to organize them as bookmarks in the browser (point I).

Not so long ago, I stumbled upon Material Design Lite, which I really wanted to play around with since then; but I was lacking a nice use case (point II). Points I & II then finally led to the creation of ‘Good Mood’ as a part of my personal website MaxSpeicher.com. ‘Good Mood’ shall serve as a curated collection of my favorite GIFs, which I also intend to extend in the future. Whenever you’re having a bad day, you can go there, laugh a bit and then go on with a (hopefully) better mood than before 🙂

Now comes the geeky part: As a part of my website, the back end of ‘Good Mood’ is based on Node.js in combination with Express. The front end HTML is generated from Jade templates and—obviously—uses the Material Design Lite framework. However, during the creation of the site, there were some little obstacles to overcome.

I started with the front page of ‘Good Mood’, on which I show a random GIF from my collection. That one was pretty easy. But I thought one might also want to check out a specific GIF from time to time. So I decided to provide a second page on which the whole collection is featured.

How to Load Images Asynchronously as Soon as They Enter the Viewport

Problem 1: Animated GIFs are usually pretty heavyweight, so it’s not optimal to load the whole page with all GIFs, particularly if it’s accessed on the go via smart phone or alike.

The solution to this one was pretty straightforward: a GIF should be loaded only if the user has scrolled to the respective position, i.e., the image enters the viewport. For this, I register a waypoint for each material card displaying a GIF:

$.registerWaypoint = function($element, func) {
  waypoints.push({
    t: $element.offset().top, // top
    b: $element.offset().top + $element.outerHeight(), // bottom
    func: func
  });
};

In the above code, func is the callback function for asynchronously loading the GIF once the viewport reaches the corresponding waypoint:

$.loadCardImgAsync = function(cardCssClass, imgSrc) {
  var asyncImg = new Image();
  asyncImg.onload = function() {
    $('.' + cardCssClass + ' > .mdl-card__title').addClass('bg-img');
  };
  asyncImg.src = imgSrc;
};

In this case, I simply add a predefined CSS class bg-img to the respective card, which displays the GIF in terms of a background-image after it has been loaded as a new Image object.

Finally, we need a function for checking the waypoints against the current scrolling offset and viewport height. That function is bound to the window’s scroll event. Once a waypoint is reached by the viewport—entering from either the top or the bottom—, its callback function is executed and the waypoint is removed from the array of waypoints. In order to not mess up the array indexes after having removed an element, I iterate backwards using a while loop.

checkWaypoints = function() {
  var i = waypoints.length;
  while (i--) {
    waypoint = waypoints[i];
    if (waypoint.t < currentOffset + windowHeight && waypoint.t > currentOffset
        || waypoint.b > currentOffset && waypoint.b < currentOffset + windowHeight) {
      waypoint.func();
      waypoints.splice(i,1);
    }
  }
};

How to Dynamically Adjust Background Images to Mobile Viewports with CSS

Problem 2: The GIF with the cat was too wide for the mobile view of the page, which made horizontal scrolling necessary. But: Horizontal scrolling is pretty uncool!

Found here.
Found here.

This problem was a bit trickier than the previous one, mostly because it involved CSS*. When working with <img> tags, we can simply give them a max-width of 100% and omit the height property, so that the correct aspect ratio is automatically retained. However, since I use material design cards, I had to deal with <div> elements and the CSS background-image property. Unfortunately, those don’t know which height they must have unless we tell them. Say, for instance, the animated GIF we’re dealing with is 400 pixels wide and 225 pixels high. Then, we need the following structure according to material design cards:

div.mdl-card.mdl-shadow--4dp(class='#{card.cssClass}')
  div.mdl-card__title.bg-img
  div.mdl-card__supporting-text Found at
  div.mdl-card__actions.mdl-card--border
    a.mdl-button.mdl-button--colored.mdl-js-button.mdl-js-ripple-effect(href='#{card.link}', target='_blank')
      i.fa.fa-google-plus
      | /#{card.caption}

First, we have to give the container <div> element a width of 400 pixels and a max-width of 90% (to give it some space to the left and right on small screens), but we make no statement about its height:

.cat-card.mdl-card {
  display: inline-block;
  width: 400px;
  max-width: 90%;
}

The height of the container then must be determined by the inner <div> element that actually has the background-image property. In order to do so dynamically, it needs a padding-top value that reflects the aspect ratio of the background image. In our case, that would be 225 / 400 = 0.5625 = 56.25%.

.cat-card > .mdl-card__title.bg-img {
  background: url('/images/gif/cat.gif') center / cover;
  color: #fff;
  padding-top: 56.25%;
}

Now, since the padding of the inner <div> is relative to the actual width of the container <div>, the height of the container automatically adjusts to retain the correct aspect ratio of the background image. Go check out CodePen, where I had first sketched the solution to this. Yet, we need one more piece of the puzzle, which goes into the header of the HTML page:

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

Aaand done! Enjoy—both the website and the source code, which is also available on GitHub!

* http://www.commitstrip.com/en/2014/09/26/the-worst-issues-are-not-always-where-you-would-expect-them/

Advertisements

motherfuckingwebsite.com Redesigned. My Other Poster Presented at #ICWE2014

(Disclaimer: motherfuckingwebsite.com was not made by me!)

Device-agnostic design poster presented @ ICWE 2014From my original post about redesigning motherfuckingwebsite.com (see here), I have created a poster along with a corresponding short paper, which have been presented at the 2014 International Conference on Web Engineering (ICWE).

The short paper will be included in the conference proceedings published by Springer: Maximilian Speicher (2014). “Paving the Path to Device-agnostic and Content-centric Web Design”. In Proc. ICWE (Posters).

Special thanks go to Fred Funke, who helped with designing the poster!

This is a motherfucking website. And it’s not completely fucking perfect

(Disclaimer: motherfuckingwebsite.com was not made by me!)

motherfuckingwebsite.com
The motherfucking website.

I recently stumbled upon motherfuckingwebsite.com, which is the most pragmatic and minimalistic approach to website creation I’ve seen so far (except for plain TXT files, of course). The first two lines read “This is a motherfucking website. And it’s fucking perfect.” The site has raised quite some attention on different social media platforms with lots of people stating that the guy who created it is absolutely right.

Basically, he says that the site is perfect because it loads fast, is accessible to everyone, is dead responsive (without using media queries), has content (i.e., it gets its “fucking point across”), uses semantic HTML5 tags etc. Most of the statements he makes are indeed right and there are undoubtedly lots of web designers out there who should take them to heart. The creator’s final note is that motherfuckingwebsite.com is “fucking satire”. His aim is to convey that websites are not broken by default. Instead, developers break them.

“Good design is as little design as possible.”
— Dieter Rams

Based on the facts that lots of people like the idea behind the site and that the creator makes a whole bunch of true points, I want to point out three things in which he is not completely right or that he passed over. These would bring a site of this kind closer to perfection, assuming that we follow a text-centric and device-agnostic approach.

  1. Line length: Text lines on motherfuckingwebsite.com span across the whole width of the viewport. This is particularly disadvantageous on large screens. An optimally readable line should contain only ~66 characters, which corresponds to ~30 em.1 To reduce the amount of scrolling, this must can (Update July 23, 2016) be augmented with a multi-column layout and pagination.2
  2. Navigation: motherfuckingwebsite.com does not make statements about navigation. However, a website featuring larger amounts of content would require a navigation bar, optimally fixed to the top of the viewport.3 This navigation bar should adapt to smaller screens without device- or resolution-specific break points (= device-agnostic design).
  3. Aesthetics: motherfuckingwebsite.com follows a completely technical/functional point of view. Yet, this does not completely cover perfectness from the users’ perspective. Particularly, research has found that visual aesthetics are a crucial factor concerning user satisfaction.4 Even without excessive use of graphics this can be reached by leveraging more sophisticated color schemes and typography rather than just black/white coloring and default fonts.

Keeping the above points in mind, motherfuckingwebsite.com is for sure a good starting point for “back-to-the-roots”, minimalistic and device-agnostic web design.

Update (November 28, 2014): Please also pay attention to the follow-up posts based on this article, as well as the conference article published by Springer:

1 http://goldilocksapproach.com/article/
2 Michael Nebeling, Fabrice Matulic, Lucas Streit, and Moira C. Norrie (2011): “Adaptive Layout Template for Effective Web Content Presentation in Large-Screen Contexts”. In: Proc. DocEng.
3 Cf. http://www.dartlang.org/
4 Talia Lavie and Noam Tractinsky (2004): “Assessing dimensions of perceived visual aesthetics of websites”. International Journal of Human-Computer Studies, 60(3), pp. 269–298.