I previously noted Keith J Grant’s article on the HTML dialog element which promised a native means of handling popups and modal dialogues. I’ve not yet used dialog in production, partly because of spotty browser support (although there is a polyfill) but also partly because—for reasons I couldn’t quite put my finger on after reading the spec—it just didn’t feel like the finished article.
Fast forward to March 2019 and Scott O’Hara has written an excellent piece describing why it’s still not ready. There are a combination of factors: lack of browser support, reliance on JavaScript; and multiple accessibility issues.
Sometimes when coding a UI element you want a shadow around the whole box. However, most CSS box-shadow examples/tutorials tend to show inset box-shadows or ones that otherwise sit off to the side.
Here’s how to apply box-shadow to the whole box for a simple but nice effect.
The fairly-recently added <details> element is a great, native HTML way to toggle content visibility.
<p>Lorem ipsum dolor sit amet.</p>
<details>
<summary>System Requirements</summary>
<p>Requires a computer running an operating system. The computer
must have some memory and ideally some kind of long-term storage.</p>
</details>
When taking the DIY approach to building a new server, Certbot is a great option for installing secure certificates. However, sometimes you can run into problems. Here, I review the main recurring issues I’ve encountered and how I fixed them.
When creating new servers for my projects I use Certbot as a means of installing free Let’s Encrypt secure certificates.
It’s great to be able to get these certificates for free and the whole process is generally very straightforward. However, since working with Let’s Encrypt certificates over the last few years I’ve found that the same recurring questions tend to plague me.
This is a note to “future me” (and anyone else it might help) with answers to the questions I’ve pondered in the past.
How do I safely upgrade from the old LE system to Certbot?
For servers where you previously used the 2015/2016, pre-Certbot Let’s Encrypt system for installing SSL certs, you can just install Certbot on top and it will just work. It will supersede the old certificates without conflict.
How do I upgrade Certbot now that Let’s Encrypt have removed support for domain validation with TLS-SNI-01?
Essentially the server needs Certbot v0.28 or above. See Let’s Encrypt’s post on how to check your Certbot version and steps to take after upgrading to check everything is OK. To apply the upgrade I performed apt-get update && apt-get upgrade -y as root although depending on when you last did it this might be a bit risky as it could update a lot of packages rather than just the Certbot ones. It might be better to just try sudo apt-get install certbot python-certbot-apache.
To what extent should I configure my 443 VirtualHost block myself or is it done for me?
When creating a new vhost on your Linode, DigitalOcean (or other cloud hosting platform) server, you need only add the <VirtualHost *:80> directive. No need to add a <VirtualHost *:443> section, nor worry about pointing to LE certificate files, nor bother writing rules to redirect http to https like I used to. When you install your secure certificate, certbot will automatically add the redirect into your original file and create an additional vhost file (with extension -le.ssl.conf) based on the contents of your existing file but handling <VirtualHost *:443> and referencing all the LE SSL certificate files it installed elsewhere on the system.
How should I manage automated renewals?
There’s no longer any need to manually add a cron job for certiticate renewal. Auto-renewal of certificates is now handled by a cron job which comes bundled with the certbot package you initially install – in my case usually a certbot ppa package for Ubuntu 16.04 or 18.04. However you won’t find that cron job in the crontab for either your limited user, nor the root user. Instead, it is installed at a lower level (/etc/cron.d) and should just work unless you’ve done something fancy with systemd in your system which in my case is unlikely.
How can I tell if renewals are working and what should I do if they’re not?
If you notice that the SSL certificate for your domain is within 30 days of expiry and hasn’t yet auto-renewed, then you know that something has gone wrong with the auto-renewal process. You can test for problems by running sudo certbot renew --dry-run. You may find that there is, for example, a syntax error in your apache2.conf or nginx config file which needs corrected – not that I’ve ever been guilty of this, you understand…
In all my years of spinning up “HTML Typographic Elements” lists or pages as a reference for designers, I didn’t realise that the W3C provide the very thing I needed in their HTML Element Sampler. These pages provide comprehensive dummy content covering all the main typographic elements which is really handy when designing a website’s typographic styles and pattern library.
Recently, we’d seen some articles suggest that things haven’t changed a great deal with select's styling limitations, but I decided to return to the problem and tinker with it myself to be sure. As it turns out, a reasonable set of styles can create a consistent and attractive select across new browsers, while remaining just fine in older ones too.
Here’s a breakthrough in the always-frustrating field of styling form elements. Scott Jehl of Filament Group introduces a new technique for styling the select element in a modern way without the need for a parent element, pseudo-elements, or javascript. Thanks, Scott!
A brief explainer (for future-me and anyone else it helps) on what promises are and how to use them. Note: this is not an official definition, but rather one that works for me.
In the normal run of things, JavaScript code is synchronous. When line 1 has run (perhaps defining a new variable) and the operation has completed, line 2 runs (perhaps operating on the variable we just defined). However sometimes in line 1 we need to do something which will take longer – maybe an unknown length of time – for example to call a function which fetches data from an external API. In many cases we don’t mind that taking a while, or even eventually failing, but we want it to execute separately from the main JavaScript thread so as not to hold up the execution of line 2. So instead of waiting for the task to complete and return its value, our API-calling function instead returns a promise to supply that value in the future.
A Promise is an object we use for asynchronous operations. It’s a proxy for the success value or failure reason of the asynchronous operation, which at the time the promise is created is not necessarily yet known.
A promise is in one of three states:
pending
fulfilled (the operation completed successfully)
rejected (the operation failed)
We say a pending promise can go on to be either fulfilled with a value, or rejected with a reason (error).
We also talk about a promise being settled when it is no longer pending.
One memorable analogy was provided in Mariko Kosaka’s The Promise of a Burger Party. In it she describes the scenario of ordering a burger from, say, Burger King. It goes something like this:
you place your order for a Whopper;
they give you a tray with a buzzer. The tray is a promise that they will provide your burger as soon as it has been cooked, and the buzzer is the promise‘s state;
the buzzer is not buzzing to start with: it’s in the pending state;
the buzzer buzzes: the promise is now settled;
they might inform you that their flame-grill broke down half-way through. The cooking operation failed, and the promise of a burger has been rejected with that reason. You’ll likely want to act on that (by getting a refund);
alternatively all goes to plan, you go the counter and they fulfil their promise of a tasty burger placed onto your tray.
you decide you want to act on the success of getting your tasty burger by doing another thing, namely buying a coke. In code you’ll be within the .then() method which is the success handler for your promise and in there you can just call buyCoke(). (Note: the buyCoke() operation might be synchronous; the real life analogy being that it’s so quick to pour a coke that the assistant does it and serves it on a tray immediately rather than giving you a tray as a promise for it.) At the end of your then() you might choose to return a meal object which combines your burger and coke.
You could then chain a further .then() to the original .then() to work with your snowballing data value. This is because then() methods always return a promise (even if the operation within was not asynchronous), and we already know that promises are thenable (i.e. have a then() method) hence our ability to keep chaining.
Promise syntax
There are two things we need to be able to do with promises:
create and return them;
work with a returned promise.
Create and return a promise
When you create a promise you pass a function known as the executor to it, which runs instantly. Its arguments resolve and reject are callbacks provided by JavaScript. Our code goes inside the executor.
let examplePromise =newPromise(function(resolve, reject){// do a thing, possibly async, then…if(/* everything turned out fine */){resolve("Stuff worked!");}else{reject(Error("It broke"));}});
I’ve used Git for many years but it can still trip me up. At times I’ve worked primarily in a GUI (like Sourcetree or Fork), and other times directly on the command line. I’ve worked on projects where I’ve been the sole developer and others where I’m part of a large team. Regardless of the tools or context, I’ve learned there are certain need-to-knows. Here’s a list of useful Git concepts and commands for my reference and yours.
Note: the following is not an exhaustive list but rather the thing I keep coming back to and/or regularly forget. For deeper explanations, see the list of resources at the foot of the article.
Option 1: Create a new repo in your Github account
This generates a new, empty repo (optionally initialised with a README).
Do this when you will be working on a new, dedicated project rather than contributing changes to a pre-existing one.
Option 2: Create repo from a “template repository” (owned by you or someone else)
This generates a new repo with the same directory structure and files as the template. It’s a good option for starting your own new, potentially long-lived project from a solid starting point.
Unlike a fork it does not include the entire commit history of the parent repository. Instead it starts with a single commit.
Option 3: Fork an existing repo (usually owned by someone else)
This generates a new repo which is a copy of another repo, including its commit history. Your commits will update your copy rather than the original repo.
Do this by clicking the Fork button in the header of a repository.
This is good for (often short-lived) collaboration on an existing repo. You can contribute code to someone else’s project, via PRs.
Alternatively you might want to keep the original remote available so you can pull in its future project updates, but reset the origin remote to your new/target repo.
git remote rename origin upstream
git remote add origin https://github.com/mygithubusername/mynewproject.git
git push origin master
git pull origin master
# in the future the original repo gets an updategit pull upstream master
The source repo is my fork of a project to which I want to contribute
Duplicating (also knows as “duplicate without forking”)
This is a special type of clone. I know this is an option, but it‘s not one I’m familiar with or have had call to use. I can refer to Duplicating a repository if need be.
Start locally from a blank slate
Although cloning is the easiest way to get started locally, ocassionally I start by coding from scratch instead.
mkdir myproject &&cd myproject
echo"# Welcome to My Project Repo">> README.md
git init
gitadd README.md
git commit -m"first commit"# go to Github and create an empty repo, if you haven’t already.# then add as a remotegit remote add origin https://github.com/mygitusername/myproject.git
# push up, passing -u to set the remote branch as the default upstream branch our local branch will track# this saves typing out ‘origin master’ repeatedly in future.git push -u origin master
Remotes
Remove a remote from your local settings:
git remote rm<name>
Rename a remote:
git remote rename oldname newname
Configuration
Configure your favourite editor to be used for commit messages:
git config --global core.editor "nano"
Use git st as a shortcut for git status (to stop me mistyping as “statsu”):
Stage and commit all changes in a single command (note: doesn’t work with new, untracked files):
git commit -am"fix: typo in heading"
Branches
Show all local branches:
git branch
Show all local and remote branches:
git branch -a
Show branches you last worked on (most recently commited to):
git branch --sort=-committerdate
Save current state to new branch but don’t yet switch to it (useful after committing to wrong branch):
git branch newbranchname
Create and switch to new branch (main or whatever branch you want to branch off):
git checkout -b mynewbranch
Note that if you branch off foo_feature then when creating a PR in GitHub for your changes in mynewbranch you can change the Base branch from the default of main to foo_feature. This specifies that you are requesting your changes be merged into foo_feature rather than main and makes the comparison of changes relative to foo_feature rather than main.
Switch to an existing branch:
git checkout branchname
Save typing by setting the upstream remote branch for your local branch:
# git branch -u remotename/branchnamegit branch -u fuzzylogic/v3
# now there’s no need to type origin mastergit pull
Delete local branch:
git branch -d name_of_branch
# need to force it because of some merge issue or similar?git branch -D name_of_branch
Save changes temporarily
stash is like a clipboard for git.
# Before changing branch, save changes you’re not ready to commitgit stash
# change branch, do other stuff. Then when return:git stash pop
Staying current and compatible
fetch remote branch and merge simultaneously:
git pull remotename branchname
# common use case is to update our local copy of mastergit pull origin master
# shorthand when a default upstream branch has been setgit pull
# an alternative is to update (fetch) which does not auto-merge, then 'reset' to the latest commit on the remote# https://stackoverflow.com/questions/55731891/effects-of-git-remote-update-origin-prune-on-local-changesgit checkout master
git remote update --prunegit reset --hard origin/master
Merge another branch (e.g. master) into current branch:
git merge otherbranch
# a common requirement is to merge in mastergit merge master
Rebasing
git rebase can be used as:
an alternative to merge; and
a means of tidying up our recent commits.
As an alternative to merge its main pro is that it leads to a more linear therefore easier-to-read history. Note however that it is potentially more disruptive therefore not right for every situation.
Say I’ve been working on a feature branch and I think it’s ready.
I might want to just tidy up my feature branch’s commits and can do this with an “interactive rebase”. This technique allows me to tidy my feature branch work to remove trivial, exploratory and generally less relevant commits so as to keep the commit history clean.
I might also want to bring in master to ensure synchronicity and compatibility. rebase sets the head of my feature branch to the head of master then adds my feature branch’s commits on top.
While it’s a good idea to rebasebefore making a PR, don’t use it after making a PR because from that point on the branch is public and rebasing a public branch can cause problems for collaborators on the branch. (The only exception to the previous rule is if you’re likely to be the only person working on the PR branch)
Rebuild your feature branch’s changes on top of master:
Force push your rebased branch (again, only when you’re unlikely to have/require collaborators on the PR):
git push --force origin myfeaturebranch
Tidy a feature branch before making a PR:
git checkout myfeaturebranch
git rebase -i master
# just tidy the last few (e.g. 3) commitsgit rebase -i HEAD~3
# this opens a text editor listing all commits due to be moved, e.g.:
pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3# change 'pick' to 'fixup' to condense commits, say if #2 was just a small fix to #1
pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3# alternatively if use 'squash', after saving it will open an editor# and prompt you to set a new commit message for the combined stuff.
pick 33d5b7a Message for commit #1
squash 9480b3d Message for commit #2
squash 5c67e61 Message for commit #3
Show commit history (most recent first; q to quit):
git log
# compact versiongit log --oneline# limit scope to commits on a branchgit log branchname
Check if your feature branch is trailing behind:
# show commits in master that are not yet in my feature branchgit log --oneline my-feature..master
# show commits on remote branch that are not yet in my local branchgit log --pretty='format:%h - %an: %s' new-homepage..origin/new-homepage
# show commits by me that included “heroku” and that changed file Gemfilegit log --author=Demaree --grep=heroku --oneline Gemfile
Show changes that occurred in the most recent commit or a given commit.
git show
# show changes in a given commit
git show 591672e
Review differences between staged changes and last commit:
gitdiff--cached
Review changes between a given version/commit and the latest:
gitdiff 591672e..master
Fixing Things
Discard all your as-yet uncommitted changes:
git restore .
Get your local feature branch out of a problem state by resetting to the state it is on the remote (e.g. at last push).
git reset --hard origin/my-branch
Undo all the changes in a given commit:
git revert 591672e
Alter the previous commit (change the message and/or include further updates):
# we are amending the previous commit rather than creating a new commit.# if file changes are staged, it amends previous commit to include those.# if there are no staged changes, it lets us amend the previous commit’s message only.git commit --amend
Move current branch tip backward to a given commit, reset the staging area to match, but leave the working directory alone:
git reset 591672e
# additionally reset the working directory to match the given commitgit reset --hard 591672e
See what the app/site was like (e.g. whether things worked or were broken) at a given previous commit, noting the following:
You’re now “detatched”, in that your computer’s HEAD is pointing at a commit rather than a branch.
You’re expected to merely review, not to make commits. Any commits you make would be “homeless”, since commits are supposed to go in branches. (However you could then branch off.)
git checkout 591672e
Return one or more files to the state they were in at a previous commit, without reverting everything else.
git checkout 3aa647dac9a8a251ca223a693d4c140fd3c1db11 /path/to/file.md /path/to/file2.erb
# if happy you then need to commit those changesgit commit
When git st reveals a list of staged files including lots of strange files you don’t want there mixed with others you do…
# add those you want to stay modified and stagedgitadd path/to/file-I-want-1.rb path/to/file-I-want-2.md
# this will clear all others out of the stagegit checkout .
Grab one or more commits from elsewhere and drop into your current branch:
git cherry-pick 591672e
# grab the last commit from a branch e.g. mastergit cherry-pick master
Fix a pull that went wrong / shouldn’t have been done:
git pull origin branchname
# whoops!git reflog
# shows a list of every thing you've# done in git, across all branches!# each one has an index HEAD@{index}# find the one before you broke everythinggit reset HEAD@{index}# magic time machine
If you are fixing something that was raised in a GitHub issue, link that issue in your fix PR’s sidebar under Linked Issues (rather than just mentioning it in the PR) and it will automatically close the issue when you merge.
These days, whenever I’m about to use a web font on a new site I generally find myself running a google search for the latest “definitive @font-face syntax” that covers all modern browser/device needs.
When buying web fonts from type foundries such as Fontsmith the foundries do tend to provide their own guidelines. However, I’m not convinced that these are sufficiently cross-platform compatible.
Recently I’ve been reading Flexible Typesetting by Tim Brown and in it he recommends Webfont Handbook by Bram Stein. That’s now next on my reading list, however in the meantime I found an excerpt on A List Apart which specifically covers the best modern @font-face syntax.
Based on Stein’s advice, here’s what I’m now using.