Category: Software Development

Adjust text color to be readable on light and dark backgrounds of user interfaces

Most modern user interfaces are supporting different color schemes for day and night: the so called light and dark modes. Selecting a text color for each of those modes is not a big deal and it’s the way to go when designing the user interface.

In some cases, the text color is driven by the displayed contents. In the example below, the tint color is matched to the color of the drink. The global tint color of this app is totally different, but this color adjustment gives a very nice effect. But as you might already see, there is a small problem when it comes to very light or very dark colors: each color either has a good readability on light or dark backgrounds. Some colors might fit to both, but that’s not always the case. In the example below, the light yellow is still visible, but when it comes to small icons or small text, the details are lost.

To overcome this issue, a simple solution is to select two colors for each recipe so that each mode has a different one. That’s fine, but it might totally change the effect of this colored pages.

Can we calculate a suitable color?

Some time ago, there was an article about Black or white text on a colour background? In this one, I described different algorithms to calculate the best text color (black or white) for a colored background. But now, we need the opposite: a colored text that has a good readability on white (light) or black (dark) backgrounds.

When we look at HSL and HSV/HSB color models, we already have a value for ‘lightness’ or ‘brightness’. The idea is to find a color that matches a given hue and saturation and that has a brightness which is readable on light and dark background. For this, we can use different algorithms. Very good results could be achieved with a ‘Weighted W3C Formula‘. This formula take into consideration that the human eye perceives some of the primary colors darker than others.

f'(x) = r ? 0.299 + g ? 0.587 + b ? 0.11

Each color that is located at the border between the black and white overlay is suitable for light and dark backgrounds.

Step 1: convert the given color to HSV/HSB

Step 2: keep hue and saturation constant and adjust the brightness (make the color lighter or darker)

Step 3: convert the HSV/HSB value back to the required color format

Implementation in PHP

A simple calculation for a given RGB color is shown below. The classes used in this snippet are available on GitHub. The code checks the initial brightness of the color and lightens or darkens the values until the ‘border’ calculated by the ‘Weighted W3C Formula’ is reached. This is the case for the value 127, the total range of the brightness is 0 to 255.

$hsv = Convert::rgb2hsv($rgb);

$step = 0.01;
$brightness = Calculate::weightedW3C($rgb);
if ($brightness < 127) {
    while ($brightness < 127 && $hsv[2] >= 0 && $hsv[2] <= 1) {
        $hsv[2] += $step;
        $brightness = Calculate::weightedW3C(Convert::hsv2rgb($hsv));
    }
} else {
    while ($brightness > 127 && $hsv[2] >= 0 && $hsv[2] <= 1) {
        $hsv[2] -= $step;
        $brightness = Calculate::weightedW3C(Convert::hsv2rgb($hsv));
    }
}

return Convert::hsv2rgb($hsv);

Some examples

But how does this result look for different colors? Let’s start with some dark colors. Those are fine for a light background, but they become unreadable on a dark one. The top colors show the input color (before) and the color below shows the output of the calculation above (after).

Color #632300 adjusted to be readable on light and dark background
Color #454545 adjusted to be readable on light and dark background

And now let’s look at some light colors which are fine for dark backgrounds, but they are totally unreadable on light backgrounds.

Color #73FEFF adjusted to be readable on light and dark background
Color #F0C&96 adjusted to be readable on light and dark background

The last color is similar to the example at the beginning and as you can see, the optimized color has a much better readability. This could be achieved for both light and dark colors. The code example shown above is written in PHP. An adoption should be easily possible for any other coding or scripting language

The algorithm mentioned in this post is also available on GitHub https://github.com/mixable/color-utils. This package is usable with composer:

composer require mixable/color-utils

The optimized color can be calculated with:

use Mixable\Color\Calculate;
// ...

$hex = '#ffcc00';
$optimizedColor = Calculate::readableColorForLightAndDarkBackground($hex);

Xcode: how to disable an extension during app build

Sometimes the development version of an app includes multiple code e.g. an extension that should not be released yet. In this case, it’s possible to exclude the extension when building an app. This keeps all your code, but does not include the extension during the build phase.

To achieve this, simply open the Build Phases of your main app and remove the extension(s) from Dependencies and Embed App Extensions. You can add the extension later when required.

Below is a screenshot of the setting in Xcode.

Photo by Clément Hélardot on Unsplash

Quick Look plugins for software development

Quick Look already supports multiple file types. But there ist more – especially for software development. Here are some plugins that make Quick Look even better.

Note: some of the plugins might not work instantly after brew install ... when you are on macOS Catalina or later. In this case, it is possible to download the plugin manually and copy the .qlgenerator file to ~/Library/QuickLook. This requires to run qlmanage -r (or a system restart) to enable the plugin.

QLMarkdown

QLMarkdown provides QuickLook support for markdown files (*.md). This plugin renders the markdown content and shows the result. To install QLMarkdown, use:

brew cask install qlmarkdown

For manual installation, the plugin is available at https://github.com/toland/qlmarkdown.

QLStephen

This Quick Look plugin provides a file preview for files without extension, e.g. README, INSTALL, Capfile, CHANGELOG, etc. It can be installed using Homebrew:

brew cask install qlstephen

For manual installation, the plugin is available at https://github.com/whomwah/qlstephen.

QLColorCode

This is a Quick Look plug-in that renders source code with syntax highlighting. To install the plugin, use Homebrew:

brew cask install qlcolorcode

For manual installation, the plugin is available at https://github.com/anthonygelibert/QLColorCode. If you want to configure QLColorCode, there are several defaults commands that are described on the download page.

Quick Look Json

This is a Quick Look plug-in that renders json files. To install the plugin, use Homebrew:

brew cask install quicklook-json

For manual installation, the plugin is available at http://www.sagtau.com/quicklookjson.html.

WebP QuickLook

This is an open-source QuickLook plugin to generate thumbnails and previews for WebP images. To install the plugin, use Homebrew:

brew install webpquicklook

For manual installation, the plugin is available at https://github.com/dchest/webp-quicklook.

Something is missing? Please let me know in the comments, if there are any other plugins that might be helpful for software development.

Photo by Shane Aldendorff on Unsplash

UX improvements: `enterkeyhint` to define action label for the keyboard of mobile devices

Usability

The enterkeyhint is a html attribute described in the HTML standard, which can be used to improve the context of action buttons of keyboards on mobile device.

The enterkeyhint content attribute is an enumerated attribute that specifies what action label (or icon) to present for the enter key on virtual keyboards. This allows authors to customize the presentation of the enter key in order to make it more helpful for users.

It allows the following fixed values: enter, done, go, next, previous, search and send. Let’s have a look at those values and the resulting keyboard style on iOS:

<input>

The default behavior without any value.

<input enterkeyhint=”enter”>

The user agent should present a cue for the operation ‘enter’, typically inserting a new line.

<input enterkeyhint=”done”>

The user agent should present a cue for the operation ‘done’, typically meaning there is nothing more to input and the input method editor (IME) will be closed.

<input enterkeyhint=”go”>

The user agent should present a cue for the operation ‘go’, typically meaning to take the user to the target of the text they typed.

<input enterkeyhint=”next”>

The user agent should present a cue for the operation ‘next’, typically taking the user to the next field that will accept text.

<input enterkeyhint=”previous”>

The user agent should present a cue for the operation ‘previous’, typically taking the user to the previous field that will accept text.

<input enterkeyhint=”search”>

The user agent should present a cue for the operation ‘search’, typically taking the user to the results of searching for the text they have typed.

<input enterkeyhint=”send”>

The user agent should present a cue for the operation ‘send’, typically delivering the text to its target.

Photo by Melisa Hildt on Unsplash

Synology: How do I update an existing Docker container with a new image?

As always: before you do such an update, make sure to create a backup of all your files. If something goes wrong, this may lead to data loss!

To update an existing Docker container, the following steps are necessary;

  1. Go to Registry and download new image (mostly the “latest” version)
  2. Go to Container, select the container you need to update and stop it
  3. From Actions menu select Clear
  4. Start the container again

This will clear the complete container and start with the newly downloaded Docker image. Since the data folders are mounted into the container, this will not erase the apllications data. Configurations are also not affected by this.

Photo by sergio souza on Unsplash

Android Studio: when shortcuts do not work on macOS

Compared to other IntelliJ® based software, some shortcuts in Android Studio did not work for me. For example cmd + shift + F, which should open the global search did not work.

The reason for this is the keymap setting that was set to IntelliJ IDEA Classic. Setting the keymap to macOS (as shown in the figure below) solved the issue.

Android Studio Keymap settings

Run GitLab console on Synology NAS

As the Synology DSM uses Docker to run GitLab, we can use Docker as well to install GitLab Runner. For this, connect to the Synology using SSH:

ssh <admin-user>@<synology> -p <port>

To connect to the GitLab container, you can use the following command to open:

docker exec -it synology_gitlab /bin/bash

You might adjust the name of the GitLab docker depending on your system.

To open the console, run:

gitlab-rails console

When GItLab is installed using the DSM package manager, just use the following commands:

cd /home/git/gitlab/bin
./rails console production

Commands for the console

Below are some examples how to use the GitLab console.

Check the mail delivery method

ActionMailer::Base.delivery_method

Output might be: => :smtp

Check the smtp settings

ActionMailer::Base.smtp_settings

Output might be: => {:address=>"example.com", :port=>25, …

Testing the SMTP configuration (see documentation)

Notify.test_email('mail@example.com', 'Subject', 'Mail Body').deliver_now

GitLab on Synology: set ‘external_url’

There are two (or even more) solutions to install GitLab on a Synology:

  • Using Docker and the container gitlab/gitlab-ce
  • Using the DSM package manager

Depending on the type of installation, different settings are required to update the external url.

Using Docker container

The external url of GitLab can e defined in /etc/gitlab/gitlab.rb. The parameter takes an url and can also handle a port:

external_url 'http://example.synology.me:30000/'

Important: when a port is specified in external_url, this will override the https/https port where nginx is listening. To use a different port for nginx, this requires an additional setting:

nginx['listen_port'] = 80

After changing this setting, it’s necessary to run:

gitlab-ctl reconfigure

The settings above are necessary, if port routing is set like the following:

Using DSM package manager installation

This installation of GitLab on Synology uses localhost as a default value for external url. This may lead to some problems when accessing GitLab over another IP or host name. In my case, this lead to missing icons and a non functional WebIDE. An inspection of the html page shows, that some resources are requested over http://localhost/... which leads to 404 errors for those resources.

Since the GitLab container on Synology is not based on the omnibus package, you can not use directly external_url in /etc/gitlab/gitlab.rb. If you want to change the url you can do it by changing the docker environment parameter GITLAB_HOST.

GitLab on Synology: Environment settings