Copywriting for Interfaces – Takeaways

Here’s what I’ll try to remember from UX Planet’s great article on Copywriting for Interfaces.

  • Headlines should be catchy and short so that they could quickly draw users’ attention
  • The perfect length of the headline is 6 words (underlying research)
  • Captions should provide new information so it shouldn’t describe obvious statements which users already see in the photo.
  • Keep CTAs at a minimum, usually not more than 1–2 words
  • Applying imperative case in CTA microcopy gives strong and direct instructions of what to do next.
  • Notifications with less than 25 characters perform much better than long text.
  • Error messages should be polite and friendly. A bit of humor can relax annoyed users but must be used carefully.
  • Place an UI element that offers further action close to an error message.
  • Tooltips work best when having 150 characters or less

Prevent Object-fit polyfill from messing with broken image’s alternative text styling

That is a hell of a long title for a very short post.

If you’re using the Object Fit Images Polyfill you might have noticed that broken images’ alt texts render in Times New Roman. This happens because Object Fit Images  works by setting a faux font-family on the image, which is then used by JavaScript. The problem is that the browser tries to render a broken image’s alt text which, of course, doesn’t exist. So it falls back to whatever the browser uses as default. 

To prevent this we can simply add inherit to our font-stack of the image: 

// When using Object Fit Images Manually
img {
object-fit: cover;
font-family: "object-fit:cover", inherit;

So what if you’re using PostCSS Object Fit Images to automatically add that font family to any selector that employs object-fit? Luckily it respects any existing font declaration and adds it to the font stack. So we can simply add the inherit statement directly:

// When using PostCSS Object Fit Images 
img {
object-fit: cover;
font-family: inherit;

The result in both cases is: font-family: "object-fit:cover", inherit; and allows for the polyfill to do its thing while at the same time setting the font-family to the one used in the next proximate parent.

Stretch SVG Background Images

The next time I’m going mad when trying to stretch a SVG background image using background-size I’ll remember adding preserveAspectRatio="none" to the SVG itself. Otherwise it’s gonna stick to its original aspect ratio like its life depends on it.

MAMP MySQL repair fails with Access Denied

mysqlcheck: Got error: 1045: Access denied for user ‘root’@‘localhost’ (using password: YES) when trying to connect

I have no clue where the MAMP GUI tries to take the credentials from when running checks and repairs. It just never seems to work.

The solution that worked for me, however, is to simply run mysql_upgrade -uroot -p on the command line. Don’t forget to check that MAMP’s mysql binary is in your PATH, because it is not by default. To do so add to your shell’s config (that’s .zhsrc for me) and restart your terminal:
export PATH="/Applications/MAMP/Library/bin:$PATH"

Et voilà:

Upgrade process completed successfully.
Checking if update is needed.

Using CSS Blur to add full-width image background

Many designs require the implementation of full-width imagery while restricting the component’s height at the same time.

Blurred Hero Component

Today I came up with this simple idea that may help in some situations: Put a blurred version of the hero image in the background, reduce its opacity and make it span the entire width. Place the actual image above and restrict its width to a dimensions that makes it easier for content editors to find a fitting image.

Bonus points: when using a small resolution for the blurred image it could serve as a placeholder while loading the high res version.

Decoupled Drupal mit Gatsby

Heute kam ich endlich mal dazu, dieses Tutorial zu Decoupled Drupal mit GatsbyJS nachzubauen. In kürzester Zeit war Folgendes möglich:

  • CMS-Setup inklusive Einrichten der JSON-API
  • Anlegen einer von Drupal völlig unabhängigen statischen Site, die CMS-Content von der API konsumiert und rendert.

Oh, ich freu mich auf die Zukunft und auf reale Projekte mit Drupal als Headless CMS. Ungeahnte Möglichkeiten öffnen sich.

Re-use and override TailwindCSS Configuration

TailwindCSS is hands-down my most useful CSS tool of 2017. It’s a fantastic helper to create utility-first CSS. I’ve been working with it since its first public release and I’m still more than happy to have it.

Today I found out a way to make it even more useful. Say you’re having a Parent Theme that you use for a lot of projects, where each project implements a child theme that needs to adjust properties such colors, breakpoints or font stacks. That’s as simple as requiring your Parent Theme’s tailwind.js, override or add properties and export the adapted config.

const config = require('../parent_theme/tailwind');

config.colors['grey'] = '#eee'
config.screens['md'] = '32em'

module.exports = config;


Composer PHP Memory Limit on MAMP Pro

With every PHP update MAMP Pro adds an updated `php.ini file, so previous adaptations are lost after upgrading.

Interestingly, editing a specific PHP versions config file (via File > Edit Template > PHP -> [Version]) doesn’t have any effect on MAMP’s PHP used on the command line. To increase the PHP limit to be able to work with Composer I did the following:

  1. Find the current memory_limit value by running:
    php -r "echo ini_get('memory_limit').PHP_EOL;“
  2. Find out which php-ini is currently loaded on the command line by running:
    php -r 'phpinfo();' | grep 'php.ini'
  3. Update that config file

Rinse and repeat with every MAMP update.

Design Better

Discover. Learn. Elevate.
Introducing the best practices, stories, and insights from the world’s top design leaders. Loaded with in-depth books, podcasts, and more, DesignBetter.Co is your essential guide to building remarkable products and teams.

Set Front Page from settings[.local].php in Drupal 8

When working on Drupal projects I usually need to set a static front page by referencing a Node’s ID. When working with different environments chances are high that Node ID varies from environment to environment.

Luckily we can easily override any configuration value in the settings file and thus have different values in settings.php than in settings.local.php. It’s simple as that: $config['']['page']['front'] = '/node/1';

Drupal: Add Body Class when Tabs are displayed

I had the urge to style various elements differently in case tabs (the ones generated by menu_local_tasks) are present on the page. Out of the box $tabs array isn’t available in html.tpl.php so I had to implement ‘ hook_preprocess_html’ and add my desired class to my array of body classes. Yay!

function THEMENAME_preprocess_html(&$vars, $hook) {
  // Make tabs available on html tpl
  $vars['tabs'] = menu_local_tabs();
  // if we have primary tabs, add an accoring body class
  if (!empty($vars['tabs']['#primary'])) {
    $vars['classes_array'][] = 'has-tabs';

Unmaintainable Block Admin Page in Drupal

When you have more than 100 Blocks things get messy on Drupal’s Block Admin Interface. If you ever went crazy because of weird issues when dragging and dropping blocks to change their weight and/or region you probably have hit Drupal’s internal limit of handling weights from -50 to +50 or otherwise said, 100 items.

It can be fixed by setting the variable drupal_weight_select_max to a higher value. This can be done in various ways, here’s how its implemented in a deploy script.

function dgm_deploy_update_7011() {
  variable_set('drupal_weight_select_max', 250);

Programmatically manipulate a Node’s field value upon saving 

For a recent project we needed to automatically change a Node’s field value upon saving with a computed value. For an unrelated reason we needed this value to be in a regular text field, so using Computed Field was off the table.

It turned out to be really simple to accomlish with a minimal amount of custom code.

 * Changes the value of field_marker to a string made up of the
 * Node's type and the value of it's category taxonomy term
 * Slashes will be replaced with deshes, spaces get removed
 * Must make sure that the following exists:
 *  - text field "field_marker"
 *  - node types "gesuch" and "angebot"
 *  - taxonomy reference field "field_category"

// Helper function to keep our code
function save_marker_category($node) {
  if($node->type == 'gesuch' || $node->type == 'angebot') {

    $find = array('/', ' ');
    $replace = array('-', '');

    $category_object = taxonomy_term_load($node->field_category['und'][0]['tid']);
    $category =  trim(strtolower(str_replace($find, $replace, $category_object->name)));

    $type = $node->type;
    $node->field_marker['und'][0]['value'] = $type.'_'.$category;

    // Save the new value
    field_attach_update('node', $node);

function MYMODULE_node_update($node) {

function MYMODULE_node_insert($node) {

Slick Slider inside Table Display

Today I ran into an issue when trying to use Slick Slider within an element that has display: table. The layout broke almost completely and in all browsers on small width viewports. Simply adding table-layout: fixed; to the element that has display: table solved it.

HTML Template per Node Type

In case you need a different html.tpl.php on a per content type basis in Drupal 7

function THEME_preprocess_html(&$vars) {
  $node = menu_get_object();
  if ($node && $node->nid) {
    $vars['theme_hook_suggestions'][] = 'html__' . $node->type;