subscript, superscript and line-heights

By default subscript (<sub></sub>) and superscript (<sup></sup>) tags are styled with vertical-align: sub, respectively vertical-align: super by most browsers.
However, without adaptations, this will probably break your line-heights.

A common suggestion is to style those two tags accordingly:

sup, sub {
  vertical-align: baseline;
  position: relative;
  top: -0.4em;  /* can be adapted according to preferences */
}
sub {  
...

A modern approach to SVG icons

You have some SVG files you want to use as icons on your website. How would you embed them?

Common options are:

  1. Use them with an image: <img src='path-to-icon.svg'>
  2. Embed them inline with <svg>$ICON</svg>
  3. Embed them using CSS and background-image: url(path-to-icon.svg) or even background-image: url(data:$ICON).
  4. Build your own icon font.

All of these have drawbacks:

  • Image and background-image do not allow to recolor the image using CSS.
  • Inline-<svg> are unnecessary work for the server and are...

Using path aliases in esbuild

In esbuild, you usually import other files using relative paths:

import './some-related-module'
import `../../utils/some-utility-module`
import `../../../css/some-css.sass`

This is totally fine if you import closely related files, but a bit clunky when you're trying to import some "global" module, like a utility module. When moving a file, your imports also need to change.

To get around this, esbuild support a mechanism first introduced in TypeScript called "path aliases". It works like this:

First, you create a file called `js...

Jasmine: Creating DOM elements efficiently

Jasmine specs for the frontend often need some DOM elements to work with. Because creating them is such a common task, we should have an efficient way to do it.

Let's say I need this HTML structure:

<ul type="square">
  <li>item 1</li>
  <li>item 2</li>
</ul>

This card compares various approaches to fabricating DOM elements for testing.

Constructing individual elements

While you can use standard DOM functions to individually create and append elements, this is extremely verbose:

let list = document.createElement('...

Inspect and Debug CSS Flexbox and Grid Layouts by using the Layouts Tab in Dev Tools

tl;dr

In Chrome DevTools in the Layouts tab you have handy options to debug CSS Flexbox and Grid. Including:

  • Display size and lines along with labels
  • Changing their attributes
  • Change how overlay is colored and fastly switch nested elements in the Elements panel

This guide will only cover some example gif recordings on how to use with Grid, since it's basically straight forward to apply this for Flexbox by yourself afterwards.

For this purpose a the link to documentation and a simple code pen have been added...

Chrome DevTools: Treasure (Overview)

tl;dr

The Chrome DevTools are a neat collection of tools for the daily work as a web developer. If you're lucky, you'll maybe find some handy stuff in here.

Analysing

Breakpoints

  • [Breakpoints on HTML Elements](https://makandracards.com/makandra/517982-chrome-devtools...

Sass: get rid of deprecation warnings in dependencies

TLDR: sass >= 1.35.0 has the option quietDeps to silence deprecation warnings from dependencies.

quietDeps: If true, the compiler must not print deprecation warnings
for stylesheets that are transitively loaded through an import path or importer.


You might have seen deprecation warnings like this during assets compilation:

DEPRECATION WARNING: Using / for division is deprecated and will be removed in Dart Sass 2.0.0.
Recommendation: math.div($grid-gutter-width, 2)
More info and automated migrator: https://sass-la...

What Sass means by "@function rules may not contain style rules."

When writing a Sass function, you may run into an error message that may be confusing:

@function rules may not contain style rules.

What Sass is trying to tell you is that a line in your Sass function is computing a result that is neither assigned to a variable nor returned.

Keep in mind that all functions in Sass return something, Sass does not mutate objects.

JSON APIs: Default design for common features

When you build a JSON API you need to come up with a style to represent attributes, pagination, errors or including associated objects. Instead of reinventing the wheel, you may reuse successful API designs.

JSON API

JSON:API specifies common features found in most JSON APIs, like pagination, ordering and nested resources. The spec looks very similar to how one would build an API with Rails and uses similar patterns. Even if you don't plan on supporting the whole spec, it can still make sense to know how th...

CSS: :is() pseudo selector

tl;dr

The :is() pseudo selector - specificity of its most specific argument - matches against a comma-separated list of selectors.

Example

Compound selectors like ...

.datepicker .prev, .datepicker .next, .datepicker .switch
  padding-bottom: 1rem

ul li, ol li
  list-style-type: none

can be simplified by using the :is() pseudo selector ...

.datepicker :is(.prev, .next, .switch)
  padding-bottom: 1rem

:is(ul, ol) li
  list-style-type: none

Hint

The specificity of :is() is equals t...

CSS: :where() pseudo selector

tl;dr

The :where() pseudo selector - zero specificity - matches against a comma-separated list of selectors.

Example

Compound selectors like ...

.datepicker .prev, .datepicker .next, .datepicker .switch
  padding-bottom: 1rem

ul li, ol li
  list-style-type: none

can be simplified by using the :where() pseudo selector ...

.datepicker :where(.prev, .next, .switch)
  padding-bottom: 1rem

:where(ul, ol) li
  list-style-type: none

Hint

The specificity of :where() is always zero!

I...

Flexbox: How to prevent <pre> elements from overflowing

I recently had the problem that embedded code boxes crashed my layout.

It turned out that pres break out of their containers when using them inside a deeper nested flex layout.
For me it was a flex inside a flex item (fleXzibit).

Image

<div class="flex">
  <div class="flex-item">
    ...
    <div class="nested-flex">
      <div class="nested-flex-item">
        <pre>A code example</pre>
      </div>
    </div>
    ...
  </div>
</div>

The reason is that flexbox items default to `mi...

Integrating ESLint

Introduction

To ensure a consistent code style for JavaScript code, we use ESLint. The workflow is similar to integrating rubocop for Ruby code.

1. Adding the gem to an existing code base

You can add the following lines to your package.json under devDependencies:

  "devDependencies": {
    "eslint": "^8.7.0",
    "eslint-config-standard": "^16.0.3",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-node"...

How to add esbuild to the rails asset pipeline

This are the steps I needed to do to add esbuild to an application that used the vanilla rails asset pipeline with sprockets before.

Preparations

  1. update Sprockets to version 4
  2. add a .nvmrc with your preferred node version (and install it)
  3. add gems jsbundling-rails and foreman to your Gemfile:
    gem 'jsbundling-rails'
    group :development, :test do
      gem 'foreman'
      # ...
    end
    
  4. bundle install
  5. run bin/rails javascript:install:esbuild in a console to prepare esbuild.
  6. run yarn install...

Better numeric inputs in desktop browsers

You want to use <input type="number"> fields in your applications.
However, your desktop users may encounter some weird quirks:

  1. Aside from allowing only digits and decimal separators, an "e" is also allowed (to allow scientific notation like "1e3").
    • Non-technical users will be confused by this.
    • Your server needs to understand that syntax. If it converts only digits (e.g. to_i in Ruby) you'll end up with wrong values (like 1 instead o...

Event delegation (without jQuery)

Event delegation is a pattern where a container element has a single event listener that handles events for all descendants that match a CSS selector.

This pattern was popularized by jQuery that lets you do this:

$('.container').on('click', '.message', function(event) {
  console.log("A message element was clicked!")
})

This technique has some advantages:

  1. When you have many descendants, you save time by only registering a single listener.
  2. When the descendants are changed dynamic...

Semantic HTML

Besides their default styling properties, HTML elements have a semantic meaning. For example, an h1 tag is usually styled with a larger font and bold, while it denotes "the single most important headline in its context".

While CSS enables us to style almost any HTML element like anything that is needed, choosing HTML elements corresponding to the meaning of their content has a few advantages:

  • HTML becomes a little clearer
  • Edge cases have already been considered and implemented:
    • Keyboard support (tabbing, arrow keys)
    • State...