Today I Learned

We are all on an adventure of daily learning. This journey happens to belong to a frontend developer, Neil Magee.

In an attempt to catalogue and not forget what has been learnt, this blog will record it for the future.

Controlling Tailwind

Today I learned how to control Tailwind. I am planning on using Tailwind on an upcoming project and in order to put something new like this onto a production website, I need to understand it deeply.

Tailwind out of the box

/* input.css */
@tailwind base;

@tailwind components;

@tailwind utilities;
// tailwind.config.js
module.exports = {
  theme: {},
  variants: {},
  plugins: []
# command
tailwind build input.css -o output.css

Putting the above together and running the command will output a css file that is 54309 lines of code and 854.59KB in file size! The developers talk about this on the official site and it is not the recommended way to use Tailwind. What I needed to know was what config settings could create a very minimal output that I could add to as I needed it.

Material UI theming and style overrides - Part 5

Today I learned that sometimes a refactor is not always better, just different. I followed through with my plan to split my styles out into individual modules:

// Example styles module 'body.js'
import CustomTheme from "../../Theme";

export default {
  formBuilder: {
    paddingBottom: CustomTheme.spacing(8)
  formBuilderContainer: {
    maxWidth: "770px",
    padding: 0

That module sits in a /Styles folder, at the same level as my container component, and is exposed via an index.js file like so:

export { default as body } from "./body";
Material UI theming and style overrides - Part 4

Today I learned I still don’t have a good answer when it comes to managing CSS-in-JS. Last time I discussed this topic I had decided to make a single Styles.js object that contained style overrides to Material UI. I consolidated all my components styles into that Styles.js file. Abbreviated example below:

import CustomTheme from "../Theme";

const Styles = {
  formPreviewContainer: {
    maxWidth: "770px",
    paddingTop: CustomTheme.spacing(8),
    paddingBottom: CustomTheme.spacing(8)
  formHeader: {
    position: "relative",
    paddingTop: CustomTheme.spacing(4),
    paddingBottom: CustomTheme.spacing(4),
    paddingLeft: CustomTheme.spacing(4),
    paddingRight: CustomTheme.spacing(8),
    marginBottom: CustomTheme.spacing(4),
    backgroundColor: CustomTheme.palette.primary.main
  // ... other styles omitted for brevity ...
  textInput: {
    "& .MuiInput-underline:before": {
      borderBottom: `1px solid ${CustomTheme.palette.grey[300]}`
    [CustomTheme.breakpoints.down("sm")]: {
      width: "100%"
    [CustomTheme.breakpoints.up("md")]: {
      width: "50%"
  textArea: {
    width: "100%",
    "& .MuiInputBase-input": {
      lineHeight: "24px"
    "& .MuiInput-underline:before": {
      borderBottom: `1px solid ${CustomTheme.palette.grey[300]}`

export default Styles;

Hugo theme improved pagination

Today I learned how to do numbered pagination in my Hugo theme using golang. This was a bit harder than I expected as I am no expert on programming with golang. But once I remembered that golang still follows the same programming conventions that other languages do, even though the syntax is different.

After the posts in my theme, there is a simple navigation area at the bottom. At the moment it looks like this:

An image of my Hugo themes current pagination

My current pagination

Using web fonts in email campaigns

Today I learned to keep following my intuition.

TLDR Use woff, not woff2 for web fonts in email

I had been asked a question by our art director today about using web fonts in an email campaign that was being designed. The company we are designing for has a corporate identity that specifies certain font families. I had already begun to test this back in March so I had an idea of the state of web font support in email clients.

Before I answered him more definitively, I wanted to perform a few tests using our email marketing software — Campaign Monitor — to confirm what could be achieved.

React Redux is pretty great!

Today I learned to really appreciate React Redux. I have used Flux like patterns only a handful of times. Mainly in Vue using Vuex. But it’s been a while since I last used one.

I am in the middle of building a prototype App in React and the “main” component was becoming unwieldy. It contained all the main state, all the functions that were passed to child components as props and the way things were going, it was about to become responsible for asyncronous data as well. That is too much for one component.

Controlled inputs and performance

Today I learned about the performance impact of using controlled inputs in React.

I noticed that once I had multiples of a component I’d made on screen (that included text inputs) the typing performance would begin to lag. It also got exponentially worse for each additional component.

onChange vs onBlur

The main difference I tried was changing my event from onChange to onBlur (this was based on some Stack Overflow advice).


Animated gif showing poor input performance

Laggy input performance