An Engineering Competency Matrix for a Digital Agency

Developing the skills of our engineers is a key element of achieving our vision. A high-quality software development practice requires highly skilled engineers. We also know the experience of our customers correlates to the abilities of our team (higher quality work, smoother process) and our company culture is built around learning (“aspire to greatness” is one of our values).

To be recognised as North America’s leader in high-quality software development, customer experience, and company culture.

The Nolte Vision

In summary great engineers = great work = happy team + happy clients.

The Matrix

The below table shows the skills required by Nolte engineers, these are very focussed on the technologies we use.

The last 4 columns show which skills are required for each of the product types we work on. This does not mean one single engineer needs to have all these skills to work on the project, but the project team as a whole will most likely need to be able to cover them all.


We run the company on a quarterly OKR cycle, which includes setting training objectives. Each engineer meets with their manager to identify the skills they need for their job. For each skill they evaluate their current level based on the matrix and assign a priority based on the need to improve the skill (high priority means it is urgent to improve). For example:

SkillCurrent LevelRequired LevelPriority
WordPressNone [little or no experience]IntermediateHigh [About to start a WordPress project]
AnimationsNot requiredN/AN/A


In the near future we plan to integrate this matrix into promotion and compensation discussions. A possible option is to set minimum requirements for each seniority level along these lines:

  • Senior: must be expert in at least 4 key competencies*.
  • Mid-level: must be expert in at least 1 key competency* and intermediate in at least 2 others.
  • Junior: does not yet meet the requirements of Mid-level or Senior.

* Todo: define key competencies.

Further Reading & Thanks

This matrix was inspired by the following articles:

Also a big shout out to all in the Nolte team who provided feedback along the way

Keeping Gutenberg’s Core Columns Block Aligned to the Grid.

The WordPress Gutenberg editor comes with a load of power to create custom layouts. However, as Spiderman said, with great power comes great responsiblity… so how do we reduce the risk of our meticulously designed site being messed up by an editor who is not design-savvy?

In this post we are going to focus on one aspect of this, the core column block. Our designs are normally based on a 12-column grid, however the column block allows the editor to enter any percentage width they like for each column. This means they can create columns which are 5% or even 98% wide, ignoring our grid completely. What a mess they could make!

In the Lean theme we came up with a simple solution for this – the columns are automatically snapped to the nearest width allowed on a 12-column grid (ie a multiple of 8.333%). Here’s how we did it:

First we hooked into the render_block filter and called functions we’ll use to add classes to all core/columns blocks (the wrapper block for a set of columns) and all core/column blocks (an individual column).

You’ll note we used this WordPress PHP hook instead of a hook from the JavaScript API. We felt this is better for maintainability, as the hook updates the block at render time only. The JavaScript hook updates the block data which is saved to the database, this means any further changes to the saved HTML could invalidate existing blocks meaning they have to be fixed or even re-created.

We only need to add two classes to the core/columns wrapper: md:flex -mx-1. Using TailWindCSS these apply the necessary CSS properties to set up a flex grid within the container (see the TailWind flex grid documentation):

For now we’re using strpos and substr_replace functions to manipulate the HTML string. We could of course use a PHP DOM parser library to simplify this further.

Now the real magic happens on the individual column blocks. On mobile we want them to be full width so the columns stack, and then switch the to column layout from the medium breakpoint upwards.

First we get the % width set in the editor from the $block properties. This can be null if no widths are set at all – in this case we assume the user wants the columns to auto-size, so we don’t add any width class at all and let flex auto-size them.

Then, assuming a width is set, we round it to the nearest factor of 12 / 100 to snap it to the closest width available on a 12 columns grid. In TailWind we use the w-1/12, w-2/12, … w-11/12 classes to achieve this.


This is definitely a quick fix, a better solution would be to customise the core/column block width controls (or replace the block with a completely custom one) so the user has to select some sort of “columns to span” amount. This is quite a bit more complex, as it involves building the logic to ensure the total is always 12, as well as some other probably gotchas.

I hope this was useful or at least a little interesting. You can contact me at or via the comments section if you have any questions, comments or suggestions. Also check out these resources:

  • My Lightening Talk on Building a Gutenberg Enabled Theme for Non-designers.
  • The full gist of this code example.
  • A working example in the blocks section of the Lean Theme.

Slow Running Animations in Safari

I came across this problem whilst working on this CSS-only continuous ticker slider. It stumped me for a while and I couldn’t find any good information online, so I hope this is helpful.

The Problem

Checkout the animations below:

You can see the Safari version (on the right) runs much slower than specified in the CSS. On desktop, I found this occurs the 2nd or 3rd time the page is loaded after clearing the cache or making a change to the CSS animation property. On mobile it normally happened on the first page load.

The problem was tricky as it did not occur consistently. Some hunting around on the web gave me some clues that this was an optimisation, Safari is throttling animations which it determines as not important. The criteria are not clear, but it appears some sort of interaction with the element will decrease the risk of this happening.

The fact this happened more often on mobile reinforced this theory, I would expect any optimisations to be stricter on mobile devices which generally have less resources than laptops or desktops.

The Solution

After some trial and error, I found that activating the animation when the element scrolls into view fixed the problem. This makes some sense, as it’s more efficient to only animate an element when required and not as soon as the page loads (assuming the browser doesn’t optimise for this automatically). Some JavaScript is required for this:

import 'intersection-observer' // Polyfill for older browsers which haven't implemented the IntersectionObserver API.

 * Function that triggers the image strip animation on scroll.
export default function scroll () {
  const animTriggerClass = 'anim-image-strip-trigger'
  const animElems = document.getElementsByClassName( 'js-image-strip' )

  const io = new IntersectionObserver(
    entries => {
      entries.forEach( entry => {
        if ( entry.intersectionRatio > 0 ) {
 animTriggerClass ) 
          io.unobserve( )

  animElems.forEach( element => {
    io.observe( element )

Then update my CSS to trigger the animation when the anim-image-strip-trigger class is added:

.anim-image-strip-trigger {
    animation: ticker-kf 18s linear infinite;

In Summary

The problem has a relatively simple solution, the hard part was figuring out what the root cause was. It would be nice if Apple documented this along with guidelines for how animations should be used in Safari for optimal performance. It would also have been really helpful if they output a warning in the console instead of leaving engineers guessing!

A Continuous Image Ticker Built With Pure CSS

When working on a continuous image ticker slider for a new project I was surprised to find no JavaScript slider libraries which support this feature. After some back and forth with my designer on some alternatives, I decided to implement it as designed. In fact, it’s possible to do with pure CSS if you know the width of each item in the slider.

The Theory

Some important info:

  • There are 6 items in my ticker and each is 16rem wide with a space of 2rem between them. So in total the ticker width is (16 + 2) * 6 = 108rem.
  • I want 10 items to scroll by every 30 seconds, or in other words each item should scroll through in 3s. In this example I want 1 cycle of the ticker animation to last 3 * 6 = 18s.

Once the animation is complete it will leave a big white space on the right, which we don’t want. I got round this by duplicating the slider items in my PHP template. This works on the assumption that the total slider width is greater than or equal to its container, however if this doesn’t hold true you could duplicate the slides 3 or more times as required.

Now once the ticker has slid one full length I reset it back to the beginning to start again. If my maths is correct the reset will be seamless and the ticker will appear to be continuous!

In Practice

First let’s build the HTML. I’m using TailWind to set the layout (check out their flexbox grid documentation):

<!-- Wrap the slider in div with overflow hidden to hide scrollbars -->
<div class="overflow-hidden">

  <!-- The slider itself is a flex grid -->
  <div class="flex -mx-4 img-ticker">

    <!-- Original set of images -->
    <!-- Each image is a grid column with width 16rem (w-64) and horiztonal margin 1rem (mx-4) -->
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">

    <!-- Copy set of images -->
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">
    <img class="w-64 mx-4 self-start flex-none" src="">


Note how the slider items are repeated twice.

Now we can create our CSS keyframes using the slide distance I calculated above:

@keyframes ticker-kf {
  0% {
    transform: translate3d(0, 0, 0);

  100% {
    transform: translate3d(-108rem, 0, 0);

This makes the slider move one full slider width to the right. Note I’m using translate3d as it has been proven to be the most efficient translation across all browsers.

Now let’s apply it using the following CSS:

.img-ticker {
  animation: ticker-kf 18s linear infinite;

This will execute the animation over 18s using a linear easing curve so the speed remains the same throughout. Finally we tell the browser to reset and repeat on an infinite loop.

Et voila! We have a pure CSS ticker!

As I did, you can go on to make this solution more flexible by using your templating engine to calculate and output the required keyframes and CSS animation property based on the number of items.

Check out the complete solution on codepen:

See the Pen Pure CSS Ticker Slider by Adam Fenton (@adamf321) on CodePen.

A Note on Design Fidelity

The original design has the image widths follow our fluid 12 column grid. This meant some complex calculations (which are not possible to do on the server-side) in the case where the slider stretched outside the container to the full viewport width. However, we realised the constant movement makes it impossible to see any misalignment, so I simplified the slider by compromising on 2 fixed widths (one for mobile and another for desktop).