Snippets

Developers all share the experience of almost remembering some code they saw on Stackoverflow or blog post once. Sometimes even convincing themselves that it was used in another once of their projects (it wasn't). Scouring their search history for hours to no avail, only to be left in utter despair. Their once hot drink now sitting cold, undrinkable and staring at you... shaming you. That's happened to me far too many times and in a moment of strength I thought (extremely) loudly "THIS SHALL HAPPEN NO MORE!". So, I decided that I'll collate all of the ones I come back to again and again.

CSS

Responsive CSS grid

Taken from the infamous CSS Tricks post A Complete Guide to Grid. This serves as a good starting point for setting up your responsive grid.

.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* This is better for small screens, once min() is better supported */
/* grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr)); */
grid-gap: 1rem;
/* This is the standardized property now, but has slightly less support */
/* gap: 1rem */
}

Full width in restricted container

A useful snippet when you need to break out of some constraints in the page layout e.g a grid of images between some written content that fills the width of the page.

.full-width {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}

Max width in restricted container

Too much uniformity in a layout can create for a sub par experience, to create some moments of interest you can break out slightly, but not full width.

.not-full-but-bigger {
margin: auto calc(50% - 50vw);
width: 60vw;
transform: translateX(calc(50vw - 50%));
}

Line Clamp

An essential snippet of code to have in your arsenal. No more CSS hacks or over engineered Javascript solutions needed.

.line-clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}

A CSS only carousel, made possible by the introduction of scroll-snap. If you're wanting chevrons and click to slide functionality stick to a JS library, but for a mobile only carousel it works great.

.carousel {
display: flex;
width: 100%;
overflow-x: auto;
scroll-snap-type: x mandatory;
}
.carousel .item {
flex-shrink: 0;
width: 100%;
scroll-snap-align: center;
}
/* hide horizontal scroll bar Chrome/Safari */
.carousel::-webkit-scrollbar-track,
.carousel::-webkit-scrollbar,
.carousel::-webkit-scrollbar-thumb {
width: 0 !important;
}
.carousel {
/* Firefox */
scrollbar-width: none;
/* IE */
ms-overflow-style: none;
}

Background shorthand

Sometimes it can be a pain remembering the order of each background property (it gets me every time).

/* image, position, size and repeat */
body {
background: url(sweettexture.jpg) top center / 200px 200px no-repeat;
}

Multiple background images

Remember that the icon/image is declared after the colour. A good use case for this is image placeholders, for example you could have your companys logo above their brand grey.

.image-placeholder {
background: #eff0f2 url('./icons/logo.svg');
}
/* alternatively we can define colour and image seperately for the same effect */
.image-placeholder {
background-color: #eff0f2;
background-image: url('./icons/logo.svg');
}

Underline styles

Although improving, underlining text in CSS doesn't allow for many stylistic customisations (like stroke width or space from the text). The below solution creates a flexible underline which skips any descenders.

li {
// for the underline to "skip" the descenders
text-shadow: 1px 1px var(--primary-background), 1px -1px var(--primary-background),
-1px 1px var(--primary-background), -1px -1px var(--primary-background);
}
.current-menu-item {
position: relative;
&:before {
content: '';
position: absolute;
left: 0;
right: 0;
height: 1.5px;
bottom: 1px;
background: var(--primary-foreground);
z-index: -1;
}
}

Accessible icon text

To make buttons more accessible we need to let screen readers differentiate each buttons intention. By utilising the visually-hidden class name we can hide the text (keeping only the icon) and out buttons will be accessible.

.visually-hidden {
position: absolute;
overflow: hidden;
clip: rect(0 0 0 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
}

The snippet in a component

Using revert instead of underline

Say we have created a link with text-decoration: none and we want the underline to show on hover, instead of explicitly saying text-decoration: underline we can use revert so it falls back to the original "state".

a {
text-decoration: none;
&:hover {
text-decoration: revert;
}
}

Apply styles if within another component

This is a fairly tricky thing to understand because we normally understand css as only being able to look inward. However, with Styled components we can check whether a styled component exists within another component and change those styles accordingly.

const TextLink = styled.a`
/* Standard styles: */
color: blue;
text-decoration: none;
/* Styles when rendered inside a quote: */
${QuoteContent} & {
color: black;
text-decoration: revert;
}
`;

Taken from Josh Comeau's course css-for-js devs

The Stack layout

Utilising the "Lobotomised Owls" selector we can create more consistent spacing between elements on our pages. Essentially we are telling the browser to only apply margin top to those elements which have a previous sibling.

.stack {
--space: 1.5rem;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.stack > * {
margin-top: 0;
margin-bottom: 0;
}
.stack > * + * {
margin-top: var(--space);
}

references:

Nested Navigation Hover

Prevent the pesky issue where the nested navigation disappears before we can get to it! No need for any JS, take advantage of transition-delay. Taken from Josh Comeau’s CSS for JS developers course.

.dropdown {
opacity: 0;
transition: opacity 400ms;
transition-delay: 300ms;
}
.dropdown-wrapper:hover .dropdown {
opacity: 1;
transition: opacity 100ms;
transition-delay: 0ms;
}

Animation Fill Mode both

I've always used forwards in the past because I never thought to explore the other options. As it turns out there is a both option, which means no more adding default styles before the keyframes animation!

.box {
animation: slide-in 1000ms ease-out both;
animation-delay: 500ms;
}

Git

Delete local branches

When you have merged and deleted a branch on github this command will delete the local branches that dont exist remotely.

git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d

Add something to .gitignore

Refreshes the tracking of your files. Super useful for adding new things to your .gitignore file.

git rm -r --cached .

Git stash

An underrated command in my opinion. Need to quickly switch branch to do something but don't want to commit your changes on the current branch just yet? Git stash is perfect for this.

# for when it's too hard to think of a message
git stash
# to make it clearer what each stash is
git stash save "optional message for yourself"
# apply the latest stash (I tend to use this the most)
git stash apply stash@{0}
# view a list of your stashes
git stash list

Gulp

Wordpress Setup

var { src, dest, series, watch } = require('gulp');
var browserSync = require('browser-sync').create();
var sass = require('gulp-sass');
const rename = require('gulp-rename');
let scss = () => {
return src('./sass/main.scss')
.pipe(sass())
.pipe(rename('style.css'))
.pipe(dest('./', { overwrite: true }));
};
let editorStyles = () => {
return src('./sass/editor.scss')
.pipe(sass())
.pipe(rename('gutenberg-editor-styles.css'))
.pipe(dest('./styles', { overwrite: true }));
};
let server = () => {
return browserSync.init({
proxy: '<http://localhost:8888>',
});
};
let reload = (done) => {
browserSync.reload();
done();
};
watch(['**/*.scss'], series(scss, editorStyles, reload));
watch(['**/*.js', '**/*.php'], reload);
exports.scss = scss;
exports.server = server;
exports.default = series(scss, editorStyles, server);

HTML

Details element for HTML accordion

An HTML first "accordian". Forget about using Javascript and make it simple for yourself by utilising semantic HTML. You can also style the default arrow by targeting the :marker pseudo element.

<details>
<summary>What?</summary>
Stay Home Stay Safe!
</details>
<a
href="<https://twitter.com/CollierAdam>"
target="_blank"
rel="noopener noreferrer"
>
DM me on Twitter.
</a>

Javascript

Chunk an array

Because sometime you just need to chunk some stuff.

const chunk = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);

Parsing JSON

An interesting snippet I came across on The Cost of Javascript. I'll be using this trick the next time I'm parsing big chunks of JSON.

const data = { foo: 42, bar: 1337 }; // 🐌
const data = JSON.parse('{"foo":42,"bar":1337}'); // 🚀

Flatten an array

Intoduced in ES6 we can now easily flatten multi dimensional arrays. Gone are the days of having to create our own solution (taken from stackoverflow).

// This method accepts one argument to choose the depth of the flattening
const multiDimensionalArray = [
[1, 2],
[3, 4],
[5, 6],
];
const flattenedArray = multiDimensionalArray.flat(); // [1, 2, 3, 4, 5, 6]

Remove a property from an Object

A pretty neat solution, by leveraging ES6 Object destructuring assignment we can immutably remove properties.

const item = {
id: 1,
price: 50,
image: 'item.jpeg',
};
const { id, ...item2 } = item;
// now item 2 doesnt have an id property
console.log(item2);

Optional Chaining

More than anything it's going to save you some heaps of typing, it's a neat solution for something that has plagued developers sanity for many a year.

// Instead of something like
const city = user && user.address && user.address.city;
// We can do
const city = user?.address?.city;

\$(document).ready in vanilla

No other excuse, I just forget what this is all the time.

document.addEventListener('DOMContentLoaded', function () {
// Handler when the DOM is fully loaded
});

Get a single value from an array of objects via id

Simple, elegant and it will save you a bunch of time. No more mapping or filtering involved.

myArray.find((x) => x.id === '45').author;

Duplicate child elements

// Child elements are usually a HTMLCollection (which we can't map over)
// So we need to convert it to an array first
Array.from(element.children).map((child) => {
// by setting to true we grab the whole subtree too
let clonedChild = child.cloneNode(true);
element.appendChild(clonedChild);
});

Decode HTML entities

Sometimes when using API's or text from the document special characters are encoded into HTML entities. We can take advantage of the textarea tag to auto decode these strings for us.

export const decodeHtmlEntities = (html) => {
var textArea = document.createElement('textarea');
textArea.innerHTML = html;
let decodedHTML = textArea.value;
textArea.remove();
return decodedHTML;
};

Node Modules

Check size of all Node Modules

Find all of the Node module directories, check how big each one is and the total amount of space it takes up (it can be a surprising amount of space)

find . -name "node_modules" -type d -prune -print | xargs du -chs

Delete all Node Modules

Delete all of your node modules from your mac and sit there, shocked at the number of modules you've just erased.

find . -name 'node_modules' -type d -prune -print -exec rm -rf '{}' \\;

taken from Go Make Things

NPM

Interactively update packages

npx npm-check -u

Yalc (local component package workflow)

Yalc is a great little tool similar to the likes of yarn link and npm link. What it allows us to do is use our local component packages as dependencies of other projects. I prefer Yalc because it physically changes your package.json so you are always aware of which component package you're using and where from.

Install Yalc globally:

# install globally
npm i -g yalc
# publish package locally
yalc publish
# publish and update all projects using that yalc store
yalc publish --push
# add your local package as a dependency
yalc add my-package
# (This will change/add the package location in your package.json)
# remove it from / revert your package.json
yalc remove my-package

NVM

NVM (Node Version Manager) is a tool which helps you easily manage your Node versions. Without NVM managing node versions locally is a real pain, install this once and breathe a sigh of relief.

Install the latest version of node

Your Node install looking a little outdated? easily install the latest stable version of node.

nvm install node

List versions of node installed

Check what versions of Node you have installed, if you have a new one installed you can switch it there and then

nvm list

Specify a node version to use

If you need to use a specific version of Node for a project declare it in the command.

nvm install 6.14.4 # or 10.10.0, 8.9.1, etc

Use current node version in all terminals

Are new terminal sessions using different versions of Node? Set your default version which will be used across everything.

nvm alias default node

Oh My ZSH

The Oh My ZSH framework for managing your ZSH configuration and comes bundled with thousands of helpful functions, plugins and themes. It's a real game changer.

Install ZSH

Taken from the github README.

sh -c "$(curl -fsSL <https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh>)"

Add the Geometry theme

This is the theme that I use because it's super simple and as customisable as you want. Personally I like it for it's unobtrusive design.

# lets cd into our custom themes directory
cd ~/.oh-my-zsh/custom/themes
# clone the theme
git clone <https://github.com/geometry-zsh/geometry>

To activate the theme in your .zshrc file:

ZSH_THEME="geometry/geometry"

Add Custom Plugins

Oh My ZSH can be a real time by utilising the community driven plugin ecosystem. A few of the plugins I like to use:

To add these plugins to your Oh My ZSH install:

# let's cd into our custom plugins directory
cd ~/.oh-my-zsh/custom/plugins
# clone the zsh-syntax-highlighting plugin
git clone <https://github.com/zsh-users/zsh-syntax-highlighting.git> ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
# clone the zsh-nvm plugin
git clone <https://github.com/lukechilds/zsh-nvm> ~/.oh-my-zsh/custom/plugins/zsh-nvm
# clone the zsh-autosuggestions plugin
git clone <https://github.com/zsh-users/zsh-autosuggestions> ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

then in our .zshrc file lets initialise the plugins

plugins=(
git
zsh-syntax-highlighting
zsh-autosuggestions
zsh-nvm
)

Prevent the Percentage Sign issue in Hyper

Annoyingly there is a percentage sign issue in Hyper, here's how to fix it. Let's add the below to the bottom of our .zshrc file.

# prevent percentage prompt when first open
unsetopt PROMPT_SP

Amend the Terminal Title

It's always a nice touch to have your personal terminal title showing.

cd ~/.oh-my-zsh/custom/themes/geometry
# open vs code
code .
# find this line in geomatry.zsh
geometry::clear_title() { print -n '\\e]0;%~\\a'; }
# and amend to
geometry::clear_title() { print -n "\\e]0;Adam's Terminal\\a"; }

PHP

Import SVG inline

A nice easy way to grab icons anywhere in your site.

<?php include("icons/my-icon.svg"); ?>
// getting an icon from a parent directory
<?php include __DIR__ . '/../icons/facebook.svg'; ?>

Enqueue a script

A method to functionally add scripts to your wordpress projects footer.

wp_enqueue_script(
'lazysizes',
get_template_directory_uri() . '/js/lazysizes.min.js'
);

Get template part

Reuse some templated PHP content you have created

<?php get_template_part('template_parts/griditem'); ?>

Use variables in template parts

Sometimes you need to pass variables down into a template part, a similar thinking pattern to react and props.

// you can use any value including objects.
set_query_var( 'var_name_to_be_used_later', 'Value to be retrieved later' );
// in the template part
$passedVariable = get_query_var('var_name_to_be_used_later');

Name all blocks on the page

If you have ever done any Gutenberg block development for Wordpress this is an essential snippet.

// lets grab all of the blocks from the post content
$blocks = parse_blocks($post->post_content);
// and lets print it out
var_dump($blocks);

React

Add Context to a site

Taken from @kentcdodds great blog post How to use React Context effectively. A good base for setting up global state in any React application.

// context.js
import React from 'react';
const StateContext = React.createContext();
const DispatchContext = React.createContext();
// handle the reducer
const stateReducer = (state, action) => {
switch (action.type) {
// an example action
case 'increment': {
return { count: state.count + 1 };
}
default: {
throw new Error(`Unhandled action type: ${action.type}`);
}
}
};
const initialState = {
count: 0,
};
function StateProvider({ children }) {
const [state, dispatch] = React.useReducer(stateReducer, initialState);
return (
<StateContext.Provider value={state}>
<DispatchContext.Provider value={dispatch}>
{children}
</DispatchContext.Provider>
</StateContext.Provider>
);
}
function useAppState() {
const context = React.useContext(StateContext);
if (context === undefined) {
throw new Error('useAppState must be used within a StateProvider');
}
return context;
}
function useAppDispatch() {
const context = React.useContext(DispatchContext);
if (context === undefined) {
throw new Error('useAppDispatch must be used within a StateProvider');
}
return context;
}
function useContext() {
return [useAppState(), useAppDispatch()];
}
export { StateProvider, useContext };
// Any react file
import { useContext } from "../../context"
// use destructuring to make state and dispatch accessible
// count in this case is destructured from the state
const [{ count }, dispatch] = useContext()
// you could just do
const [state, dispatch] = useContext()
// then we can dispatch
dispatch({ type: "count" })
// or use the state
<div>{count}</div>

Immutability in React

React in general tends to frown upon mutating values, especially when updating state. So here are a few methods I like to use to update immutably. Many more can be found in Redux's post Immutable Update Patterns

Update an object

The spread operator comes into it's essense here, making it easy to update an object.

// state = {
// clicks: 0,
// count: 0
// }
return {
...state,
clicks: state.clicks + 1,
count: state.count - 1,
};

Add an item to an array

We can spread the current array values to the beginning of our new array, followed by our extra value.

const newItem = 'foo';
// a new array
return [
...state, // explode the old state first
newItem, // then add the new item at the end
];

Prepend an item to an array

Taking advantage of ES6 spread operators we can add an item to an array immutably.

const newItem = 'foo';
// a new array
return [
newItem, // add the new item first
...state, // then explode the old state at the end
];

Update an item in an array by index

Map is perfect for returning a new array, in this case we can update an item by index.

return state.map((item, index) => {
// Replace the item at index 2
if (index === 2) {
return 3;
}
// Leave every other item unchanged
return item;
});

useMediaQuery Custom Hook

Conditionally render components based on the browser size rather than rendering and hiding the components with CSS. Taken from @cassidoo's post Building a custom React media query hook for more responsive apps

import { useState, useEffect } from 'react';
export function useMediaQuery(query) {
const [matches, setMatches] = useState(false);
useEffect(() => {
const media = window.matchMedia(query);
if (media.matches !== matches) {
setMatches(media.matches);
}
const listener = () => {
setMatches(media.matches);
};
media.addListener(listener);
return () => media.removeListener(listener);
}, [matches, query]);
return matches;
}
// how to use it
function Page() {
let isPageWide = useMediaQuery('(min-width: 800px)');
return (
<>
{isPageWide && <UnnecessarySidebar />}
<ImportantContent />
</>
);
}

Pass props to props.children

A very basic example of how we can pass props down to props.children. If you're wanting to abstract away some logic, make your code more readable or make it easy to switch out components, this is a great solution.

// inside our component we add the props we want as arguments for props.children
const Blocks = ({ allBlocks, children }) =>
allBlocks.map((block, index) => <div>{children(block, index)}</div>);
// then we can access those arguments via a function
<Blocks allBlocks={state.allBlocks}>
{(block, index) => {
return <DynamicBlock block={block} index={index} />;
}}
</Blocks>;

Terminal

Tree command

Very common to find in Github README's the tree command makes it super easy to get directory structures in an easy to read format.

# Get the tree of the first directory level
tree -v -L 1
# Ignore node_modules and grab the tree two directory levels down
tree -I 'node_modules' -v -L 2

Wordpress

Install Wordpress locally

Wordpress's officially documentation is pretty good for this. (I do wish there was a quick and easy CLI solution for this).

Setting up Virtual Hosts

Go to MAMP > Preferences > Ports and set Apache Port to be 80

Open the hosts file in VS Code:

cd /etc
code hosts

Add the urls you want to use:

127.0.0.1 your-site.test

(you may need to sudo save, VS Code makes this easy for you)

Add the virtual hosts to the end of /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf:

<VirtualHost *:80>
DocumentRoot "/Applications/MAMP/htdocs" ServerName localhost
</VirtualHost>
<VirtualHost *:80>
ServerName your-site.test DocumentRoot "/Users/username/Sites/directory"
</VirtualHost>

(notice how we are re-setting up the main localhost first)

And make sure the NameVirtualHost is set to:

NameVirtualHost *:80

Then in /Applications/MAMP/conf/apache/httpd.conf

Uncomment this line:

# Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf

Find this line:

<Directory />
Options Indexes FollowSymLinks
AllowOverride None
</Directory>

and change it from None to All:

Lastly find these two instances:

Listen 8888
ServerName localhost:8888

and change them to:

Listen 80
ServerName localhost:80

and then it should work!

If you find your site feels a little sluggish compared to using localhost you can speed up the lookup time by adding it as an alias. So in /etc/hosts:

127.0.0.1 localhost your-site.test

Altering Site Address and Wordpress Address

When switching to virtual hosts from a localhost setup the site address and wordpress address general settings were causing some issues. You may find you can't access the admin, because its setup for a different url, so here's how to fix that.

Open your projects wp-config.php file and after the “define” statements (just before the comment line that says “That’s all, stop editing!”), insert a new line:

define('RELOCATE',true)

Now if your site is at http://www.yourdomainname.com your need to go to http://www.yourdomainname.com/wp-login.php (notice how we are manually accessing the wp-login.php file)

Login in as normal and make the changes in General > Settings

Make sure to remove define('RELOCATE',true) after successfully changing the urls.

Do you know a great snippet which you think should be added to this page? Send it over and I'll take a look!

Table of Contents

Like the content I'm creating? Show some love and:

Buy me a Coffee