Christian Heilmann

You are currently browsing the Christian Heilmann blog archives for May, 2013.

Archive for May, 2013

Five reasons your visitors don’t return to your web product *

Friday, May 31st, 2013

  • They decided they actually really hate you and everything you stand for
  • They’ve been abducted by aliens and are busy being probed
  • They watched too much Fox News and now receded to the cold war bunker eating tinned apricots until it is safe to come out again
  • They never existed, you are actually in a secret government facility strapped to a chair and they keep injecting you with neurochemicals telling you that you are a web designer
  • They are but they are wearing false noses, teeth and hairpieces to disguise themselves and really mess with you

dumb is good slogan proposal from brave new world

* Hey, I never claimed they are good reasons. I just wanted to do one of those incredibly successful blog posts with a catchy title that get tweeted around a lot.

Fixing the mobile web at Beyond Tellerand

Thursday, May 30th, 2013

The last few days I spent in sunny Duesseldorf attending the Beyond Tellerand conference, organised by my good friend and partner in 8-bit crimes, Marc Thiele.

crowd at beyond tellerand
the welcome gift bag for speakers, customised for each

I’ve been saying for quite a while that the success and quality of a conference is incredibly linked to the enthusiasm of the organisers and with Beyond Tellerand, you hit the jack-pot, both as a speaker and attendee. I could wax poetic about how great the conference, how diverse the talks and how funky the location were but my colleague Marco Zehe did a much better job in his conference write-up. Suffice to say, I really enjoyed it and consider Beyond Tellerand one of the best conferences in Europe at the moment. I especially like the intelligent decision not to bother with catering but bring people into an area with lots of restaurants and give them a longer break instead. All in all, the schedule had lots of great breaks to network and there was no sense of rush at all.

I was scared and also very honoured to give the opening keynote on the second day, with my task being to wake the crowd up after the party the night before and to set the tone for the rest of the day.

In my keynote Fixing the Mobile Web, I explained that I am worried that we lack passion for quality in our craft and instead follow a breakneck speed race of releasing more and more and quicker instead. I also pointed out how we got a lot of promises of what HTML5 would mean for us and got let down by the platforms that waved the flag the most and called Flash dead. I then explained how FirefoxOS wants to bridge that gap and fulfill these promises whilst being the first impression millions of new users will get of the web with our work being the first things they use.

I recorded a screencast of the talk with some audio issues, but it still should give you a good idea of what was going on until the organisers release the high-quality video.

After the talk, I also sat down with the German web magazine t3n to record a quick video on my talk and the impressions of the conference (in German). The video is here.

Furthermore there will be a German recording I did with the Workingdraft podcast once they edited it which goes into more detail about FirefoxOS and my presentation.

All in all I want to thank everybody involved. The people who came to see and talk to us, all the other speakers who did a great job, the organisers and sponsors and the crew of the location. It was fun and it will come back soon, so check out Beyond Tellerand.

Giving “image swivel” the vanilla web diet treatment

Friday, May 17th, 2013

With my chapter for the upcoming Smashing Book 4 done and talking about “The Vanilla Web Diet” and some workshops in the making I thought it is a good idea to show in an example how to make a seemingly good solution better by rethinking it with the principles of the vanilla web diet in mind.

The solution I am targeting is the image swivel effect that was posted a few days ago on CSS tricks. I sent my solution to the author and he was very interested in getting more information as to the why. The effect as it stands works and does the job to inspire people to play with it. The comments showed that where lots of developers had a go at creating their own solutions fixing some of the issues I am about to cover here. My favourite probably is Eduardo García Sanz’s Pure CSS solution which to me is a good plan to achieve an effect like that if you don’t need touch support or keyboard access.


Before I get accused of “hating” – the code is OK as a demo to get creative juices flowing but it has many issues that would show up when used in production. It is also mouse-dependent and doesn’t work on touch devices. Therefore I’ll start by stating what I find troublesome about the published solution and then explain how to approach the problem to make it as simple and maintainable as possible. I also add support for mouse, keyboard and touch access and try to achieve the effect whilst not blocking people out.

If you prefer to see this as a screencast, here is one I recorded explaining the ideas, the issues I found with the original code and how my solution works. This is live and unscripted.

How much markup do we need?

Let’s start by looking at the solution that is shown in the CSS tricks article.
The HTML is the following:

<div id="faces">
  <div id="face-area">
    <div id="image-1" style="display: none;">
      <img src="/images/look-left-3.jpg">
    </div>
    <div id="image-2" style="display: none;">
      <img src="/images/look-left-2.jpg">
    </div>
    <div id="image-3" style="display: none;">
      <img src="/images/look-left-1.jpg">
    </div>
    <div id="image-4" style="display: none;">
      <img src="/images/look-center.jpg">
    </div>
    <div id="image-5" style="display: none;">
      <img src="/images/look-right-1.jpg">
    </div>
    <div id="image-6" style="display: none;">
      <img src="/images/look-right-2.jpg">
    </div>
    <div id="image-7" style="display: none;">
      <img src="/images/look-right-3.jpg">
    </div>
    <div id="the_faces_overlay">
      <div class="the_faces" data-number="1"></div>
      <div class="the_faces" data-number="2"> </div>
      <div class="the_faces" data-number="3"></div>
      <div class="the_faces" data-number="4"></div>
      <div class="the_faces" data-number="5"></div>
      <div class="the_faces" data-number="6"></div>
      <div class="the_faces" data-number="7"></div>
    </div> 
  </div><!-- END #face-area -->
</div> <!-- END #faces -->

Warning sign #1: Repeated HTML structures without logical connections

This is a very common mistake I see when starting an effect like that. We create something that contains the content and then something that gets acted upon to show the effect. Thus we lose the benefit of already interacting with the parent element and using event handling to find out where we are. I guess historically this is based on “CSS only solutions” that needed that kind of separation as you could not calculate or detect mouse position in CSS.

As we create two separate sets of markup for an effect we need to find a way to connect the element that was interacted with to the one we want to show. This means adding IDs to all the elements, classes to all the elements we interact with and a data attribute to tell which of the images to show. This is bad for maintainability. If we add an image, we need to also add an element to interact with. Great code is catered to making maintenance as easy as possible. Here we have a lot of dependencies to deal with when adding or removing an image.

Warning sign #2: Lack of semantic markup


The other gripe I have with this HTML is that it means nothing at all. As the order of the images is important, the right HTML construct to use here is an ordered list.

Warning sign #3: Lack of alternative content


Another big HTML mistake is adding images without an alt attribute. This means that screenreader users would get the file path of the images read out to them. Either provide a sensible alternative text or add a alt=”” to hide the image from screenreaders.

Warning sign #4: Dependency on the number of elements


One big warning sign to me here is that our effect is dependent on the number of images in the widget and that we need to have the data attributes and the IDs maintained together although they are on different elements.

The more elements we add means the more IDs we need to maintain. This is not what coding is about. Computers are good at calculating things for us.

Warning sign #5: Empty elements and inline styles

Whenever I see inline styles I know something went wrong. There is no point in them and if ever they should only be generated by code, not by humans. The same with empty HTML elements: you probably did some extra work that is not needed. HTML is there to contain content or provide interaction. If you have a lot of empty DIVs without an obvious templating use case, something went wrong.

Giving no power to CSS

The CSS of the solution is not much, and it doesn’t do much either. This is a shame seeing how much easier it is for a visual maintainer to change CSS rather than changing JavaScript.

body {
  background: #333 
}
#faces {
  height: 333px;
  width: 500px;
  margin: 0 auto;
  border: 8px solid white;
}
#face-area {
  height: 500px;
  width: 333px;
  position: relative;
}
#the_faces_overlay {
  position: absolute;
  width: 500px;
  top: 0;
  left: 0;
}
#faces .the_faces {
  height: 333px;
  width: 14.2857143%;
  float: left;
  margin: 0;
  padding: 0;
}

Warning sign #6: CSS dependent on the amount of elements

The glaring issue here is the “width: 14.2857143%;” which is calculated by dividing 100% into seven parts. This means that if you delete an image from the HTML, you also need to change the CSS width here. You should never be dependent on the amount of elements in your CSS, as those are prone to change. In this case especially there is no logical way to find out why this is the width. CSS calc() can at least make that obvious but in general it is a bad idea to create look and feel that is tied to a certain amount of elements.

Goldfish jQuery

The jQuery code to make the effect work is very short:

// Reveal the "center" image
var centerImage = $("#image-4").show();
// Bind hovers to each column
$(".the_faces").each(function() {
  $(this).on("mouseover", function() {
    $("#image-" + $(this).attr("data-number")).show();
  }).on("mouseout",function() {
    $("#image-" + $(this).attr("data-number")).hide();
  });
});
// Reset center image
$("#face-area").on("mouseleave", function() {
  centerImage.show();
}).on("mouseenter", function() {
  centerImage.hide();
});

It is, however, very demanding to the browser. Slowing down a browser can be done in many ways – the most damaging ones are heavy computation, accessing the DOM and lots and lots of event handling. The latter two is what we do here.

Warning sign #7: lack of data caching

We loop over all the elements with the class “.the_faces” and add a mouseover and mouseout handler to each of them. Every time these get fired, we read an attribute, create a string with it and access an element that has the ID of the string and show or hide it. Showing and hiding using the jQuery methods is another access to the DOM as it manipulates the display style property. We show and hide the “center image” upfront and also on another event hander on the overall parent element.

If we were to add touch and keyboard handlers we’d triple the amount of assigned event handlers as we apply them on each image.

I call this Goldfish code – we keep asking the browser for things we should already know. The widget interface we have here is static HTML - there is no loading of content, no changes in it. Therefore there is no point in continuously reading out what the data-number attribute is and ask the browser to find the element with a certain ID. Caching results is a very simple thing to do and the performance benefits are amazing.

Rethinking the solution the vanilla web diet way

I approached the solution by looking at what we need to do here:

  • We have a widget of a certain size with images in it
  • We have an unknown amount of images – it should be dead easy to remove or add one or replace them all
  • Moving the mouse over the widget should loop through the images, also touching the widget should do so and it would be nice to be able to flip forward and backward with the keyboard
  • Should things not work out it would be nice to have an display that still makes sense

The HTML - we don’t need IDs or data attributes

<a href="/productpage" id="rollover">
<ol>
  <li><img src="pics/IMG_0518.jpg" alt""></li>
  <li><img src="pics/IMG_0517.jpg" alt=""></li>
  <li><img src="pics/IMG_0516.jpg" alt=""></li>
  <li><img class="current" src="pics/IMG_0515.jpg" alt=""></li>
  <li><img src="pics/IMG_0519.jpg" alt=""></li>
  <li><img src="pics/IMG_0520.jpg" alt=""></li>
  <li><img src="pics/IMG_0521.jpg" alt=""></li>
</ol>
</a>

We should link this to something – after all a beautiful effect like that should react in some sale or deep-dive, right? Good thing is that in HTML5 links can contain other elements. So all we add is a link. This automatically gives us keyboard access to the widget – something otherwise we’d have to create by using roaming tabIndex.

As the order of the images is important, an OL is the right element to use. Each image has an empty alt attribute to ensure there is no hassle with screenreaders. Instead of defining which image to show as the first one in our JavaScript we keep this maintained in HTML, too, by adding a class of “current” to the image.

Showing and hiding with CSS

body {
  font-family: arial, sans-serif;
}
#rollover.js {
  display: block;
  margin: 2em;
  z-index: 3;
  position: relative;
  height: 270px;
  width: 200px;
  cursor: none;
}
#rollover.js img {
  width: 100%;
  position: absolute;
  top: 0;
  left: 0;
  visibility: hidden;
}
#rollover.js img.current {
  visibility: visible;
}

As our functionality is dependent on JavaScript, our styling should be, too. This we can achieve by adding a “js” class to the element when JavaScript is available and only apply the styles when needed. This CSS gives the widget a fixed size and positions all the images stacked inside it.

Instead of doing a hide() and show() in JavaScript, all we need to do is to apply a class of “current” to the element we need to show. All the hiding and showing is thus done in CSS which means that in the future we’d want to do other visual things with the “shown” and “hidden” images, all we need to change is the CSS.

(function(){
 
  if (document.querySelector) {
 
    var rollover = document.querySelector('#rollover');
    rollover.className = 'js';
 
    var images = rollover.querySelectorAll('img');
    var all = images.length;
    var width = rollover.offsetWidth;
    var ox = rollover.offsetLeft;
    var boundarywidth = width / all;
    var current = 0;
    var x = 0;
    var index = 0;
    var touched = false;
 
    var setcurrent = function(index) {
      if (images[index]) {
        images[current].className = '';
        images[index].className = 'current';
        current = index;
      }
    };
 
    var findindex = function(x) {
      index = parseInt((x - ox) / boundarywidth, 10);
      if (index !== current) {
        setcurrent(index);
      }
    };
 
    rollover.addEventListener('mousemove', function(ev) {
      if (!touched) {
        findindex(ev.clientX);
      }
    }, false);
 
    rollover.addEventListener('touchstart', function(ev) {
      touched = true;
    }, false);
 
    rollover.addEventListener('touchend', function(ev) {
      touched = false;
    }, false);
 
    rollover.addEventListener('touchmove', function(ev) {
      if (touched) {
        findindex(ev.changedTouches[0].clientX);
        ev.preventDefault();
      }
    }, false);
 
    rollover.addEventListener('keydown', function(ev) {
      var key = ev.char || ev.key || ev.which;
      if (key === 37) { index = index - 1;}
      if (key === 39) { index = index + 1;}
      if (index < 0) {index = 0;}
      if (index > all - 1) {index = all - 1;}
      setcurrent(index);
    }, false);
 
    if (rollover.querySelector('.current')) {
      for (var i = 0; i < all; i++) {
        if (images[i].className === 'current') {
          current = i;
          break;
        }
      }
    } else {
      setcurrent(current);
    }
  }
})();

Quite longer than the jQuery, but bear with me as this does a lot more and in a much less demanding fashion. We wrap our code in a closure to makes sure we don’t leave any nasty globals behind. That should always be the first step.

Then we test if the browser supports document.querySelector. This is the standard answer to jQuery’s $() and is supported by lots and lots of great browsers. It is not supported by old and outdated browsers, which is why it is a good idea to test for it. This means that old Internet Explorer versions will not get the effect but instead they get the images as a numbered list (as we made the CSS dependent on a class applied with JavaScript). This is good, as it means we don’t need to test on these old browsers, which is hard to do and frankly a waste of our time.

We get a reference to our rollover widget using document.querySelector() and add the “js” class to it. This hides all the images and sets up the look and feel of the widget – all maintained in CSS. No need to loop through a lot of elements or use inline styles to hide them.

Next we get references to all the DOM elements we need and calculate what we need to find out what to show when the mouse cursor or the finger is on a certain part of the widget.

First we get all the images and store them in images. This will not change while the page is open, and querySelectorAll() gives us references to all of them. We store the amount of images in all to compare against later on.

Next we do the thing dynamically that the original solution did by hand – calculate the width of the different strips of the interaction that shows and hides images. We do this by reading out the offsetWidth of the widget as it is defined in CSS, so we don’t know and don’t want to hard-wire any widths in our JavaScript. We find out how far left the widget is in the browser by reading the offsetLeft property and store that in ox. Then we calculate the width of the interaction boundaries by dividing the width of the widget by the amount of images and store that in boundarywidth.

This makes the widget flexible to change any time the CSS changes or the amount of images does. If you remove or add an image, the width of the boundaries is calculated newly. No need to change the CSS to reflect that width. We made this now maintainable simply by adding or removing list items.

We define the current shown image index as 0, preset an x variable as 0, define the current index of the detected movement as 0 and set touched to false.

The index will be the index of the image to be shown at a certain point in the interaction. The index of the currently shown one is be stored in current, x will be detected position of the mouse or finger on the screen and touched defines if the screen is currently being touched or not.

The setcurrent() function hides the last shown image and shows a new one by shifting the “current” class from one to the other. It then stores the new image index in current. This is a very simple way to show a new state in a collection of things that can only show one at a time. No need to ask the browser which one is visible when we can store this in a variable like current.

The findindex() function converts the detected horizontal position of the mouse cursor or the finger of the user into an index of our image array. All you need to do is to subtract the left position of the widget itself and divide the value by the boundarywidth. Convert it to an integer and compare it to the current index and if it differs, call setcurrent().

All that is left is to assign the event handlers to make the magic happen. The first is a mousemove listener on the widget that calls findindex() when no touch happened. The current horizontal mouse position is stored in clientX of the mousemove event.

Touch interaction needs to be initiated (at least in Chrome in my testing here) so we set the Boolean of touched to true when a touchstart happened and to false when touchend was detected.

When a user moves a finger over the widget the browser fires the touchmove event and the current horizontal position is stored in the clientX property of the changedTouches array. We only detect the first finger in this case.

Keyboard detection doesn’t give us a position on the screen, so all we do is manipulate the image index directly. We listen for a keydown event and check the code of the key that was pressed. If it is the left arrow we subtract one from the current index and in the case of the right arrow we add one to it. We ensure that the index stays in the allowed limits and call setcurrent().

The last thing to do is to show the current image. If there is one with the right class in the HTML we need to find out its index and we do that by looping over them until we find the right one. If there isn’t any we just apply the current class to the first image (as defined at the start of the script).

Many solutions to the same idea

I hope this gives you an idea of how to approach an effect like that when you want to put it in production. There are of course other ways of doing it, but I wanted to ensure a few things that get very often forgotten:

  • The whole effect is now generated from the HTML, so all you need to do to create a new swivel is add other images
  • The whole look and feel is defined in CSS and you can resize the widget without having to worry about the size of the different boundaries
  • It can be used with a keyboard, the mouse or on touch devices
  • The DOM interaction is kept to an absolute minimum which means the performance on low spec devices is much, much better
  • There is no jQuery dependency

A few questions and answers about “mobile web” and sites vs. apps

Wednesday, May 15th, 2013

I just got asked to provide a few answers for a survey amongst “mobile web experts” and thought it’d be good to re-use those here. So here goes:

What is the difference between a web site and a web application?


There are a few differences. On a very basic level applications are catered for doing things whereas web sites are more catered for offering content for consumption. Web sites started as structured, interlinked academical documents. Later on we added multimedia content to make them much more engaging but all in all they are fixed in their state.
Applications are more dynamic. They allow for customisation of the interface and store the state of what happens so that when you get back to it you can go on from where you left off.

The use case of an app should always be to do something with it. This could be as simple as voting on a how much you like a kitten photo and go as far as editing video content live in your browser or on your device. Basic examples would be a webmail client as an application and a pure image gallery to click through as a web site.

Web sites are static whereas web applications have atomic updates and in of themselves have a very small footprint as most of the content gets loaded subsequently and changes every time you use it.

All in all it is a sliding scale though as for example an image gallery can easily become an application if it allows you to upload your own images or edit and remix the existing ones in your browser. That is one of the main benefits of web technology – it is very flexible and allows for quick and simple changes to the final product without being hindered by a complex compilation, packaging and deployment process.

What kind of features should a web site have to be qualified as a web application?


Again, there are many things to consider. One main thing is that an app does one thing and one thing well. It is there to help you do something.

Technically it should behave like the fat client apps of old: it should retain my state and settings, allow me to customise the interface to my needs and it needs to work offline. The latter is not a technical necessity in terms of definition but to me crucial usability. Seeing how flaky our connections are – I am writing this on a plane – our apps should make people as effective as possible and this means we shouldn’t be dependent on a connection. The interface should be usable whilst we are off the grid and sync as soon as we go online.

Customisation and personalisation of the interface and interactivity to me make an application. This could just mean a game where I can change my character and get extras the more I play. A proper “web” application to me also should use the web whenever it can. For example I am very frustrated with playing a game on my phone and when I go to my tablet playing the same game my score and achievements aren’t synced although the device knows who I am. Why be online then?

A lot of badly designed web apps are just wrappers for content like a news feed. For example turning a blog into an app is a pointless exercise. It just adds the overhead of having to install the wrapper, update and uninstall it when I am fed up with the blog but doesn’t give me the “do something” part that defines an app.

If I don’t interact with it other than reading there is no point in making it an app. You lose a lot of the flexibility of the web when packaging HTML as native apps with the most important thing being opaque updates. An app that is hosted on the web can be patched and upgraded without the end user having to download megabytes of data. That is incredibly useful on slow or flaky connections. Instead of the whole app you only download the changes.

What is the difference between a mobile-friendly site and a mobile web app?


A mobile-friendly site is a web site that detects the capabilities of the device it is displayed on and doesn’t make assumptions about how big my screen is and that I have a mouse and keyboard or not. It runs in the browser of the device and is thus hindered by its limitations – which in the case of older Android devices are quite limited indeed. It caters to the mobile space in terms of display changes – single column display, larger fonts, larger buttons.

A mobile web app is an application built with web technologies running in an own, full-screen wrapper and not inside a browser. It takes advantage of all the things the current environment allows for. For example it stores content and itself locally instead of having to be online and requesting everything new every time you open it. It can access the special features of certain environments like swipe gestures, accelerometer for interaction or accessing the camera to get content in. Its purpose is for me to do things with it and not just visit it like I visit a web site.

What would you consider is the key feature that made HTML5 (as opposed to Flash and Java) the number 1 choice for developing mobile web apps?


Flexibility is the super power of HTML5. It is easy to make an HTML5 app adapt to a new environment and to make an interface that shows and hides content and functionality dependent on the capability of the device or environment. Both Java and Flash are not “web native”, meaning you need to initiate and execute an own code environment inside a browser before you see the results. This hinders interactivity of the containing document and the content of the Flash movie or Java Applet. Whilst both Java and Flash have incredibly good development tools and capabilities once they are available they are very demanding to the hardware they run on. That’s why iOS devices don’t have Flash. There is already a fully capable environment available – the browser – and executing another one inside it means using a lot of resources. On mobile devices this means shorter battery life and the device heating up quickly.

With HTML5 we have the opportunity to improve what mobile, web enabled devices already have to have – a browsing environment. These are available open source and for free (Firefox, Chromium and others) and developers can build apps without needing to sign up for one company and get their SDK to get started.

All environments have their uses and there are things that are better done in Flash than in HTML5. Betting on open technologies and browsers means though that you are very likely to be flexible enough to cater to the next environment around the corner. The web has always evolved and mutated around the needs of the market. That’s why multimedia in HTML5 is just another element of the document and not a black hole that can not interact with the rest of the browser or the document.

Where would you say the mobile web is heading? Do you see a future for the mobile web?


There is no mobile web. There is the web. Right now we start consuming it more and more on mobile devices. That is cool. And the web is totally ready for that as it is flexible enough to adapt.

If you use web standard technologies to build applications that expect a certain device, a fixed size of a screen, a special way of user interaction or expect a fast connection you are building a very limited and very quickly outdated piece of software.

Over the last years we should have learned that hardware is a commodity and susceptible to very sudden change. An amazing piece of hardware that is the hot new thing now can tomorrow be embarrassingly outdated.

When you build your web apps to only cater for that you try to be native code and that is a race you can not win. A lot of native apps are built to promote a new piece of hardware and to get people to upgrade. That is a very old technique of selling more products called in-built obsolescence.

Web apps should be beyond this. Our job is to give end users the best possible experience on the current devices but not make them a necessity. We did this mistake in the past which is why you see web applications that tell you that you need a “modern browser like Internet Explorer 6” and “at least 800×600 resolution”.

Native apps on high-end devices are doing really well right now, but I can foresee that people will get bored of having to buy a new phone every year just to get new functionality that is not that important when you consider the cost. The web will stay and always be the open alternative for those who want to consume and create on their own terms instead of being dependent on the success or goals of a certain company.

“just use technology $x” is a terrible answer to a question

Monday, May 13th, 2013

A few days ago a vertical video went viral of the student Jeff Bliss telling his teacher off for being a bad teacher who just hands out materials without explaining anything.

And we all applauded him for his gall and his eagerness to learn and to point out the obvious flaws in the education system. Teachers are not paid enough, are under more stress to be seen as someone who has students with good grades rather than understanding and have to deliver course materials they don’t believe in but are forced to go through as those are the ones that are easy to mark.

Terrible, isn’t it? So why do people in our little world of web development constantly and voluntarily become this bad, bored and ineffective teacher?

What am I talking about? The thing I mentioned in large detail in my talk at BaconConf this year but here it is for the generation who wants things in 140 chars or as a cute image with large letters on it:

Whenever you answer a question of another developer with “just use $x” you breed an expert idiot. You did not teach them anything, you showed a way out of learning.

In my ongoing task to de-clutter my life I just un-subscribed from several communities on Google+, namely the HTML5 community and the JavaScript one. Not because I am not interested in these matters any more, quite the opposite: because I care much about these communities and all I found there is frustration and annoyance. Nearly every single question new developers have is answered in three ways:

  • Use jQuery – here is a plugin
  • Just Google for it
  • You’ll need to use framework $x / JavaScript and/or HTML5 is not good enough for that

None of these answers are satisfactory if you really want to help someone who needs to solve a problem and learn how to repeat the solution in the future. The latter in most cases is a plain lie and shows that you are blaming a technology for your lack of interest in it.

What gets answered far too quickly is the “how” – how to achieve a massively complex result (which yet has to be proven to be really necessary) without thinking about it or understanding the solution that you apply. We assume that is enough and that we are doing something good – we let a new developer have a positive experience of having something achieved very quickly and that will obviously entice him or her to learn more and go explore in more detail later on.

That is not necessarily the case. We showed people a shortcut and how to focus on the outcome and hope the step where they understand what they are doing comes later. Sadly in a lot of cases this never comes but it fills people with fake confidence that gets shattered once they have their first job interview in a real company who cares about what they build.

If you want to teach people, make them understand the “why” and let them find their own “how”. That is much harder work, but also much more rewarding when you see them grow and explore.

We do not teach people how to write by copying and pasting the style of other authors. We tell them about similes, metaphors, rhetoric devices, orthography and grammar rules. Why bother with that? We could just show them TXTSPK and explain that anyone who knows English will understand what they try to convey. The reason why we do it is that we teach the fun of playing with language and finding your own style.

“But I don’t have time for that – I just want to help someone solving their problem”

Is a very common, admirable, but misguided idea. What you do is advertise the solution that made most sense to you as you already solved the problem. You steal the learning experience away from the other person and the way we learn is our most personal asset and differs vastly from person to person.

If you don’t want to really teach and see people grow and learn on their own terms, please stop spouting truisms and “best quick solutions” in places where people come to learn. If all they want is for you to solve their issue, they should hire you to do so for them.

Don’t be the grumpy teacher you learned to first despise and later on pity. We can do better on the web.